diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..aecf25037 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* -crlf diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f12a0f00..424b01c4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,9 @@ cmake_minimum_required(VERSION 2.8) +include(CMakePrintHelpers) project(stellabellum C CXX) -if (WIN32) - set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/win32") -elseif (UNIX) - set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux") -endif () +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux") set(SWG_ROOT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(SWG_ENGINE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/engine) @@ -16,8 +13,6 @@ set(SWG_GAME_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/game) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) -include_directories(/usr/include/i386-linux-gnu) - find_package(BISON REQUIRED) find_package(FLEX REQUIRED) find_package(JNI REQUIRED) @@ -28,101 +23,83 @@ find_package(Perl REQUIRED) find_package(Threads) find_package(ZLIB REQUIRED) find_package(CURL REQUIRED) +find_package(Curses REQUIRED) # c++17 yeah! set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -# shame on you cmake for auto-setting optimization flags! -set(CMAKE_CXX_FLAGS_DEBUG "") -set(CMAKE_CXX_FLAGS_RELEASE "") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "") -set(CMAKE_CXX_FLAGS_MINSIZEREL "") - -# I'll be honest, win32 is probably very very broken and won't build - it will need worked on so that MSVC uses -# the vs2013+ STL instead of stlport, and probably will thus need removal/modification/addition of TONS of the ifdef blocks for WIN32 -if (WIN32) - find_package(Iconv REQUIRED) - - # Dont-Build-PDB RELEASE build use the following (by either commenting---uncommenting the line as needed) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:libc.lib /SAFESEH:NO") - - # Do-Build-PDB RELEASE build use the following (by either commenting---uncommenting the line as needed) - #set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DWIN32 -Dwin32 -DUDP_LIBRARY -DDEBUG_LEVEL=0 \ - # -DPRODUCTION=1 /Oi /Ot /Oy /O2 /GF /Gy /Zi /MT -D_USE_32BIT_TIME_T=1 -D_MBCS \ - # -DPLATFORM_BASE_SINGLE_THREAD -D_CRT_SECURE_NO_WARNINGS /MP /wd4244 /wd4996 /wd4018 /wd4351 \ - # /Zc:wchar_t- /Ob1 /FC") - - # Dont-Build-PDB RELEASE build use the following (by either commenting---uncommenting the line as needed) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DWIN32 -Dwin32 -DUDP_LIBRARY -DDEBUG_LEVEL=0 -DPRODUCTION=1 \ - /Oi /Ot /Oy /O2 /GF /Gy /MT -D_USE_32BIT_TIME_T=1 -D_MBCS -DPLATFORM_BASE_SINGLE_THREAD -D_CRT_SECURE_NO_WARNINGS \ - /MP /wd4244 /wd4996 /wd4018 /wd4351 /Zc:wchar_t- /Ob1 /FC") - - # Standard DEBUG build use the following (by either commenting---uncommenting the line as needed) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DWIN32 -Dwin32 -D_DEBUG -DUDP_LIBRARY -DDEBUG_LEVEL=2 -DPRODUCTION=0 /MTd \ - -D_USE_32BIT_TIME_T=1 -D_MBCS -DPLATFORM_BASE_SINGLE_THREAD -D_CRT_SECURE_NO_WARNINGS /MP /wd4244 /wd4996 /wd4018 /wd4351 \ - /Zc:wchar_t- /Ob1 /FC") -elseif (UNIX) - find_package(Curses REQUIRED) - - # linker flags - if (${CMAKE_BUILD_TYPE} STREQUAL "RELWITHDEBINFO" OR ${CMAKE_BUILD_TYPE} STREQUAL "MINSIZEREL") - set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-z,norelro,-O3,--sort-common,--as-needed,--relax,-z,combreloc,-z,global,--no-omagic") - set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,norelro,-O3,--sort-common,--as-needed,--relax,-z,combreloc,-z,global,--no-omagic") - else () - set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-z,norelro,-O3,--sort-common,--as-needed,--relax,-z,combreloc,-z,global,--no-omagic,-x,-s") - set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,norelro,-O3,--sort-common,--as-needed,--relax,-z,combreloc,-z,global,--no-omagic,-x,-s") - endif () - - # don't put anything too crazy in debug...and any common flags go into CMAKE_CXX_FLAGS - set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DDEBUG_LEVEL=2 -DPRODUCTION=0 -O0 -g3") - - # release specific cflags - optimizations beyond the default for both types is mostly just -O flags - set(CMAKE_CXX_FLAGS_RELEASE "-DDEBUG_LEVEL=0 -DPRODUCTION=1") - - # we use fewer, if any, crazy optimizations for profile generation, and likewise release flags for the minsizerel - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE}") - set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_RELEASE}") - - # Ofast doesn't work with gcc builds - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast \ - -fno-threadsafe-statics -fslp-vectorize \ - -fno-stack-protector -fstrict-enums -finline-hint-functions \ - -fno-coverage-mapping -fno-spell-checking \ - -mno-retpoline") - - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb") - - # RELWITHDEBINFO is used for building bins that produce profdata files - # we only need the basics of our heavy optimizations here, i think - that and one of these flags - # breaks JNI when we profile - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS} -Ofast -finline-hint-functions -fprofile-instr-generate") - - # MINSIZEREL is used for profiled, flto builds - set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_RELEASE} -flto -fwhole-program-vtables") - elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - # O3 and Ofast include one or more flags that cause java to crash when using gcc6 - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -fno-signed-zeros -freciprocal-math -fno-unroll-loops -fno-tree-loop-optimize -fno-plt") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -Og") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og") - elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") - endif () - - # our "always on" flags - build by default for the system we're on but include all instruction sets - set(CMAKE_CXX_FLAGS "-m32 -pipe -march=native -mtune=native \ - -Wformat -Wno-overloaded-virtual -Wno-missing-braces -Wno-format \ - -Wno-write-strings -Wno-unknown-pragmas \ - -Wno-uninitialized -Wno-reorder -Wno-tautological-constant-out-of-range-compare -Wno-stringop-overflow -Wno-address-of-packed-member") - - add_definitions(-DLINUX -D_REENTRANT -Dlinux -D_USING_STL -D_GNU_SOURCE -D_XOPEN_SOURCE=500 -U_FORTIFY_SOURCE) - - # this is so some profile specific stuff is turned on in the code - if (${CMAKE_BUILD_TYPE} STREQUAL "RELWITHDEBINFO") - add_definitions(-DENABLE_PROFILING) - endif () +# Global CMake CXX Flags +# our "always on" flags - build by default for the system we're on but include all instruction sets +set(CMAKE_CXX_FLAGS "\ + ${CMAKE_CXX_FLAGS} \ + -pipe \ + -march=native \ + -maes \ + -Wformat \ + -Wno-overloaded-virtual \ + -Wno-missing-braces \ + -Wno-format \ + -Wno-write-strings \ + -Wno-unknown-pragmas \ + -Wno-uninitialized \ + -Wno-reorder \ + -Wno-tautological-constant-out-of-range-compare \ + -Wno-address-of-packed-member \ +") + +string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) + +# Global Linker flags +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,norelro,-O3,--sort-common,--as-needed,--relax,-z,combreloc,-z,global,--no-omagic") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,norelro,-O3,--sort-common,--as-needed,--relax,-z,combreloc,-z,global,--no-omagic") + +# Add on flags to strip debug symbols if RELEASE or MINSIZEREL +if (${CMAKE_BUILD_TYPE} STREQUAL "RELEASE" OR ${CMAKE_BUILD_TYPE} STREQUAL "MINSIZEREL") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS},-x,-s") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},-x,-s") +endif () + +# Compiler specific settings. +# GNU - These are for GCC 7.5 (the version on the 3.0.x VM) +# Clang - These are for CLang 11 (current version as of Jan-2022), but it is not installed on the 3.0.x VM +if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-stringop-overflow") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG -DDEBUG_LEVEL=2 -DPRODUCTION=0 -pg -ggdb") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG_LEVEL=0 -DPRODUCTION=0 -pg -ggdb -no-pie") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -DDEBUG_LEVEL=0 -DPRODUCTION=1 -no-pie -flto -fwhole-program-vtables") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDEBUG_LEVEL=0 -DPRODUCTION=1") +elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "CLang") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG -DDEBUG_LEVEL=2 -DPRODUCTION=0 -pg -ggdb -g -fprofile-instr-generate -fcoverage-mapping") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG_LEVEL=0 -DPRODUCTION=0 -Ofast -pg -ggdb") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -DDEBUG_LEVEL=0 -DPRODUCTION=1 -no-pie -flto -fwhole-program-vtables") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDEBUG_LEVEL=0 -DPRODUCTION=1 -Ofast") +endif() + +# Remove whitespace from flags +string(REGEX REPLACE "[ \t\r\n]+" " " CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) +string(REGEX REPLACE "[ \t\r\n]+" " " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}) +string(REGEX REPLACE "[ \t\r\n]+" " " CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL}) +string(REGEX REPLACE "[ \t\r\n]+" " " CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) + +message("Using Compiler: ${CMAKE_CXX_COMPILER_ID}") + +add_definitions(-DLINUX -D_REENTRANT -Dlinux -D_USING_STL -D_GNU_SOURCE -D_XOPEN_SOURCE=500 -U_FORTIFY_SOURCE) + +# this is so some profile specific stuff is turned on in the code +if (${CMAKE_BUILD_TYPE} STREQUAL "RELWITHDEBINFO" OR ${CMAKE_BUILD_TYPE} STREQUAL "DEBUG") + add_definitions(-DENABLE_PROFILING) +endif () + +if (${CMAKE_BUILD_TYPE} STREQUAL "DEBUG") + cmake_print_variables(CMAKE_CXX_FLAGS_DEBUG) +elseif (${CMAKE_BUILD_TYPE} STREQUAL "RELWITHDEBINFO") + cmake_print_variables(CMAKE_CXX_FLAGS_RELWITHDEBINFO) +elseif (${CMAKE_BUILD_TYPE} STREQUAL "MINSIZEREL") + cmake_print_variables(CMAKE_CXX_FLAGS_MINSIZEREL) +elseif (${CMAKE_BUILD_TYPE} STREQUAL "RELEASE") + cmake_print_variables(CMAKE_CXX_FLAGS_RELEASE) endif () add_subdirectory(external) diff --git a/README.md b/README.md index ac75b13cb..e4ac3e1c0 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,15 @@ This is the main server code for SWGSource 1.2 as originally forked from the https://bitbucket.org/stellabellumswg/ repository. Please see that repository for original publication and alteration credit. # Works in progress -* 64-bit-types - fully 64 bit version that builds and runs completely. +* 64-bit-types - fully 64 bit version (presently in testing - 11/12/2021) (Special thanks to Apathy for his help in making a 64 bit version happen!) # Building -For local testing, and non-live builds set MODE=Release or MODE=Debug in the build.properties file in swg-main. +## Clang Versions + +**Important**: For versions of clang <= 4 you'll probably have to remove/omit a deprecated CFLAG or two from the CMakelists.txt file + +Only use the Debug and Release targets unless you want to work on 64 bit (MODE=RELWITHDEBINFO). For local testing, and non-live builds set MODE=Release or MODE=debug in build_linux.sh. For production, user facing builds, set MODE=MINSIZEREL for profile built, heavily optimized versions of the binaries. diff --git a/build.xml b/build.xml index e0c32d6cb..e1765850d 100755 --- a/build.xml +++ b/build.xml @@ -52,6 +52,13 @@ Architecture is ${arch} + + + + + + + Compiling as ${bits}-bit application. @@ -83,7 +90,11 @@ - + + + + + @@ -99,6 +110,19 @@ + + + + + + + + + + + + + diff --git a/cmake/linux/FindOracle.cmake b/cmake/linux/FindOracle.cmake index a4d14c4b0..d6074ead5 100644 --- a/cmake/linux/FindOracle.cmake +++ b/cmake/linux/FindOracle.cmake @@ -22,7 +22,6 @@ # ############################################################################### - # If ORACLE_HOME not defined, assume Oracle libraries not available if(DEFINED ENV{ORACLE_HOME}) @@ -31,17 +30,15 @@ if(DEFINED ENV{ORACLE_HOME}) find_path(ORACLE_INCLUDE_DIR NAMES oci.h PATHS - /usr/include/oracle/18.3/client + ${CMAKE_ORACLE_INCLUDE_DIR} ${ORACLE_HOME}/rdbms/public ${ORACLE_HOME}/include ${ORACLE_HOME}/sdk/include # Oracle SDK ${ORACLE_HOME}/OCI/include) # Oracle XE on Windows - set(ORACLE_OCI_NAMES clntsh libclntsh oci) - set(ORACLE_NNZ_NAMES nnz18 libnnz18 ociw32) - set(ORACLE_OCCI_NAMES libocci occi) - + set(ORACLE_NNZ_NAMES libnnz18 nnz18 libnnz21 nnz21 ociw32) + set(ORACLE_OCCI_NAMES libocci occi oraocci10 oraocci11) set(ORACLE_LIB_DIR ${ORACLE_HOME}/lib @@ -49,24 +46,19 @@ if(DEFINED ENV{ORACLE_HOME}) ${ORACLE_HOME}/sdk/lib/msvc ${ORACLE_HOME}/OCI/lib/msvc) # Oracle XE on Windows - find_library(ORACLE_OCI_LIBRARY NAMES ${ORACLE_OCI_NAMES} PATHS ${ORACLE_LIB_DIR}) find_library(ORACLE_OCCI_LIBRARY NAMES ${ORACLE_OCCI_NAMES} PATHS ${ORACLE_LIB_DIR}) find_library(ORACLE_NNZ_LIBRARY NAMES ${ORACLE_NNZ_NAMES} PATHS ${ORACLE_LIB_DIR}) - set(ORACLE_LIBRARY ${ORACLE_OCI_LIBRARY} ${ORACLE_OCCI_LIBRARY} ${ORACLE_NNZ_LIBRARY}) - if(APPLE) set(ORACLE_OCIEI_NAMES libociei ociei) - find_library(ORACLE_OCIEI_LIBRARY NAMES libociei ociei PATHS ${ORACLE_LIB_DIR}) - if(ORACLE_OCIEI_LIBRARY) set(ORACLE_LIBRARY ${ORACLE_LIBRARY} ${ORACLE_OCIEI_LIBRARY}) else(ORACLE_OCIEI_LIBRARY) @@ -75,18 +67,13 @@ if(DEFINED ENV{ORACLE_HOME}) endif() endif() - set(ORACLE_LIBRARIES ${ORACLE_LIBRARY}) - endif(DEFINED ENV{ORACLE_HOME}) - # Handle the QUIETLY and REQUIRED arguments and set ORACLE_FOUND to TRUE # if all listed variables are TRUE include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(ORACLE DEFAULT_MSG ORACLE_LIBRARY ORACLE_INCLUDE_DIR) - - -mark_as_advanced(ORACLE_INCLUDE_DIR ORACLE_LIBRARY) +find_package_handle_standard_args(Oracle DEFAULT_MSG ORACLE_LIBRARY ORACLE_INCLUDE_DIR) +mark_as_advanced(ORACLE_INCLUDE_DIR ORACLE_LIBRARY) \ No newline at end of file diff --git a/engine/client/application/Miff/src/lex_yy.c b/engine/client/application/Miff/src/lex_yy.c index df6de76d9..bdf2e3fa8 100644 --- a/engine/client/application/Miff/src/lex_yy.c +++ b/engine/client/application/Miff/src/lex_yy.c @@ -49,11 +49,11 @@ typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; +typedef short short int flex_int16_t; +typedef short int flex_int32_t; typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; +typedef unsigned short short int flex_uint16_t; +typedef unsigned short int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN diff --git a/engine/client/application/Miff/src/linux/miff.cpp b/engine/client/application/Miff/src/linux/miff.cpp index 6927490e8..454f3e329 100755 --- a/engine/client/application/Miff/src/linux/miff.cpp +++ b/engine/client/application/Miff/src/linux/miff.cpp @@ -275,7 +275,7 @@ static void callbackFunction(void) { if (!outfileHandler->writeBuffer()) { - fprintf(stderr, "MIFF: failed to write output file \"%s\"\n", local_outFileName); + fprintf(stderr, "FAILURE: failed to write output file \"%s\"\n", local_outFileName); local_errorFlag = ERR_WRITEERROR; } } diff --git a/engine/client/application/Miff/src/linux/parser.lex b/engine/client/application/Miff/src/linux/parser.lex index f80c2c9b2..2d5192c6b 100644 --- a/engine/client/application/Miff/src/linux/parser.lex +++ b/engine/client/application/Miff/src/linux/parser.lex @@ -326,8 +326,11 @@ EXP (e|E)(\+|-)? /* do a count on bracket matching... */ if (0 == count_brace()) { - if (!initialCompile && !globalErrorFlag) - MIFFMessage("mIFF successfully compiled!\n", 0); + if (!initialCompile && !globalErrorFlag) { + char myString[256]; + sprintf(myString, "mIFF (SUCCESS): compiled \"%s\"", inFileName); + MIFFMessage(myString, 0); + } } yyterminate(); /* tell yyparse() it's time to quit! DO NOT comment or delete this line! */ diff --git a/engine/client/application/Miff/src/linux/parser.yac b/engine/client/application/Miff/src/linux/parser.yac index 25feaf7e8..647b4e766 100644 --- a/engine/client/application/Miff/src/linux/parser.yac +++ b/engine/client/application/Miff/src/linux/parser.yac @@ -29,6 +29,7 @@ #include /* for wide character (16bit) strings */ #include /* for strtoupper and strtolower */ #include +#include /* for standard types - i.e. uint32_t */ /*----------------------------------------------------------------** ** debug options, turn these on to TEST ONLY! don't leave these ** @@ -66,11 +67,11 @@ void checkPragmas(void); void includeBinary(char *fname); -void write32(long i32); -void write16(short i16); +void write32(int32_t i32); +void write16(int16_t i16); void write8(char i8); -void writeU32(unsigned long ui32); -void writeU16(unsigned short ui16); +void writeU32(uint32_t ui32); +void writeU16(uint16_t ui16); void writeU8(unsigned char u8); void writeDouble(double d); void writeFloat(float f); @@ -627,14 +628,14 @@ void checkArgs(void) /*----------------------------** ** Write to FILE functions... ** **----------------------------*/ -void write32(long i32) +void write32(int32_t i32) { - MIFFinsertChunkData(&i32, sizeof(long)); + MIFFinsertChunkData(&i32, sizeof(int32_t)); } -void write16(short i16) +void write16(int16_t i16) { - MIFFinsertChunkData(&i16, sizeof(short)); + MIFFinsertChunkData(&i16, sizeof(int16_t)); } void write8(char i8) @@ -642,14 +643,14 @@ void write8(char i8) MIFFinsertChunkData(&i8, sizeof(char)); } -void writeU32(unsigned long ui32) +void writeU32(uint32_t ui32) { - MIFFinsertChunkData(&ui32, sizeof(long)); + MIFFinsertChunkData(&ui32, sizeof(uint32_t)); } -void writeU16(unsigned short ui16) +void writeU16(uint16_t ui16) { - MIFFinsertChunkData(&ui16, sizeof(short)); + MIFFinsertChunkData(&ui16, sizeof(uint16_t)); } void writeU8(unsigned char ui8) diff --git a/engine/client/application/Miff/src/parser.c b/engine/client/application/Miff/src/parser.c index 22fdd21e4..90a23d7c2 100644 --- a/engine/client/application/Miff/src/parser.c +++ b/engine/client/application/Miff/src/parser.c @@ -134,11 +134,11 @@ void checkPragmas(void); void includeBinary(char *fname); -void write32(long i32); -void write16(short i16); +void write32(int32_t i32); +void write16(int16_t i16); void write8(char i8); -void writeU32(unsigned long ui32); -void writeU16(unsigned short ui16); +void writeU32(uint32_t ui32); +void writeU16(uint16_t ui16); void writeU8(unsigned char u8); void writeDouble(double d); void writeFloat(float f); @@ -2829,14 +2829,14 @@ void checkArgs(void) /*----------------------------** ** Write to FILE functions... ** **----------------------------*/ -void write32(long i32) +void write32(int32_t i32) { - MIFFinsertChunkData(&i32, sizeof(long)); + MIFFinsertChunkData(&i32, sizeof(int32_t)); } -void write16(short i16) +void write16(int16_t i16) { - MIFFinsertChunkData(&i16, sizeof(short)); + MIFFinsertChunkData(&i16, sizeof(int16_t)); } void write8(char i8) @@ -2844,14 +2844,14 @@ void write8(char i8) MIFFinsertChunkData(&i8, sizeof(char)); } -void writeU32(unsigned long ui32) +void writeU32(uint32_t ui32) { - MIFFinsertChunkData(&ui32, sizeof(long)); + MIFFinsertChunkData(&ui32, sizeof(uint32_t)); } -void writeU16(unsigned short ui16) +void writeU16(uint16_t ui16) { - MIFFinsertChunkData(&ui16, sizeof(short)); + MIFFinsertChunkData(&ui16, sizeof(uint16_t)); } void writeU8(unsigned char ui8) diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferClient.h b/engine/server/application/CentralServer/src/shared/AuctionTransferClient.h index 176ec79e6..617f75fd3 100755 --- a/engine/server/application/CentralServer/src/shared/AuctionTransferClient.h +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferClient.h @@ -40,7 +40,7 @@ class AuctionTransferClient : public AuctionTransfer::AuctionTransferAPI void onSendAbortTransaction(unsigned int, unsigned int, void *) {}; void onSendAuditAssetTransfer(unsigned int, unsigned int, void *) {}; - void onGetNewTransactionID(unsigned int, unsigned int, int64, void *) {}; + void onGetNewTransactionID(unsigned int, unsigned int, int64_t, void *) {}; // Responses to reply requests void onReplyReceivePrepareTransaction(unsigned int, unsigned int, void *) {}; @@ -52,10 +52,10 @@ class AuctionTransferClient : public AuctionTransfer::AuctionTransferAPI void onIdentifyHost(unsigned int, unsigned int, void *) {}; // callbacks initiated by auction - void onReceivePrepareTransaction(unsigned int, int64, unsigned int, unsigned int, int64, const char *) {}; - void onReceiveCommitTransaction(unsigned int, int64) {}; - void onReceiveAbortTransaction(unsigned int, int64) {}; - void onReceiveGetCharacterList(unsigned int, unsigned int, const char *) {}; + void onReceivePrepareTransaction(unsigned int, int64_t, unsigned int, unsigned int, int64_t, const char *) {}; + void onReceiveCommitTransaction(unsigned int, int64_t) {}; + void onReceiveAbortTransaction(unsigned int, int64_t) {}; + void onReceiveGetCharacterList(unsigned int, int64_t, const char *) {}; private: diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.h index a3d85096e..2ad6d405d 100755 --- a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.h +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.h @@ -62,7 +62,7 @@ class AuctionTransferAPI virtual void onSendCommitTransaction (unsigned trackingNumber, unsigned responseCode, void *user) = 0; virtual void onSendAbortTransaction (unsigned trackingNumber, unsigned responseCode, void *user) = 0; virtual void onSendAuditAssetTransfer(unsigned trackingNumber, unsigned responseCode, void *user) = 0; - virtual void onGetNewTransactionID( unsigned trackingNumber, unsigned responseCode, long long transactionID, void *user) = 0; + virtual void onGetNewTransactionID( unsigned trackingNumber, unsigned responseCode, int64_t transactionID, void *user) = 0; // responses to reply requests virtual void onReplyReceivePrepareTransaction (unsigned trackingNumber, unsigned responseCode, void *user) = 0; @@ -75,10 +75,10 @@ class AuctionTransferAPI // Callbacks initiated by the Auction System - virtual void onReceivePrepareTransaction (unsigned trackingNumber, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const char *newName) = 0; - virtual void onReceiveCommitTransaction (unsigned trackingNumber, long long transactionID) = 0; - virtual void onReceiveAbortTransaction (unsigned trackingNumber, long long transactionID) = 0; - virtual void onReceiveGetCharacterList(unsigned trackingNumber, unsigned stationID, const char *serverID) = 0; + virtual void onReceivePrepareTransaction (unsigned trackingNumber, int64_t transactionID, unsigned stationID, unsigned characterID, int64_t assetID, const char *newName) = 0; + virtual void onReceiveCommitTransaction (unsigned trackingNumber, int64_t transactionID) = 0; + virtual void onReceiveAbortTransaction (unsigned trackingNumber, int64_t transactionID) = 0; + virtual void onReceiveGetCharacterList(unsigned trackingNumber, int64_t stationID, const char *serverID) = 0; private: AuctionTransferAPICore *m_apiCore; diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.cpp index c2ccccb06..cc7d509d6 100755 --- a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.cpp +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.cpp @@ -135,7 +135,7 @@ void AuctionTransferAPICore::responseCallback(short type, Base::ByteStream::Read ServerTrackObject *stobj = new ServerTrackObject(++m_mappedServerTrack, real_server_track, connection); m_serverTracks.insert(std::pair(m_mappedServerTrack, stobj)); - long long transactionID; + int64_t transactionID; get(iter, transactionID); switch (type) { @@ -143,7 +143,7 @@ void AuctionTransferAPICore::responseCallback(short type, Base::ByteStream::Read { unsigned stationID; unsigned characterID; - long long assetID; + int64_t assetID; std::string newName; get(iter, stationID); get(iter, characterID); @@ -167,7 +167,7 @@ void AuctionTransferAPICore::responseCallback(short type, Base::ByteStream::Read // this had the stationID read in as the transactionID std::string serverID; get(iter, serverID); - m_api->onReceiveGetCharacterList(m_mappedServerTrack, (unsigned int)transactionID, serverID.c_str()); + m_api->onReceiveGetCharacterList(m_mappedServerTrack, transactionID, serverID.c_str()); } default: break; diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.h index a15f6cbae..00ae65cd1 100755 --- a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.h +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.h @@ -724,8 +724,9 @@ const unsigned MAX_ARRAY_SIZE = 1024; Base::get(source, arraySize); ValueType v; - if (arraySize > MAX_ARRAY_SIZE) + if (arraySize > MAX_ARRAY_SIZE) { arraySize = 0; + } for(unsigned int i = 0; i < arraySize; ++i) { diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Types.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Types.h index 69419a0fc..ea2b96257 100755 --- a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Types.h +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Types.h @@ -11,7 +11,8 @@ #ifndef BASE_LINUX_TYPES_H #define BASE_LINUX_TYPES_H -#include +//#include +#include #ifdef EXTERNAL_DISTRO namespace NAMESPACE @@ -30,13 +31,13 @@ namespace Base typedef signed char int8; typedef unsigned char uint8; -typedef signed short int16; -typedef unsigned short uint16; +typedef int16_t int16; +typedef uint16_t uint16; typedef int32_t int32; -typedef u_int32_t uint32; +typedef uint32_t uint32; typedef int64_t int64; -typedef u_int64_t uint64; +typedef uint64_t uint64; } #ifdef EXTERNAL_DISTRO }; diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h index 0c64cb2cb..aa9ba015f 100755 --- a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h @@ -28,10 +28,10 @@ typedef unsigned char uint8; typedef short int16; typedef unsigned short uint16; -typedef int int32; -typedef unsigned uint32; -typedef __int64 int64; -typedef unsigned __int64 uint64; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; }; #ifdef EXTERNAL_DISTRO diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.cpp index ed2e0ad3b..c12681592 100755 --- a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.cpp +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.cpp @@ -76,7 +76,7 @@ void ReplyRequest::pack(Base::ByteStream &msg) } ////////////////////////////////////////////////////////////////////////////////////// -CommonRequest::CommonRequest( RequestTypes type, unsigned serverTrack, long long transactionID ) +CommonRequest::CommonRequest( RequestTypes type, unsigned serverTrack, int64_t transactionID ) : GenericRequest((short)type, serverTrack), m_transactionID(transactionID) { } @@ -101,7 +101,7 @@ void GetIDRequest::pack(Base::ByteStream &msg) } ////////////////////////////////////////////////////////////////////////////////////// -SendPrepareCompressedRequest::SendPrepareCompressedRequest(RequestTypes type, unsigned serverTrack, const char *serverID, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const unsigned char *xmlAsset, unsigned length) +SendPrepareCompressedRequest::SendPrepareCompressedRequest(RequestTypes type, unsigned serverTrack, const char *serverID, int64_t transactionID, unsigned stationID, unsigned characterID, int64_t assetID, const unsigned char *xmlAsset, unsigned length) : GenericRequest((short)type, serverTrack), m_transactionID(transactionID), m_stationID(stationID), @@ -125,7 +125,7 @@ void SendPrepareCompressedRequest::pack(Base::ByteStream &msg) } ////////////////////////////////////////////////////////////////////////////////////// -SendPrepareRequest::SendPrepareRequest( RequestTypes type, unsigned serverTrack, const char *serverID, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const char *xml ) +SendPrepareRequest::SendPrepareRequest( RequestTypes type, unsigned serverTrack, const char *serverID, int64_t transactionID, unsigned stationID, unsigned characterID, int64_t assetID, const char *xml ) : GenericRequest((short)type, serverTrack), m_transactionID(transactionID), m_stationID(stationID), @@ -194,7 +194,7 @@ void IdentifyServerRequest::pack(Base::ByteStream &msg) ////////////////////////////////////////////////////////////////////////////////////// SendAuditRequest::SendAuditRequest( RequestTypes type, unsigned serverTrack, const char *gameCode, const char *serverCode, - long long inGameAssetID, unsigned stationID, const char *event, const char *message) + int64_t inGameAssetID, unsigned stationID, const char *event, const char *message) : GenericRequest((short)type, serverTrack), m_gameCode(gameCode), m_serverCode(serverCode), m_assetID(inGameAssetID), m_userID(stationID), m_event(event), m_message(message) { diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.h index f848c26b5..d59c86c93 100755 --- a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.h +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.h @@ -43,12 +43,12 @@ namespace AuctionTransfer class CommonRequest: public GenericRequest { public: - CommonRequest(RequestTypes type, unsigned serverTrack, long long transactionID); + CommonRequest(RequestTypes type, unsigned serverTrack, int64_t transactionID); virtual ~CommonRequest() {}; void pack(Base::ByteStream &msg); private: - long long m_transactionID; + int64_t m_transactionID; }; ////////////////////////////////////////////////////////////////////////////////////// @@ -66,15 +66,15 @@ namespace AuctionTransfer class SendPrepareRequest: public GenericRequest { public: - SendPrepareRequest(RequestTypes type, unsigned serverTrack, const char *serverID, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const char *xmlAsset); + SendPrepareRequest(RequestTypes type, unsigned serverTrack, const char *serverID, int64_t transactionID, unsigned stationID, unsigned characterID, int64_t assetID, const char *xmlAsset); virtual ~SendPrepareRequest() {}; void pack(Base::ByteStream &msg); private: - long long m_transactionID; + int64_t m_transactionID; unsigned m_stationID; unsigned m_characterID; - long long m_assetID; + int64_t m_assetID; std::string m_xml; std::string m_serverID; }; @@ -83,15 +83,15 @@ namespace AuctionTransfer class SendPrepareCompressedRequest: public GenericRequest { public: - SendPrepareCompressedRequest(RequestTypes type, unsigned serverTrack, const char *serverID, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const unsigned char *xmlAsset, unsigned length); + SendPrepareCompressedRequest(RequestTypes type, unsigned serverTrack, const char *serverID, int64_t transactionID, unsigned stationID, unsigned characterID, int64_t assetID, const unsigned char *xmlAsset, unsigned length); virtual ~SendPrepareCompressedRequest() {}; void pack(Base::ByteStream &msg); private: - long long m_transactionID; + int64_t m_transactionID; unsigned m_stationID; unsigned m_characterID; - long long m_assetID; + int64_t m_assetID; //std::string m_xml; std::string m_serverID; Blob m_data; @@ -127,13 +127,13 @@ namespace AuctionTransfer { public: SendAuditRequest( RequestTypes type, unsigned serverTrack, const char *gameCode, const char *serverCode, - long long inGameAssetID, unsigned stationID, const char *event, const char *message); + int64_t inGameAssetID, unsigned stationID, const char *event, const char *message); ~SendAuditRequest() {}; void pack(Base::ByteStream &msg); private: std::string m_gameCode; std::string m_serverCode; - long long m_assetID; + int64_t m_assetID; unsigned m_userID; std::string m_event; std::string m_message; diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.h index c7352fa20..709f4abc4 100755 --- a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.h +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.h @@ -22,10 +22,10 @@ namespace AuctionTransfer public: GetIDResponse(RequestTypes type, void *user); virtual ~GetIDResponse() {} - long long getNewID() { return m_transactionID; } + int64_t getNewID() { return m_transactionID; } virtual void unpack(Base::ByteStream::ReadIterator &iter); private: - long long m_transactionID; + int64_t m_transactionID; }; diff --git a/engine/server/application/CentralServer/src/shared/CentralServer.cpp b/engine/server/application/CentralServer/src/shared/CentralServer.cpp index 2cf6f0ba9..b5dac66b5 100755 --- a/engine/server/application/CentralServer/src/shared/CentralServer.cpp +++ b/engine/server/application/CentralServer/src/shared/CentralServer.cpp @@ -2324,7 +2324,7 @@ void CentralServer::receiveMessage(const MessageDispatch::Emitter & source, cons } case constcrc("LfgStatRsp") : { Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage >> const msg(ri); + GenericValueTypeMessage >> const msg(ri); m_numberOfCharacterMatchRequests += msg.getValue().first; m_numberOfCharacterMatchResults += msg.getValue().second.first; diff --git a/engine/server/application/ChatServer/src/shared/ChatInterface.cpp b/engine/server/application/ChatServer/src/shared/ChatInterface.cpp index c52044b8e..b75a79139 100755 --- a/engine/server/application/ChatServer/src/shared/ChatInterface.cpp +++ b/engine/server/application/ChatServer/src/shared/ChatInterface.cpp @@ -355,7 +355,7 @@ void ChatInterface::OnGetRoom(unsigned track, unsigned result, const ChatRoom *r ChatServer::putSystemAvatarInRoom(roomName); } std::string lowerRoomName = toLower(roomName); - unsigned sequence = (unsigned)user; + uintptr_t sequence = (uintptr_t)user; std::unordered_map::iterator f = roomList.find(lowerRoomName); if (f != roomList.end() && room) { @@ -416,7 +416,7 @@ void ChatInterface::OnGetRoom(unsigned track, unsigned result, const ChatRoom *r //----------------------------------------------------------------------- -void ChatInterface::queryRoom(const NetworkId & id, ConnectionServerConnection * connection, const unsigned int sequence, const std::string & roomName) +void ChatInterface::queryRoom(const NetworkId & id, ConnectionServerConnection * connection, const uintptr_t sequence, const std::string & roomName) { UNREF(connection); ChatServer::fileLog(s_enableChatRoomLogs, "ChatInterface", "queryRoom() id(%s) connection(%s) sequence(%u) roomName(%s)", id.getValueString().c_str(), ChatServer::getConnectionAddress(connection).c_str(), sequence, roomName.c_str()); @@ -1579,7 +1579,7 @@ void ChatInterface::OnCreateRoom(unsigned track,unsigned result, const ChatRoom PROFILER_AUTO_BLOCK_DEFINE("ChatInterface - OnCreateRoom"); UNREF(user); - unsigned sequence = (unsigned)user; + uintptr_t sequence = (uintptr_t)user; static Unicode::String wideSWG = Unicode::narrowToWide("SOE+SWG"); static Unicode::String wideFilter = Unicode::narrowToWide(""); static ChatUnicodeString swgNode(wideSWG.data(), wideSWG.size()); @@ -1882,7 +1882,7 @@ void ChatInterface::OnEnterRoom(unsigned track, unsigned result, const ChatAvata return; } - unsigned sequence = (unsigned)user; + uintptr_t sequence = (uintptr_t)user; ChatAvatarId srcId; if (srcAvatar) @@ -2559,7 +2559,7 @@ void ChatInterface::OnLeaveRoom(unsigned track, unsigned result, const ChatAvata return; } - unsigned sequence = (unsigned)user; + uintptr_t sequence = (uintptr_t)user; ChatAvatarId id; if (srcAvatar) @@ -2913,7 +2913,7 @@ void ChatInterface::OnSendRoomMessage(unsigned track, unsigned result, const Cha } UNREF(srcAvatar); UNREF(destRoom); - unsigned sequence = (unsigned)user; + uintptr_t sequence = (uintptr_t)user; ChatOnSendRoomMessage chat(sequence, result); IGNORE_RETURN(ChatServer::sendResponseForTrackId(track, chat)); } @@ -2998,7 +2998,7 @@ void ChatInterface::OnSendInstantMessage(unsigned track, unsigned result, const } UNREF(srcAvatar); - unsigned sequence = (unsigned)user; + uintptr_t sequence = (uintptr_t)user; ChatOnSendInstantMessage chat(sequence, result); IGNORE_RETURN(ChatServer::sendResponseForTrackId(track, chat)); @@ -3053,7 +3053,7 @@ void ChatInterface::OnSendPersistentMessage(unsigned track, unsigned result, con DEBUG_WARNING(true, ("We received an OnSendPersistentMessage with a success result code but nullptr data. This is an error that the API should never give.")); return; } - unsigned sequence = (unsigned)user; + uintptr_t sequence = (uintptr_t)user; UNREF(srcAvatar); ChatOnSendPersistentMessage chat(sequence, result); IGNORE_RETURN(ChatServer::sendResponseForTrackId(track, chat)); diff --git a/engine/server/application/ChatServer/src/shared/ChatInterface.h b/engine/server/application/ChatServer/src/shared/ChatInterface.h index 31c3bed67..b92212078 100755 --- a/engine/server/application/ChatServer/src/shared/ChatInterface.h +++ b/engine/server/application/ChatServer/src/shared/ChatInterface.h @@ -68,7 +68,7 @@ class ChatInterface : public ChatAPI std::string getChatName(const NetworkId &id); - void queryRoom (const NetworkId & id, ConnectionServerConnection * connection, const unsigned int sequenceId, const std::string & roomName); + void queryRoom (const NetworkId & id, ConnectionServerConnection * connection, const uintptr_t sequenceId, const std::string & roomName); void updateRoomForThisChatAPI(const ChatRoom *room, const ChatAvatar *additionalAvatar); void updateRooms(); diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 187997edd..9f0bdee51 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -198,8 +198,7 @@ std::string ClientConnection::getCurrentActivePlayTimeDuration() const { void ClientConnection::sendPlayTimeInfoToGameServer() const { if (m_client && m_client->getGameConnection()) { // update the game server with play time info - GenericValueTypeMessage < std::pair < int32, std::pair < int32, unsigned - long > > > + GenericValueTypeMessage < std::pair < int32, std::pair < int32, uint32_t > > > const msgPlayTimeInfo( "UpdateSessionPlayTimeInfo", std::make_pair(static_cast(m_startPlayTime), std::make_pair(static_cast(m_lastActiveTime), m_activePlayTimeDuration))); @@ -1369,9 +1368,7 @@ ClientConnection::onValidateClient(StationId suid, const std::string &username, } // tell client the server-side game and subscription feature bits and which ConnectionServer we are and the current server Epoch time - GenericValueTypeMessage < std::pair < std::pair < unsigned - long, unsigned - long > , std::pair < int, int32 > > > + GenericValueTypeMessage < std::pair < std::pair < uint32_t, uint32_t > , std::pair < int, int32 > > > const msgFeatureBits( "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), static_cast(::time(nullptr))))); send(msgFeatureBits, true); diff --git a/engine/server/application/LoginServer/src/shared/CSToolConnection.cpp b/engine/server/application/LoginServer/src/shared/CSToolConnection.cpp index 9163a15a0..6460a3300 100755 --- a/engine/server/application/LoginServer/src/shared/CSToolConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/CSToolConnection.cpp @@ -21,20 +21,20 @@ namespace CSToolConnectionNamespace { - std::map< uint32, CSToolConnection * > toolsByID; + std::map< uintptr_t, CSToolConnection * > toolsByID; } uint32 CSToolConnection::m_curToolID = 0; // statics -CSToolConnection * CSToolConnection::getCSToolConnectionByToolId(uint32 id) +CSToolConnection * CSToolConnection::getCSToolConnectionByToolId(uintptr_t id) { - std::map< uint32, CSToolConnection * >::iterator it = CSToolConnectionNamespace::toolsByID.find(id); + std::map< uintptr_t, CSToolConnection * >::iterator it = CSToolConnectionNamespace::toolsByID.find(id); return it == CSToolConnectionNamespace::toolsByID.end() ? 0 : it->second; } -void CSToolConnection::validateCSTool(uint32 toolId, apiResult result, const apiSession& session) +void CSToolConnection::validateCSTool(uintptr_t toolId, apiResult result, const apiSession& session) { //find the tool CSToolConnection * p_connection = getCSToolConnectionByToolId(toolId); diff --git a/engine/server/application/LoginServer/src/shared/CSToolConnection.h b/engine/server/application/LoginServer/src/shared/CSToolConnection.h index 08651f09f..6690916d6 100755 --- a/engine/server/application/LoginServer/src/shared/CSToolConnection.h +++ b/engine/server/application/LoginServer/src/shared/CSToolConnection.h @@ -29,8 +29,8 @@ class CSToolConnection : public Connection virtual void onConnectionClosed(); void sendToClusters( const std::string & sCommand, const std::string &sCommandLine ); - static CSToolConnection * getCSToolConnectionByToolId( uint32 id ); - static void validateCSTool( uint32 toolId, apiResult result, const apiSession & session ); + static CSToolConnection * getCSToolConnectionByToolId( uintptr_t id ); + static void validateCSTool( uintptr_t toolId, apiResult result, const apiSession & session ); // cluster selection interface std::string selectCluster( const std::string & cluster ); @@ -47,7 +47,7 @@ class CSToolConnection : public Connection uint32 m_ui32PrivilegeLevel; std::string m_sInputBuffer; std::string m_sUserName; - uint32 m_toolID; + uintptr_t m_toolID; static uint32 m_curToolID; std::set< std::string > m_selectedClusters; diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index bd053af2e..869f6b8bd 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -480,7 +480,9 @@ void LoginServer::receiveMessage(const MessageDispatch::Emitter &source, const M break; } } - DEBUG_REPORT_LOG(!found, ("Tried to remove a connection server that wasn't in our list.\n")); + if(!found) { + DEBUG_REPORT_LOG(true, ("Tried to remove a connection server that wasn't in our list.\n")); + } m_clusterStatusChanged = true; } else { WARNING_STRICT_FATAL(true, ("Programmer bug: Got ConnectionServerDown from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); diff --git a/engine/server/application/LoginServer/src/shared/SessionApiClient.cpp b/engine/server/application/LoginServer/src/shared/SessionApiClient.cpp index 73ff91aef..6879a06d8 100755 --- a/engine/server/application/LoginServer/src/shared/SessionApiClient.cpp +++ b/engine/server/application/LoginServer/src/shared/SessionApiClient.cpp @@ -120,7 +120,7 @@ void SessionApiClient::OnSessionValidate(const apiTrackingNumber trackingNumber, else { // attempt to validate a CS Tool associated with this request. - CSToolConnection::validateCSTool( ( uint32 )userData, result, session ); + CSToolConnection::validateCSTool( ( uintptr_t ) userData, result, session ); } } diff --git a/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.h b/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.h index 321255324..1cb362f06 100755 --- a/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.h +++ b/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.h @@ -38,7 +38,7 @@ class TaskEnableCharacter : public DB::TaskRequest DB::BindableLong station_id; //lint !e1925 // public data member : suppressed because this is a private inner class DB::BindableNetworkId character_id; //lint !e1925 // public data member : suppressed because this is a private inner class DB::BindableBool enabled; //lint !e1925 // public data member : suppressed because this is a private inner class - DB::BindableLong result; //lint !e1925 // public data member : suppressed because this is a private inner class + DB::BindableLong result; //lint !e1925 // public data member : suppressed because this is a private inner class virtual void getSQL(std::string &sql); diff --git a/engine/server/application/TaskManager/src/shared/GameConnection.cpp b/engine/server/application/TaskManager/src/shared/GameConnection.cpp index baa6adfb1..afbbc6cce 100755 --- a/engine/server/application/TaskManager/src/shared/GameConnection.cpp +++ b/engine/server/application/TaskManager/src/shared/GameConnection.cpp @@ -79,7 +79,7 @@ void GameConnection::receive(const Archive::ByteStream & message) { if(! m_pid) { - GenericValueTypeMessage msg(r); + GenericValueTypeMessage msg(r); m_pid = msg.getValue(); #ifndef _WIN32 diff --git a/engine/server/application/TaskManager/src/shared/ManagerConnection.cpp b/engine/server/application/TaskManager/src/shared/ManagerConnection.cpp index 42db20990..b67798826 100755 --- a/engine/server/application/TaskManager/src/shared/ManagerConnection.cpp +++ b/engine/server/application/TaskManager/src/shared/ManagerConnection.cpp @@ -103,8 +103,8 @@ void ManagerConnection::onReceive(const Archive::ByteStream & message) switch(messageType) { case constcrc("SystemTimeCheck") : { - long const currentTime = static_cast(::time(nullptr)); - GenericValueTypeMessage > msg(r); + int32_t const currentTime = static_cast(::time(nullptr)); + GenericValueTypeMessage > msg(r); if (TaskManager::getNodeLabel() == "node0") { @@ -122,8 +122,8 @@ void ManagerConnection::onReceive(const Archive::ByteStream & message) } case constcrc("TaskConnectionIdMessage") : { - static long const clockDriftFatalTimePeriod = static_cast(TaskManager::getStartTime()) + ConfigTaskManager::getClockDriftFatalIntervalSeconds(); - long const currentTime = static_cast(::time(nullptr)); + static int32_t const clockDriftFatalTimePeriod = static_cast(TaskManager::getStartTime()) + ConfigTaskManager::getClockDriftFatalIntervalSeconds(); + int32_t const currentTime = static_cast(::time(nullptr)); TaskConnectionIdMessage t(r); WARNING_STRICT_FATAL(t.getServerType() != TaskConnectionIdMessage::TaskManager, ("ManagerConnection received wrong type identifier")); @@ -150,7 +150,7 @@ void ManagerConnection::onReceive(const Archive::ByteStream & message) { LOG("CustomerService", ("system_clock_mismatch:System clock mismatch (%d seconds) by more than %d seconds: master TaskManager epoch (%ld), remote TaskManager %s (%s) epoch (%ld). Telling remote TaskManager to terminate.", (std::max(currentTime, t.getCurrentEpochTime()) - std::min(currentTime, t.getCurrentEpochTime())), ConfigTaskManager::getMaximumClockDriftToleranceSeconds(), currentTime, t.getCommandLine().c_str(), getRemoteAddress().c_str(), t.getCurrentEpochTime())); - GenericValueTypeMessage > > systemTimeMismatchMessage("SystemTimeMismatchMessage", std::make_pair(TaskManager::getNodeLabel(), std::make_pair(static_cast(currentTime), t.getCurrentEpochTime()))); + GenericValueTypeMessage > > systemTimeMismatchMessage("SystemTimeMismatchMessage", std::make_pair(TaskManager::getNodeLabel(), std::make_pair(static_cast(currentTime), static_cast (t.getCurrentEpochTime())))); send(systemTimeMismatchMessage); } } @@ -166,7 +166,7 @@ void ManagerConnection::onReceive(const Archive::ByteStream & message) } case constcrc("SystemTimeMismatchMessage") : { - GenericValueTypeMessage > > msg(r); + GenericValueTypeMessage > > msg(r); FATAL((msg.getValue().first == "node0"), ("System clock mismatch (%d seconds) by more than %d seconds: master TaskManager epoch (%ld), self epoch (%ld)", (std::max(msg.getValue().second.first, msg.getValue().second.second) - std::min(msg.getValue().second.first, msg.getValue().second.second)), ConfigTaskManager::getMaximumClockDriftToleranceSeconds(), msg.getValue().second.first, msg.getValue().second.second)); break; } diff --git a/engine/server/application/TaskManager/src/shared/TaskManager.cpp b/engine/server/application/TaskManager/src/shared/TaskManager.cpp index f4a9ec31d..356271dbc 100755 --- a/engine/server/application/TaskManager/src/shared/TaskManager.cpp +++ b/engine/server/application/TaskManager/src/shared/TaskManager.cpp @@ -970,7 +970,7 @@ void TaskManager::update() ManagerConnection * master = Locator::getServer("node0"); if (master) { - GenericValueTypeMessage > msg("SystemTimeCheck", std::make_pair(getNodeLabel(), static_cast(timeNow))); + GenericValueTypeMessage > msg("SystemTimeCheck", std::make_pair(getNodeLabel(), static_cast(timeNow))); master->send(msg); } } diff --git a/engine/server/library/codegen/make_packages.pl b/engine/server/library/codegen/make_packages.pl index 2b580a3d1..65c55c913 100755 --- a/engine/server/library/codegen/make_packages.pl +++ b/engine/server/library/codegen/make_packages.pl @@ -307,8 +307,9 @@ sub makeEncodeFunction } print OUTFILE "\tconst DBSchema::${rowtype} *row=m_\l${buffer}.findConstRowByIndex(objectId);\n"; print OUTFILE "\tWARNING_STRICT_FATAL(row==NULL,(\"Loading object %s, no ${rowtype} in the buffer\\n\",objectId.getValueString().c_str()));\n"; - print OUTFILE "\tif (!row)\n"; + print OUTFILE "\tif (!row) {\n"; print OUTFILE "\t\treturn false;\n"; + print OUTFILE "\t}\n"; print OUTFILE "\n"; foreach $member (@{ $packageMembers{"$classname.$package"} }) diff --git a/engine/server/library/serverDatabase/src/shared/DatabaseProcess.cpp b/engine/server/library/serverDatabase/src/shared/DatabaseProcess.cpp index 5b097f2c8..3972a6814 100755 --- a/engine/server/library/serverDatabase/src/shared/DatabaseProcess.cpp +++ b/engine/server/library/serverDatabase/src/shared/DatabaseProcess.cpp @@ -195,7 +195,9 @@ DatabaseProcess::~DatabaseProcess() void DatabaseProcess::run(void) { static bool shouldSleep = ConfigServerDatabase::getShouldSleep(); - bool idle=false; +#ifdef _DEBUG + bool idle = false; +#endif int loopcount=0; float nextQueryCountTime=0; @@ -261,7 +263,7 @@ void DatabaseProcess::run(void) if (Persister::getInstance().isIdle() && Loader::getInstance().isIdle() && DataLookup::getInstance().isIdle()) { DEBUG_REPORT_LOG(ConfigServerDatabase::getReportSaveTimes() && !idle,("Database process is idle.\n")); - idle=true; + // idle=true; if (taskService) { ServerIdleMessage msg(true); @@ -270,7 +272,7 @@ void DatabaseProcess::run(void) } else { - idle=false; + // idle=false; if (taskService) { ServerIdleMessage msg(false); diff --git a/engine/server/library/serverDatabase/src/shared/UniverseLocator.cpp b/engine/server/library/serverDatabase/src/shared/UniverseLocator.cpp index bad7a18cc..0ee906b93 100755 --- a/engine/server/library/serverDatabase/src/shared/UniverseLocator.cpp +++ b/engine/server/library/serverDatabase/src/shared/UniverseLocator.cpp @@ -37,7 +37,7 @@ bool UniverseLocator::locateObjects(DB::Session *session, const std::string &sch void UniverseLocator::sendPostBaselinesCustomData(GameServerConnection &conn) const { DEBUG_REPORT_LOG(true,("Sending UniverseComplete.\n")); - GenericValueTypeMessage const universeCompleteMessage("UniverseCompleteMessage", DatabaseProcess::getInstance().getProcessId()); + GenericValueTypeMessage const universeCompleteMessage("UniverseCompleteMessage", DatabaseProcess::getInstance().getProcessId()); conn.send(universeCompleteMessage, true); SetUniverseAuthoritativeMessage const setUniverseAuthoritativeMessage(conn.getProcessId()); diff --git a/engine/server/library/serverGame/src/shared/ai/AiCreatureWeaponActions.cpp b/engine/server/library/serverGame/src/shared/ai/AiCreatureWeaponActions.cpp index 4d5498f8b..66e8cb8c4 100755 --- a/engine/server/library/serverGame/src/shared/ai/AiCreatureWeaponActions.cpp +++ b/engine/server/library/serverGame/src/shared/ai/AiCreatureWeaponActions.cpp @@ -102,7 +102,7 @@ PersistentCrcString const & AiCreatureWeaponActions::getCombatAction() { unsigned int expiredCount = 0; - for (unsigned int i = 0; i < m_singleUseActionList.size(); ++i) + for (uint32_t i = 0; i < m_singleUseActionList.size(); ++i) { if (m_singleUseActionList[i] != 0) { @@ -133,7 +133,7 @@ PersistentCrcString const & AiCreatureWeaponActions::getCombatAction() // Delayed repeat actions { - for (unsigned int i = 0; i < m_delayRepeatActionList.size(); ++i) + for (uint32_t i = 0; i < m_delayRepeatActionList.size(); ++i) { if (osTime > time_t(m_delayRepeatActionList[i])) { @@ -160,7 +160,7 @@ PersistentCrcString const & AiCreatureWeaponActions::getCombatAction() time_t nextActionTime = 0; unsigned int nextActionIndex = 0; - for (unsigned int i = 0; i < m_instantRepeatActionList.size(); ++i) + for (uint32_t i = 0; i < m_instantRepeatActionList.size(); ++i) { if (osTime >= time_t(m_instantRepeatActionList[i])) { diff --git a/engine/server/library/serverGame/src/shared/ai/HateList.cpp b/engine/server/library/serverGame/src/shared/ai/HateList.cpp index 496fb2b9a..2419100ca 100755 --- a/engine/server/library/serverGame/src/shared/ai/HateList.cpp +++ b/engine/server/library/serverGame/src/shared/ai/HateList.cpp @@ -535,8 +535,8 @@ void HateList::addServerNpAutoDeltaVariables(Archive::AutoDeltaByteStream & stre // ---------------------------------------------------------------------- int HateList::getTimeSinceLastUpdate() const { - time_t const currentTime = Os::getRealSystemTime(); - time_t const timeSinceActivitiy = (currentTime - m_lastUpdateTime.get()); + uint32_t const currentTime = Os::getRealSystemTime(); + uint32_t const timeSinceActivitiy = (currentTime - m_lastUpdateTime.get()); return clamp(0, static_cast(timeSinceActivitiy), 1024); } diff --git a/engine/server/library/serverGame/src/shared/ai/HateList.h b/engine/server/library/serverGame/src/shared/ai/HateList.h index e63690416..ec9c0fa1c 100755 --- a/engine/server/library/serverGame/src/shared/ai/HateList.h +++ b/engine/server/library/serverGame/src/shared/ai/HateList.h @@ -90,8 +90,8 @@ class HateList Archive::AutoDeltaMap m_hateList; Archive::AutoDeltaVariable m_target; Archive::AutoDeltaVariable m_maxHate; - Archive::AutoDeltaVariable m_lastUpdateTime; - Archive::AutoDeltaVariable m_autoExpireTargetDuration; + Archive::AutoDeltaVariable m_lastUpdateTime; + Archive::AutoDeltaVariable m_autoExpireTargetDuration; std::set m_recentHateList; // This is used for assist logic }; diff --git a/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp b/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp index d0cb7640e..52b8d2042 100755 --- a/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp +++ b/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp @@ -1800,11 +1800,11 @@ static void commandFuncSpatialChatInternal(Command const &, NetworkId const &act else if (!squelched && (ConfigServerGame::getChatSpamNotifyPlayerWhenLimitedIntervalSeconds() > 0) && obj->getClient()) { // send message telling character he can no longer talk - const int timeNow = static_cast(::time(nullptr)); - const int chatSpamTimeEndInterval = playerObject->getChatSpamTimeEndInterval(); + const int32_t timeNow = static_cast(::time(nullptr)); + const int32_t chatSpamTimeEndInterval = playerObject->getChatSpamTimeEndInterval(); if ((chatSpamTimeEndInterval > timeNow) && (timeNow >= playerObject->getChatSpamNextTimeToNotifyPlayerWhenLimited())) { - GenericValueTypeMessage csl("ChatSpamLimited", (chatSpamTimeEndInterval - timeNow)); + GenericValueTypeMessage csl("ChatSpamLimited", (chatSpamTimeEndInterval - timeNow)); obj->getClient()->send(csl, true); playerObject->setChatSpamNextTimeToNotifyPlayerWhenLimited((timeNow + ConfigServerGame::getChatSpamNotifyPlayerWhenLimitedIntervalSeconds())); @@ -1937,8 +1937,8 @@ static void commandFuncSpatialChat(Command const &, NetworkId const &actor, Netw else if (!squelched && (ConfigServerGame::getChatSpamNotifyPlayerWhenLimitedIntervalSeconds() > 0) && obj->getClient()) { // send message telling character he can no longer talk - const int timeNow = static_cast(::time(nullptr)); - const int chatSpamTimeEndInterval = playerObject->getChatSpamTimeEndInterval(); + const int32_t timeNow = static_cast(::time(nullptr)); + const int32_t chatSpamTimeEndInterval = playerObject->getChatSpamTimeEndInterval(); if ((chatSpamTimeEndInterval > timeNow) && (timeNow >= playerObject->getChatSpamNextTimeToNotifyPlayerWhenLimited())) { GenericValueTypeMessage csl("ChatSpamLimited", (chatSpamTimeEndInterval - timeNow)); @@ -2877,7 +2877,7 @@ static void commandFuncPermissionListModify(Command const &, NetworkId const &ac Unicode::UnicodeStringVector tokens; Unicode::tokenize(params, tokens); Unicode::String temp; - for (int i = 0; i < tokens.size(); i++) + for (uint32_t i = 0; i < tokens.size(); i++) { if(i < tokens.size() - 2) { @@ -2888,7 +2888,6 @@ static void commandFuncPermissionListModify(Command const &, NetworkId const &ac } } } - size_t curpos = 0; const Unicode::String & playerName = temp; const Unicode::String & listName = tokens[tokens.size()-2]; const Unicode::String & action = tokens[tokens.size()-1]; @@ -8275,7 +8274,7 @@ static void commandFuncSpammer(Command const &, NetworkId const &actor, NetworkI { // check warden permission first or if god const PlayerObject * gmPlayerObject = PlayerCreatureController::getPlayerObject(gm); - if (!gmPlayerObject || (!gmPlayerObject->isWarden()) && !gmClient->isGod()) + if (!gmPlayerObject || (!gmPlayerObject->isWarden() && !gmClient->isGod())) { Chat::sendSystemMessage(*gm, StringId("warden", "not_authorized"), Unicode::emptyString); return; @@ -8426,7 +8425,7 @@ static void commandFuncUnspammer(Command const &, NetworkId const &actor, Networ { // check warden permission first or if god const PlayerObject * gmPlayerObject = PlayerCreatureController::getPlayerObject(gm); - if (!gmPlayerObject || (!gmPlayerObject->isWarden()) && !gmClient->isGod()) + if (!gmPlayerObject || (!gmPlayerObject->isWarden() && !gmClient->isGod())) { Chat::sendSystemMessage(*gm, StringId("warden", "not_authorized"), Unicode::emptyString); return; diff --git a/engine/server/library/serverGame/src/shared/command/CommandQueue.cpp b/engine/server/library/serverGame/src/shared/command/CommandQueue.cpp index b80d30b36..0d16fad49 100755 --- a/engine/server/library/serverGame/src/shared/command/CommandQueue.cpp +++ b/engine/server/library/serverGame/src/shared/command/CommandQueue.cpp @@ -684,7 +684,7 @@ void CommandQueue::switchState() m_eventStartTime = s_currentTime; - const unsigned int savedQueueSize = m_queue.size(); + const uint32_t savedQueueSize = m_queue.size(); switch ( m_state.get() ) { case State_Waiting: diff --git a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserAi.cpp b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserAi.cpp index ade32b450..fadec301d 100755 --- a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserAi.cpp +++ b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserAi.cpp @@ -272,12 +272,12 @@ bool ConsoleCommandParserAi::performParsing(const NetworkId & userId, const Stri // Hate Over Time List { - std::map > > const & hateOverTime = aiCreatureController->getCreature()->getHateOverTime(); + std::map > > const & hateOverTime = aiCreatureController->getCreature()->getHateOverTime(); if (!hateOverTime.empty()) { result += Unicode::narrowToWide(fs.sprintf("* HATE OVER TIME LIST currentGameTime=(%lu)*\n", ServerClock::getInstance().getGameTimeSeconds())); - for (std::map > >::const_iterator iter = hateOverTime.begin(); iter != hateOverTime.end(); ++iter) + for (std::map > >::const_iterator iter = hateOverTime.begin(); iter != hateOverTime.end(); ++iter) { CachedNetworkId const hateTarget(iter->first); TangibleObject const * const hateTargetTangibleObject = TangibleObject::asTangibleObject(hateTarget.getObject()); @@ -369,12 +369,12 @@ bool ConsoleCommandParserAi::performParsing(const NetworkId & userId, const Stri // Hate Over Time List { - std::map > > const & hateOverTime = to->getHateOverTime(); + std::map > > const & hateOverTime = to->getHateOverTime(); if (!hateOverTime.empty()) { result += Unicode::narrowToWide(fs.sprintf("* HATE OVER TIME LIST currentGameTime=(%lu)*\n", ServerClock::getInstance().getGameTimeSeconds())); - for (std::map > >::const_iterator iter = hateOverTime.begin(); iter != hateOverTime.end(); ++iter) + for (std::map > >::const_iterator iter = hateOverTime.begin(); iter != hateOverTime.end(); ++iter) { CachedNetworkId const hateTarget(iter->first); TangibleObject const * const hateTargetTangibleObject = TangibleObject::asTangibleObject(hateTarget.getObject()); diff --git a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserCollection.cpp b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserCollection.cpp index a8ef94a9a..55c98d6d4 100755 --- a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserCollection.cpp +++ b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserCollection.cpp @@ -167,7 +167,7 @@ bool ConsoleCommandParserCollection::performParsing (const NetworkId & userId, c } } - unsigned long currentValue; + uint32_t currentValue; IGNORE_RETURN(p->getCollectionSlotValue(*slot, currentValue)); result += Unicode::narrowToWide(FormattedString<512>().sprintf("modifying collection slot %s/%s/%s/%s value of %lu by %s for character object %s (%s)\n", slot->collection.page.book.name.c_str(), slot->collection.page.name.c_str(), slot->collection.name.c_str(), Unicode::wideToNarrow(argv[2]).c_str(), currentValue, adjustment.getValueString().c_str(), oid.getValueString().c_str(), Unicode::wideToNarrow(o->getAssignedObjectName()).c_str())); @@ -239,7 +239,7 @@ bool ConsoleCommandParserCollection::performParsing (const NetworkId & userId, c else { // grant counter-type slot - unsigned long currentValue; + uint32_t currentValue; IGNORE_RETURN(p->getCollectionSlotValue(**iter, currentValue)); // quickie way to convert to an int64 @@ -316,7 +316,7 @@ bool ConsoleCommandParserCollection::performParsing (const NetworkId & userId, c else { // grant counter-type slot - unsigned long currentValue; + uint32_t currentValue; IGNORE_RETURN(p->getCollectionSlotValue(**iter, currentValue)); // quickie way to convert to an int64 @@ -393,7 +393,7 @@ bool ConsoleCommandParserCollection::performParsing (const NetworkId & userId, c else { // grant counter-type slot - unsigned long currentValue; + uint32_t currentValue; IGNORE_RETURN(p->getCollectionSlotValue(**iter, currentValue)); // quickie way to convert to an int64 @@ -456,7 +456,7 @@ bool ConsoleCommandParserCollection::performParsing (const NetworkId & userId, c else { // revoke counter-type slot - unsigned long currentValue; + uint32_t currentValue; IGNORE_RETURN(p->getCollectionSlotValue(**iter, currentValue)); // quickie way to convert to an int64 @@ -519,7 +519,7 @@ bool ConsoleCommandParserCollection::performParsing (const NetworkId & userId, c else { // revoke counter-type slot - unsigned long currentValue; + uint32_t currentValue; IGNORE_RETURN(p->getCollectionSlotValue(**iter, currentValue)); // quickie way to convert to an int64 @@ -582,7 +582,7 @@ bool ConsoleCommandParserCollection::performParsing (const NetworkId & userId, c else { // revoke counter-type slot - unsigned long currentValue; + uint32_t currentValue; IGNORE_RETURN(p->getCollectionSlotValue(**iter, currentValue)); // quickie way to convert to an int64 @@ -651,7 +651,7 @@ bool ConsoleCommandParserCollection::performParsing (const NetworkId & userId, c } else { - unsigned long value; + uint32_t value; IGNORE_RETURN(p->getCollectionSlotValue(**iterSlot, value)); if (value == 0) continue; diff --git a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserObject.cpp b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserObject.cpp index dc2fd5f03..26a51317f 100755 --- a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserObject.cpp +++ b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserObject.cpp @@ -101,10 +101,7 @@ namespace ConsoleCommandParserObjectNamespace //test handler, this should eventually be removed void testConsentHandler(const NetworkId& player, int id, bool response) { - int i = 0; - if (response == true) - i = 1; - DEBUG_REPORT_LOG(true, ("We received a test consent back with values NetworkId:%s Id:%d Response:%d\n", player.getValueString().c_str(), id, i)); + DEBUG_REPORT_LOG(true, ("We received a test consent back with values NetworkId: %s Id: %d Response: %d\n", player.getValueString().c_str(), id, (response ? 1 : 0))); } ServerObjectTemplate const *getObjectTemplateForCreation(std::string const &templateName) diff --git a/engine/server/library/serverGame/src/shared/controller/AiCreatureController.cpp b/engine/server/library/serverGame/src/shared/controller/AiCreatureController.cpp index 121e63833..4486f242a 100755 --- a/engine/server/library/serverGame/src/shared/controller/AiCreatureController.cpp +++ b/engine/server/library/serverGame/src/shared/controller/AiCreatureController.cpp @@ -2960,7 +2960,7 @@ PersistentCrcString const & AICreatureController::getCombatAction() } //----------------------------------------------------------------------- -time_t AICreatureController::getKnockDownRecoveryTime() const +uint32_t AICreatureController::getKnockDownRecoveryTime() const { AiCreatureCombatProfile const * const combatProfile = AiCreatureCombatProfile::getCombatProfile(m_aiCreatureData->m_primarySpecials); diff --git a/engine/server/library/serverGame/src/shared/controller/AiCreatureController.h b/engine/server/library/serverGame/src/shared/controller/AiCreatureController.h index 83aa7a070..5b0dc038b 100755 --- a/engine/server/library/serverGame/src/shared/controller/AiCreatureController.h +++ b/engine/server/library/serverGame/src/shared/controller/AiCreatureController.h @@ -186,7 +186,7 @@ class AICreatureController : public CreatureController AiMovementType getPendingMovementType() const; PersistentCrcString const & getCombatAction(); - time_t getKnockDownRecoveryTime() const; + uint32_t getKnockDownRecoveryTime() const; std::string const getCombatActionsString(); @@ -245,7 +245,7 @@ class AICreatureController : public CreatureController Archive::AutoDeltaVariable m_frozen; Archive::AutoDeltaVariable m_combatStartLocation; Archive::AutoDeltaVariable m_retreating; - Archive::AutoDeltaVariable m_retreatingStartTime; + Archive::AutoDeltaVariable m_retreatingStartTime; Archive::AutoDeltaVariable m_logging; Archive::AutoDeltaVariableCallback m_creatureName; Archive::AutoDeltaVariable m_hibernationDelay; diff --git a/engine/server/library/serverGame/src/shared/core/CharacterMatchManager.cpp b/engine/server/library/serverGame/src/shared/core/CharacterMatchManager.cpp index 89668966b..cb3d32c4f 100755 --- a/engine/server/library/serverGame/src/shared/core/CharacterMatchManager.cpp +++ b/engine/server/library/serverGame/src/shared/core/CharacterMatchManager.cpp @@ -40,9 +40,9 @@ // ============================================================================ -unsigned long CharacterMatchManager::ms_numberOfCharacterMatchRequests = 0; -unsigned long CharacterMatchManager::ms_numberOfCharacterMatchResults = 0; -unsigned long CharacterMatchManager::ms_timeSpentOnCharacterMatchRequestsMs = 0; +uint32_t CharacterMatchManager::ms_numberOfCharacterMatchRequests = 0; +uint32_t CharacterMatchManager::ms_numberOfCharacterMatchResults = 0; +uint32_t CharacterMatchManager::ms_timeSpentOnCharacterMatchRequestsMs = 0; // ============================================================================ // @@ -639,14 +639,14 @@ void CharacterMatchManager::requestMatch(NetworkId const &networkId, MatchMaking requestCreatureObject->onCharacterMatchRetrieved(mmcr); } - const unsigned long endTimeMs = Clock::timeMs(); + const uint32_t endTimeMs = Clock::timeMs(); if (endTimeMs >= startTimeMs) { ms_timeSpentOnCharacterMatchRequestsMs += (endTimeMs - startTimeMs); } else // time wrapped { - static const unsigned long max = std::numeric_limits::max(); + static const uint32_t max = std::numeric_limits::max(); ms_timeSpentOnCharacterMatchRequestsMs += (max - startTimeMs + endTimeMs); } } diff --git a/engine/server/library/serverGame/src/shared/core/CharacterMatchManager.h b/engine/server/library/serverGame/src/shared/core/CharacterMatchManager.h index 7fe8ed0ae..900b5e888 100755 --- a/engine/server/library/serverGame/src/shared/core/CharacterMatchManager.h +++ b/engine/server/library/serverGame/src/shared/core/CharacterMatchManager.h @@ -17,14 +17,14 @@ class CharacterMatchManager public: static void requestMatch(NetworkId const &networkId, MatchMakingCharacterPreferenceId const &matchMakingCharacterPreferenceId); - static void getMatchStatistics(unsigned long &numberOfCharacterMatchRequests, unsigned long &numberOfCharacterMatchResults, unsigned long &timeSpentOnCharacterMatchRequestsMs); + static void getMatchStatistics(uint32_t &numberOfCharacterMatchRequests, uint32_t &numberOfCharacterMatchResults, uint32_t &timeSpentOnCharacterMatchRequestsMs); static void clearMatchStatistics(); private: - static unsigned long ms_numberOfCharacterMatchRequests; - static unsigned long ms_numberOfCharacterMatchResults; - static unsigned long ms_timeSpentOnCharacterMatchRequestsMs; + static uint32_t ms_numberOfCharacterMatchRequests; + static uint32_t ms_numberOfCharacterMatchResults; + static uint32_t ms_timeSpentOnCharacterMatchRequestsMs; // Disable @@ -36,7 +36,7 @@ class CharacterMatchManager //----------------------------------------------------------------------- -inline void CharacterMatchManager::getMatchStatistics(unsigned long &numberOfCharacterMatchRequests, unsigned long &numberOfCharacterMatchResults, unsigned long &timeSpentOnCharacterMatchRequestsMs) +inline void CharacterMatchManager::getMatchStatistics(uint32_t &numberOfCharacterMatchRequests, uint32_t &numberOfCharacterMatchResults, uint32_t &timeSpentOnCharacterMatchRequestsMs) { numberOfCharacterMatchRequests = ms_numberOfCharacterMatchRequests; numberOfCharacterMatchResults = ms_numberOfCharacterMatchResults; diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 78f2c8cac..23dd89bdf 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -1613,8 +1613,7 @@ void Client::receiveClientMessage(const GameNetworkMessage &message) { } case constcrc("UpdateSessionPlayTimeInfo") : { Archive::ReadIterator readIterator = static_cast (message).getByteStream().begin(); - GenericValueTypeMessage < std::pair < int32, std::pair < int32, unsigned - long > > > + GenericValueTypeMessage < std::pair < int32, std::pair < int32, uint32_t > > > const msgPlayTimeInfo(readIterator); PlayerObject *playerObject = PlayerCreatureController::getPlayerObject(safe_cast(getCharacterObject())); diff --git a/engine/server/library/serverGame/src/shared/core/GameServer.cpp b/engine/server/library/serverGame/src/shared/core/GameServer.cpp index 80009486b..456a20d5c 100755 --- a/engine/server/library/serverGame/src/shared/core/GameServer.cpp +++ b/engine/server/library/serverGame/src/shared/core/GameServer.cpp @@ -253,11 +253,11 @@ namespace GameServerNamespace const float IDLE_CLIENTS_CHECK_TIME_SEC = 30.0f; ServerCommandPermissionManager * s_permissionManager = 0; - unsigned long s_frameTime; - uint64 s_totalObjectCreateMessagesReceived; - uint64 s_totalObjectCreateMessagesSent; - bool s_metricsManagerInstalled = false; - uint32 s_lastTaskKeepaliveTime = 0; + uint32_t s_frameTime; + uint64 s_totalObjectCreateMessagesReceived; + uint64 s_totalObjectCreateMessagesSent; + bool s_metricsManagerInstalled = false; + uint32 s_lastTaskKeepaliveTime = 0; #ifdef _DEBUG int s_extraDelayPerFrameMs = 0; // to emulate long loop time @@ -266,11 +266,11 @@ namespace GameServerNamespace std::set s_clusterStartupResidenceStructureListResponse; std::map > s_clusterStartupResidenceStructureListByStructure; - unsigned long getFrameRateLimit(); + uint32_t getFrameRateLimit(); void broadCastHyperspaceOnWarp(ServerObject const * owner); ShipObject *getAttachedShip(CreatureObject *creature); - std::map s_pendingLoadRequests; + std::map s_pendingLoadRequests; struct CtsSourceCharacterInfo { @@ -745,7 +745,7 @@ void GameServer::dropClient(const NetworkId& oid, const bool immediate) //----------------------------------------------------------------------- -unsigned long GameServer::getFrameTime() const +uint32_t GameServer::getFrameTime() const { return s_frameTime; } @@ -895,7 +895,7 @@ void GameServer::receiveMessage(const MessageDispatch::Emitter & source, const M if(Clock::timeMs() - s_lastTaskKeepaliveTime > 60000) { DEBUG_WARNING(true, ("Sending keepalive message to taskmanager for process %i", Os::getProcessId())); - static const GenericValueTypeMessage gameServerTaskManagerKeepAlive("GameServerTaskManagerKeepAlive", Os::getProcessId()); + static const GenericValueTypeMessage gameServerTaskManagerKeepAlive("GameServerTaskManagerKeepAlive", Os::getProcessId()); getInstance().m_taskManagerConnection->send(gameServerTaskManagerKeepAlive, true); s_lastTaskKeepaliveTime = Clock::timeMs(); } @@ -3583,14 +3583,14 @@ void GameServer::receiveMessage2(const MessageDispatch::Emitter & source, const GenericValueTypeMessage const characterMatchStatisticsRequest(ri); UNREF(characterMatchStatisticsRequest); - unsigned long numberOfCharacterMatchRequests, numberOfCharacterMatchResults, timeSpentOnCharacterMatchRequestsMs; + uint32_t numberOfCharacterMatchRequests, numberOfCharacterMatchResults, timeSpentOnCharacterMatchRequestsMs; CharacterMatchManager::getMatchStatistics(numberOfCharacterMatchRequests, numberOfCharacterMatchResults, timeSpentOnCharacterMatchRequestsMs); if (numberOfCharacterMatchRequests || numberOfCharacterMatchResults || timeSpentOnCharacterMatchRequestsMs) { CharacterMatchManager::clearMatchStatistics(); - const GenericValueTypeMessage >> characterMatchStatisticsResponse("LfgStatRsp", std::make_pair(numberOfCharacterMatchRequests, std::make_pair(numberOfCharacterMatchResults, timeSpentOnCharacterMatchRequestsMs))); + const GenericValueTypeMessage >> characterMatchStatisticsResponse("LfgStatRsp", std::make_pair(numberOfCharacterMatchRequests, std::make_pair(numberOfCharacterMatchResults, timeSpentOnCharacterMatchRequestsMs))); sendToCentralServer(characterMatchStatisticsResponse); } @@ -4048,7 +4048,7 @@ bool GameServer::requestSceneWarpDelayed(const CachedNetworkId &objectId, const // ---------------------------------------------------------------------- -unsigned long GameServerNamespace::getFrameRateLimit() +uint32_t GameServerNamespace::getFrameRateLimit() { return ServerWorld::isSpaceScene() ? ConfigServerGame::getSpaceFrameRateLimit() : ConfigServerGame::getGroundFrameRateLimit(); } @@ -4059,17 +4059,17 @@ void GameServer::run(void) { getInstance().initialize(); - unsigned long lastFrameTime = 0; + uint32_t lastFrameTime = 0; int oldFilesOpened = TreeFile::getNumberOfFilesOpenedTotal(); int oldSizeOpened = TreeFile::getSizeOfFilesOpenedTotal(); int newFilesOpened = 0; int newSizeOpened = 0; - unsigned long startTime = Clock::timeMs(); - unsigned long lastFrameProcessStartTime = startTime; + uint32_t startTime = Clock::timeMs(); + uint32_t lastFrameProcessStartTime = startTime; - const unsigned long targetFrameTime = static_cast(1000.0f/getFrameRateLimit()); + const uint32_t targetFrameTime = static_cast(1000.0f/getFrameRateLimit()); - const GenericValueTypeMessage gameServerTaskManagerKeepAlive("GameServerTaskManagerKeepAlive", Os::getProcessId()); + const GenericValueTypeMessage gameServerTaskManagerKeepAlive("GameServerTaskManagerKeepAlive", Os::getProcessId()); PROFILER_BLOCK_DEFINE(profileBlockMainLoop, "main loop"); PROFILER_BLOCK_ENTER(profileBlockMainLoop); @@ -4186,7 +4186,7 @@ void GameServer::run(void) alreadyReported=false; } - unsigned long curTime = Clock::timeMs(); + uint32_t curTime = Clock::timeMs(); lastFrameTime = curTime-startTime; if (!getInstance().getDone()) ServerClock::getInstance().incrementServerFrame(); @@ -5193,11 +5193,11 @@ int GameServer::getNumberOfPendingLoadRequests() // ---------------------------------------------------------------------- -unsigned long GameServer::getOldestPendingLoadRequestTime(NetworkId & id) +uint32_t GameServer::getOldestPendingLoadRequestTime(NetworkId & id) { - unsigned long oldestTime = std::numeric_limits::max(); + uint32_t oldestTime = std::numeric_limits::max(); - std::map::const_iterator i = s_pendingLoadRequests.begin(); + std::map::const_iterator i = s_pendingLoadRequests.begin(); for (; i != s_pendingLoadRequests.end(); ++i) if (i->second < oldestTime) { diff --git a/engine/server/library/serverGame/src/shared/core/GameServer.h b/engine/server/library/serverGame/src/shared/core/GameServer.h index 594f98791..85755bd40 100755 --- a/engine/server/library/serverGame/src/shared/core/GameServer.h +++ b/engine/server/library/serverGame/src/shared/core/GameServer.h @@ -87,7 +87,7 @@ public MessageDispatch::Receiver bool isGameServerConnected (uint32 processId) const; ConnectionServerConnection * getConnectionServerConnection (const std::string & connectionServerIp, const uint16 connectionServerPort); uint32 getFirstGameServerForPlanet (); - unsigned long getFrameTime () const; + uint32_t getFrameTime () const; int getNumClients() const; uint32 getProcessId () const; uint32 getPreloadAreaId () const; @@ -138,7 +138,7 @@ public MessageDispatch::Receiver static bool isAtPendingLoadRequestLimit(); static int getPendingLoadRequestLimit(); static int getNumberOfPendingLoadRequests(); - static unsigned long getOldestPendingLoadRequestTime(NetworkId & id); + static uint32_t getOldestPendingLoadRequestTime(NetworkId & id); static std::string getRetroactiveCtsHistory(std::string const & clusterName, NetworkId const & characterId); static std::vector > const *> const & getRetroactiveCtsHistoryObjvars(NetworkId const & characterId); @@ -230,7 +230,7 @@ public MessageDispatch::Receiver bool m_gameServerReadyObjectIds; bool m_gameServerReadyDatabaseConnected; bool m_gameServerReadyPlanetConnected; - uint32 m_connectionTimeout; + uint32_t m_connectionTimeout; ChatServerConnection * m_chatServerConnection; }; diff --git a/engine/server/library/serverGame/src/shared/core/ReportManager.cpp b/engine/server/library/serverGame/src/shared/core/ReportManager.cpp index 843373c7d..074fb4834 100755 --- a/engine/server/library/serverGame/src/shared/core/ReportManager.cpp +++ b/engine/server/library/serverGame/src/shared/core/ReportManager.cpp @@ -54,12 +54,12 @@ namespace ReportManagerNamespace typedef std::map ReportList; ReportList s_reportList; - typedef std::map ReportThrottle; + typedef std::map ReportThrottle; ReportThrottle s_reportThrottle; - time_t const s_throttleTime = 10; // seconds - time_t const s_throttleCleanupTime = 60; // seconds - time_t s_throttleCleanupTimer = 0; // seconds + uint32_t const s_throttleTime = 10; // seconds + uint32_t const s_throttleCleanupTime = 60; // seconds + uint32_t s_throttleCleanupTimer = 0; // seconds } using namespace ReportManagerNamespace; @@ -114,7 +114,7 @@ void ReportManager::addReport(Unicode::String const &reportingName, NetworkId co { // Remove any expired throttling - time_t const systemTime = Os::getRealSystemTime(); + uint32_t const systemTime = Os::getRealSystemTime(); if ((systemTime - s_throttleCleanupTimer) > s_throttleCleanupTime) { @@ -223,7 +223,7 @@ void ReportManager::handleMessage(ChatOnRequestLog const &chatOnRequestLog) report.append(header); - typedef std::multimap SortedChatLog; + typedef std::multimap SortedChatLog; typedef std::set SortedFromPlayers; SortedChatLog sortedChatLog; SortedFromPlayers sortedFromPlayers; @@ -266,7 +266,7 @@ void ReportManager::handleMessage(ChatOnRequestLog const &chatOnRequestLog) Unicode::String toPlayer; Unicode::String text; Unicode::String channel; - time_t time; + uint32_t time; for (; iterChatLog != chatLog.end(); ++iterChatLog) { diff --git a/engine/server/library/serverGame/src/shared/core/ServerWorld.cpp b/engine/server/library/serverGame/src/shared/core/ServerWorld.cpp index 0a45f4a70..e5b7fb2cd 100755 --- a/engine/server/library/serverGame/src/shared/core/ServerWorld.cpp +++ b/engine/server/library/serverGame/src/shared/core/ServerWorld.cpp @@ -320,20 +320,22 @@ void ServerWorldNamespace::issueCollisionNearWarpWarning(Object const &object, V //-- Only issue these for authoritative server objects. Proxy server objects will hit this condition after an intra-planet teleport. // @todo allow proxies to know about a teleport and inform CollisionWorld so that we can always report these. - DEBUG_WARNING(!serverObject || serverObject->isAuthoritative(), - ("CollisionWorld::update() had %d segments for object id=[%s], template=[%s], authority=[%s], game sever id=[%d], start position=[%.2f,%.2f,%.2f], end position=[%.2f,%.2f,%.2f], object probably should have warped but collision system is not warping it.", - segmentCount, - object.getNetworkId().getValueString().c_str(), - object.getObjectTemplateName(), - serverObject ? (serverObject->isAuthoritative() ? "authoritative" : "proxy") : "", - static_cast(GameServer::getInstance().getProcessId()), - oldPosition_w.x, - oldPosition_w.y, - oldPosition_w.z, - newPosition_w.x, - newPosition_w.y, - newPosition_w.z - )); + if(!serverObject || serverObject->isAuthoritative()) { + DEBUG_WARNING(true, + ("CollisionWorld::update() had %d segments for object id=[%s], template=[%s], authority=[%s], game sever id=[%d], start position=[%.2f,%.2f,%.2f], end position=[%.2f,%.2f,%.2f], object probably should have warped but collision system is not warping it.", + segmentCount, + object.getNetworkId().getValueString().c_str(), + object.getObjectTemplateName(), + serverObject ? (serverObject->isAuthoritative() ? "authoritative" : "proxy") : "", + static_cast(GameServer::getInstance().getProcessId()), + oldPosition_w.x, + oldPosition_w.y, + oldPosition_w.z, + newPosition_w.x, + newPosition_w.y, + newPosition_w.z + )); + } } // ---------------------------------------------------------------------- @@ -344,20 +346,22 @@ void ServerWorldNamespace::issueCollisionFarWarpWarning(Object const &object, Ve //-- Only issue these for authoritative server objects. Proxy server objects will hit this condition after an intra-planet teleport. // @todo allow proxies to know about a teleport and inform CollisionWorld so that we can always report these. - DEBUG_WARNING(!serverObject || serverObject->isAuthoritative(), - ("CollisionWorld::update() had %d segments for object id=[%s], template=[%s], authority=[%s], game sever id=[%d], start position=[%.2f,%.2f,%.2f], end position=[%.2f,%.2f,%.2f], collision system will consider this a warp and adjust accordingly.", - segmentCount, - object.getNetworkId().getValueString().c_str(), - object.getObjectTemplateName(), - serverObject ? (serverObject->isAuthoritative() ? "authoritative" : "proxy") : "", - static_cast(GameServer::getInstance().getProcessId()), - oldPosition_w.x, - oldPosition_w.y, - oldPosition_w.z, - newPosition_w.x, - newPosition_w.y, - newPosition_w.z - )); + if(!serverObject || serverObject->isAuthoritative()) { + DEBUG_WARNING(!serverObject || serverObject->isAuthoritative(), + ("CollisionWorld::update() had %d segments for object id=[%s], template=[%s], authority=[%s], game sever id=[%d], start position=[%.2f,%.2f,%.2f], end position=[%.2f,%.2f,%.2f], collision system will consider this a warp and adjust accordingly.", + segmentCount, + object.getNetworkId().getValueString().c_str(), + object.getObjectTemplateName(), + serverObject ? (serverObject->isAuthoritative() ? "authoritative" : "proxy") : "", + static_cast(GameServer::getInstance().getProcessId()), + oldPosition_w.x, + oldPosition_w.y, + oldPosition_w.z, + newPosition_w.x, + newPosition_w.y, + newPosition_w.z + )); + } } // ---------------------------------------------------------------------- diff --git a/engine/server/library/serverGame/src/shared/network/Chat.cpp b/engine/server/library/serverGame/src/shared/network/Chat.cpp index 345494639..319e82147 100755 --- a/engine/server/library/serverGame/src/shared/network/Chat.cpp +++ b/engine/server/library/serverGame/src/shared/network/Chat.cpp @@ -697,7 +697,7 @@ unsigned int Chat::isAllowedToEnterRoom(const CreatureObject & who, const std::s // thus requiring more work from us here bool isMayor = false; std::vector cityId = CityInterface::getCitizenOfCityId(who.getNetworkId()); - for(int i = 0; i < cityId.size(); ++i){ + for(uint32_t i = 0; i < cityId.size(); ++i){ NetworkId leader = CityInterface::getCityInfo(cityId[i]).getLeaderId(); if(playerObject && who.getNetworkId() == leader) { isMayor = true; diff --git a/engine/server/library/serverGame/src/shared/object/CellPermissions.cpp b/engine/server/library/serverGame/src/shared/object/CellPermissions.cpp index 9d1dc0d09..8c7bc82be 100755 --- a/engine/server/library/serverGame/src/shared/object/CellPermissions.cpp +++ b/engine/server/library/serverGame/src/shared/object/CellPermissions.cpp @@ -620,7 +620,7 @@ bool CellPermissions::isOnList(PermissionList const &permList, CreatureObject co } if (name.rfind("account:", 0) == 0) { - if (std::stoi(name.substr(8, name.length())) == stationId) + if (static_cast(std::stoi(name.substr(8, name.length()))) == stationId) { return true; } diff --git a/engine/server/library/serverGame/src/shared/object/CreatureObject.cpp b/engine/server/library/serverGame/src/shared/object/CreatureObject.cpp index ab0df5831..24b03627b 100755 --- a/engine/server/library/serverGame/src/shared/object/CreatureObject.cpp +++ b/engine/server/library/serverGame/src/shared/object/CreatureObject.cpp @@ -482,7 +482,7 @@ namespace CreatureObjectNamespace { bool creatureIsContainedInPOBShip(CreatureObject const * creatureObject); void findAllTargetsForGroup(CreatureObject * const targetObj, std::vector & targets); - bool roomInGroup(GroupObject const * groupObj, int additionalMembers); + bool roomInGroup(GroupObject const * groupObj, uint32_t additionalMembers); GroupMemberParam const buildGroupMemberParam(CreatureObject const * creatureObject); void buildGroupMemberParamsFromCreatures(std::vector const & targets, GroupObject::GroupMemberParamVector & targetMemberParams); } @@ -6230,7 +6230,7 @@ void CreatureObject::setMood(uint32 mood) } else { - sendControllerMessageToAuthServer(CM_setMood, new MessageQueueGenericValueType(mood)); + sendControllerMessageToAuthServer(CM_setMood, new MessageQueueGenericValueType(mood)); } } @@ -6655,7 +6655,7 @@ void CreatureObject::setSayMode(uint32 sayMode) } else { - sendControllerMessageToAuthServer(CM_setSayMode, new MessageQueueGenericValueType(sayMode)); + sendControllerMessageToAuthServer(CM_setSayMode, new MessageQueueGenericValueType(sayMode)); } } @@ -8722,7 +8722,7 @@ void CreatureObject::setGuildId(int guildId) //----------------------------------------------------------------------- -void CreatureObject::setTimeToUpdateGuildWarPvpStatus(unsigned long timeToUpdateGuildWarPvpStatus) +void CreatureObject::setTimeToUpdateGuildWarPvpStatus(uint32_t timeToUpdateGuildWarPvpStatus) { FATAL(!isAuthoritative(), ("setTimeToUpdateGuildWarPvpStatus called on nonauthoritative object")); m_timeToUpdateGuildWarPvpStatus = timeToUpdateGuildWarPvpStatus; @@ -13510,7 +13510,7 @@ void CreatureObject::pushedMe(const NetworkId & attackerId, * @param slopeAngle the angle of the "hill", in radians * @param expireTime the game time when the effect expires */ -void CreatureObject::addSlowDownEffect(const TangibleObject & defender, float coneLength, float coneAngle, float slopeAngle, unsigned long expireTime) +void CreatureObject::addSlowDownEffect(const TangibleObject & defender, float coneLength, float coneAngle, float slopeAngle, uint32_t expireTime) { if (isAuthoritative()) { @@ -13553,7 +13553,7 @@ void CreatureObject::addSlowDownEffect(const TangibleObject & defender, float co * * @return true if the effect was added, false if the creature already had a slow down effect */ -bool CreatureObject::addSlowDownEffectProxy(const TangibleObject & defender, float coneLength, float coneAngle, float slopeAngle, unsigned long expireTime) +bool CreatureObject::addSlowDownEffectProxy(const TangibleObject & defender, float coneLength, float coneAngle, float slopeAngle, uint32_t expireTime) { // if we already are doing a slowdown, don't do another Property * property = getProperty(SlowDownProperty::getClassPropertyId()); @@ -14235,7 +14235,7 @@ void CreatureObject::setRegenRate(Attributes::Enumerator poolAttrib, float value // ---------------------------------------------------------------------- -void CreatureObject::setLastWaterDamageTime(unsigned long newTime) +void CreatureObject::setLastWaterDamageTime(uint32_t newTime) { m_lastWaterDamageTime = newTime; } @@ -14995,14 +14995,13 @@ void CreatureObjectNamespace::GroupHelpers::findAllTargetsForGroup(CreatureObjec // ---------------------------------------------------------------------- -bool CreatureObjectNamespace::GroupHelpers::roomInGroup(GroupObject const * groupObj, int additionalMembers) +bool CreatureObjectNamespace::GroupHelpers::roomInGroup(GroupObject const * groupObj, uint32_t additionalMembers) { if (groupObj != 0) { return groupObj->doesGroupHaveRoomFor(additionalMembers); } - additionalMembers = std::max(0, additionalMembers); return additionalMembers < GroupObject::maximumMembersInGroup(); } @@ -15345,7 +15344,7 @@ void CreatureObject::addPackedAppearanceWearable(std::string const &appearanceDa void CreatureObject::saveDecorationLayout(ServerObject const & pobSourceObject, int saveSlotNumber, std::string const & description) { int debugNumItems = 0; - const unsigned long debugStartTimeMs = Clock::timeMs(); + const uint32_t debugStartTimeMs = Clock::timeMs(); if (!isAuthoritative()) return; @@ -15539,7 +15538,7 @@ void CreatureObject::saveDecorationLayout(ServerObject const & pobSourceObject, if ((debugNumItems > 0) && getClient()->isGod()) { - const unsigned long debugEndTimeMs = Clock::timeMs(); + const uint32_t debugEndTimeMs = Clock::timeMs(); Chat::sendSystemMessage(*this, Unicode::narrowToWide(FormattedString<256>().sprintf("!!!GOD MODE STATISTICS!!! %d items saved in %lums", debugNumItems, (debugEndTimeMs - debugStartTimeMs))), Unicode::emptyString); } } @@ -15548,7 +15547,7 @@ void CreatureObject::saveDecorationLayout(ServerObject const & pobSourceObject, void CreatureObject::restoreDecorationLayout(ServerObject const & pobTargetObject, int saveSlotNumber) { - const unsigned long debugStartTimeMs = Clock::timeMs(); + const uint32_t debugStartTimeMs = Clock::timeMs(); if (!isAuthoritative()) return; @@ -15884,7 +15883,7 @@ void CreatureObject::restoreDecorationLayout(ServerObject const & pobTargetObjec if ((debugNumItems > 0) && getClient()->isGod()) { - const unsigned long debugEndTimeMs = Clock::timeMs(); + const uint32_t debugEndTimeMs = Clock::timeMs(); Chat::sendSystemMessage(*this, Unicode::narrowToWide(FormattedString<256>().sprintf("!!!GOD MODE STATISTICS!!! %d items read (%d will be moved) in %lums", debugNumItems, numItemsToBeMoved, (debugEndTimeMs - debugStartTimeMs))), Unicode::emptyString); } } diff --git a/engine/server/library/serverGame/src/shared/object/CreatureObject.h b/engine/server/library/serverGame/src/shared/object/CreatureObject.h index ab06cefde..7dd20d2d8 100755 --- a/engine/server/library/serverGame/src/shared/object/CreatureObject.h +++ b/engine/server/library/serverGame/src/shared/object/CreatureObject.h @@ -385,8 +385,8 @@ class CreatureObject : public TangibleObject void setPerformanceWatchTarget(NetworkId const &who); int getGuildId() const; void setGuildId(int guildId); - unsigned long getTimeToUpdateGuildWarPvpStatus() const; - void setTimeToUpdateGuildWarPvpStatus(unsigned long timeToUpdateGuildWarPvpStatus); + uint32_t getTimeToUpdateGuildWarPvpStatus() const; + void setTimeToUpdateGuildWarPvpStatus(uint32_t timeToUpdateGuildWarPvpStatus); bool getGuildWarEnabled() const; void setGuildWarEnabled(bool guildWarEnabled); int getMilitiaOfCityId() const; @@ -546,8 +546,8 @@ class CreatureObject : public TangibleObject int loadPackedHouses(); void setClientUsesAnimationLocomotion(bool const enabled); - void addSlowDownEffect(const TangibleObject & defender, float coneLength, float coneAngle, float slopeAngle, unsigned long expireTime); - bool addSlowDownEffectProxy(const TangibleObject & defender, float coneLength, float coneAngle, float slopeAngle, unsigned long expireTime); + void addSlowDownEffect(const TangibleObject & defender, float coneLength, float coneAngle, float slopeAngle, uint32_t expireTime); + bool addSlowDownEffectProxy(const TangibleObject & defender, float coneLength, float coneAngle, float slopeAngle, uint32_t expireTime); void removeSlowDownEffect(); void removeSlowDownEffectProxy(); void addTerrainSlopeEffect(const Vector & normal); @@ -645,8 +645,8 @@ class CreatureObject : public TangibleObject void setRegenRate(Attributes::Enumerator poolAttrib, float value); float getLavaResistance() const; - unsigned long getLastWaterDamageTime() const; - void setLastWaterDamageTime(unsigned long newTime); + uint32_t getLastWaterDamageTime() const; + void setLastWaterDamageTime(uint32_t newTime); std::map const & getCommandList() const; void clearCommands(); @@ -862,7 +862,7 @@ class CreatureObject : public TangibleObject // when switching guild war pvp status using the guild war exemption/exclusive list, // add a delay to when the actually switch takes place, to prevent exploit of quickly // switching in and out guiild war pvp using the guild war exemption/exclusive list - Archive::AutoDeltaVariable m_timeToUpdateGuildWarPvpStatus; + Archive::AutoDeltaVariable m_timeToUpdateGuildWarPvpStatus; Archive::AutoDeltaVariableObserver m_guildWarEnabled; Archive::AutoDeltaVariableObserver m_militiaOfCityId; @@ -1000,7 +1000,7 @@ class CreatureObject : public TangibleObject bool m_fixedupPersistentBuffsAfterLoading; bool m_fixedupLevelXpAfterLoading; float m_lavaResistance; - unsigned long m_lastWaterDamageTime; // used for timing last damage taken by lava (and other future harmful water types) + uint32_t m_lastWaterDamageTime; // used for timing last damage taken by lava (and other future harmful water types) float m_attribRegenMultipliers[AR_count]; Archive::AutoDeltaMap m_commands; // game commands a creature may execute @@ -1350,7 +1350,7 @@ inline float CreatureObject::getLavaResistance() const //----------------------------------------------------------------------- -inline unsigned long CreatureObject::getLastWaterDamageTime() const +inline uint32_t CreatureObject::getLastWaterDamageTime() const { return m_lastWaterDamageTime; } @@ -1412,7 +1412,7 @@ inline int CreatureObject::getGuildId() const //----------------------------------------------------------------------- -inline unsigned long CreatureObject::getTimeToUpdateGuildWarPvpStatus() const +inline uint32_t CreatureObject::getTimeToUpdateGuildWarPvpStatus() const { return m_timeToUpdateGuildWarPvpStatus.get(); } diff --git a/engine/server/library/serverGame/src/shared/object/GroupObject.cpp b/engine/server/library/serverGame/src/shared/object/GroupObject.cpp index 2aad93283..cfc0795ee 100755 --- a/engine/server/library/serverGame/src/shared/object/GroupObject.cpp +++ b/engine/server/library/serverGame/src/shared/object/GroupObject.cpp @@ -55,7 +55,7 @@ namespace GroupObjectNamespace { // ---------------------------------------------------------------------- - unsigned int const cs_maximumNumberInGroup = 8; + const uint32_t cs_maximumNumberInGroup = 8; char const * const DEFAULT_GROUP_TEMPLATE = "object/group/group.iff"; std::map s_leaderMap; static const std::string cs_emptyString; @@ -226,7 +226,7 @@ void GroupObject::createAllGroupChatRooms() // static // ---------------------------------------------------------------------- -int GroupObject::maximumMembersInGroup() +uint32_t GroupObject::maximumMembersInGroup() { return cs_maximumNumberInGroup; } @@ -327,9 +327,8 @@ bool GroupObject::isMemberPC(NetworkId const & memberId) const // ---------------------------------------------------------------------- -bool GroupObject::doesGroupHaveRoomFor(int additionalMembers) const +bool GroupObject::doesGroupHaveRoomFor(uint32_t additionalMembers) const { - additionalMembers = std::max(0, additionalMembers); return (m_groupMembers.size() + additionalMembers) <= cs_maximumNumberInGroup; } @@ -519,7 +518,7 @@ void GroupObject::removeGroupMember(NetworkId const &memberId) else { GroupUpdateObserver updater(this, Archive::ADOO_generic); - for (unsigned int i = 0; i < m_groupMembers.size(); ++i) + for (uint32_t i = 0; i < m_groupMembers.size(); ++i) { GroupMember const & member = m_groupMembers.get(i); if (member.first == memberId) @@ -535,7 +534,7 @@ void GroupObject::removeGroupMember(NetworkId const &memberId) m_groupMemberProfessions.erase(i); calcGroupLevel(); - for (unsigned int j = 0; j < m_groupPOBShipAndOwners.size(); ++j) + for (uint32_t j = 0; j < m_groupPOBShipAndOwners.size(); ++j) { if (m_groupPOBShipAndOwners.get(j).second == memberId) { @@ -603,7 +602,7 @@ void GroupObject::disbandGroup() } else if (!getKill()) { - for (unsigned int i = 0; i < m_groupMembers.size(); ++i) + for (uint32_t i = 0; i < m_groupMembers.size(); ++i) { GroupMember const & member = m_groupMembers.get(i); removeFromGroupVoiceChatRoom(member.first, member.second); diff --git a/engine/server/library/serverGame/src/shared/object/GroupObject.h b/engine/server/library/serverGame/src/shared/object/GroupObject.h index e9e98519f..aa143b23f 100755 --- a/engine/server/library/serverGame/src/shared/object/GroupObject.h +++ b/engine/server/library/serverGame/src/shared/object/GroupObject.h @@ -47,7 +47,7 @@ class GroupObject: public UniverseObject static void removeFromLeaderMap (NetworkId const &leaderId, NetworkId const &groupId); static NetworkId getGroupIdForLeader (NetworkId const &leaderId); static void createAllGroupChatRooms (); - static int maximumMembersInGroup(); + static uint32_t maximumMembersInGroup(); typedef std::pair GroupMember; typedef std::vector GroupMemberVector; @@ -61,7 +61,7 @@ class GroupObject: public UniverseObject bool isGroupFull () const; int getPCMemberCount () const; bool isMemberPC(NetworkId const & memberId) const; - bool doesGroupHaveRoomFor(int additionalMembers) const; + bool doesGroupHaveRoomFor(uint32_t additionalMembers) const; GroupMemberVector const & getGroupMembers () const; int getGroupLevel () const; uint32 getFormationNameCrc() const; diff --git a/engine/server/library/serverGame/src/shared/object/PlanetObject.cpp b/engine/server/library/serverGame/src/shared/object/PlanetObject.cpp index 0ecbb8d62..29ae6e719 100755 --- a/engine/server/library/serverGame/src/shared/object/PlanetObject.cpp +++ b/engine/server/library/serverGame/src/shared/object/PlanetObject.cpp @@ -2349,7 +2349,7 @@ void PlanetObject::adjustGcwImperialScore(std::string const & source, CreatureOb // grant GCW Region Defender bonus float bonus = 0.0f; if (gcwCategoryData->gcwRegionDefender && PvpData::isImperialFactionId(sourceObject->getPvpFaction()) && (adjustment > 0) && (playerObject->getCurrentGcwRegion() == gcwCategory) && Pvp::getGcwDefenderRegionBonus(*sourceObject, *playerObject, bonus) && (bonus > 0.0f)) - adjustment += std::max(1ll, static_cast(static_cast(bonus) * static_cast(adjustment) / static_cast(100))); + adjustment += static_cast(std::max(static_cast(1), static_cast(bonus) * static_cast(adjustment) / 100)); } LOG("CustomerService", ("GcwScore: imperial %s %d (from %s - %s)", gcwCategory.c_str(), static_cast(adjustment), source.c_str(), sourceObject->getNetworkId().getValueString().c_str())); @@ -2394,7 +2394,7 @@ void PlanetObject::adjustGcwRebelScore(std::string const & source, CreatureObjec // grant GCW Region Defender bonus float bonus = 0.0f; if (gcwCategoryData->gcwRegionDefender && PvpData::isRebelFactionId(sourceObject->getPvpFaction()) && (adjustment > 0) && (playerObject->getCurrentGcwRegion() == gcwCategory) && Pvp::getGcwDefenderRegionBonus(*sourceObject, *playerObject, bonus) && (bonus > 0.0f)) - adjustment += std::max(1ll, static_cast(static_cast(bonus) * static_cast(adjustment) / static_cast(100))); + adjustment += static_cast(std::max(static_cast(1), static_cast(bonus) * static_cast(adjustment) / 100)); } LOG("CustomerService", ("GcwScore: rebel %s %d (from %s - %s)", gcwCategory.c_str(), static_cast(adjustment), source.c_str(), sourceObject->getNetworkId().getValueString().c_str())); diff --git a/engine/server/library/serverGame/src/shared/object/PlayerObject.cpp b/engine/server/library/serverGame/src/shared/object/PlayerObject.cpp index 615c88247..f429e552d 100755 --- a/engine/server/library/serverGame/src/shared/object/PlayerObject.cpp +++ b/engine/server/library/serverGame/src/shared/object/PlayerObject.cpp @@ -511,11 +511,11 @@ int PlayerObject::getCurrentBornDate() baseTimeData.tm_wday = 0; baseTimeData.tm_yday = 0; baseTimeData.tm_year = 101; - time_t baseTime = mktime(&baseTimeData); + uint32_t baseTime = mktime(&baseTimeData); // get the current time and compute the birth date - time_t currentTime = time(nullptr); - time_t delta = (currentTime - baseTime) / (60 * 60 * 24); + uint32_t currentTime = time(nullptr); + uint32_t delta = (currentTime - baseTime) / (60 * 60 * 24); delta += ((currentTime - baseTime) % (60 * 60 * 24) != 0 ? 1 : 0); return int(delta); } // PlayerObject::getCurrentBornDate @@ -859,7 +859,7 @@ int PlayerObject::grantExperiencePoints(const std::string & experienceType, int if (ConfigServerScript::getLogBalance() && (total != current)) { // log the grant - unsigned long time = ServerClock::getInstance().getGameTimeSeconds(); + uint32_t time = ServerClock::getInstance().getGameTimeSeconds(); LOG("GameBalance", ("balancelog:%d:XP;%lu;%s;%s;%d;%d;%d;%d", static_cast(GameServer::getInstance().getProcessId()), time, owner->getNetworkId().getValueString().c_str(), experienceType.c_str(), @@ -4231,7 +4231,7 @@ void PlayerObject::handleCMessageTo(const MessageToPayload &message) { // see if guild war pvp status has changed, and if yes, start countdown timer to change the status if (GuildInterface::getGuildMemberGuildWarEnabled(owner->getGuildId(), owner->getNetworkId()) != owner->getGuildWarEnabled()) - owner->setTimeToUpdateGuildWarPvpStatus(ServerClock::getInstance().getGameTimeSeconds() + static_cast(ConfigServerGame::getPvpGuildWarExemptionExclusiveDelaySeconds())); + owner->setTimeToUpdateGuildWarPvpStatus(ServerClock::getInstance().getGameTimeSeconds() + static_cast(ConfigServerGame::getPvpGuildWarExemptionExclusiveDelaySeconds())); } else if (owner->getGuildWarEnabled()) { @@ -4770,7 +4770,7 @@ void PlayerObject::logChat(int const logIndex) { if (m_chatLog != nullptr) { - time_t const logTime = Os::getRealSystemTime(); + uint32_t const logTime = Os::getRealSystemTime(); ChatLogEntry chatLogEntry; @@ -4834,13 +4834,13 @@ void PlayerObject::cleanChatLog() // See if anything needs to be purged from the front of the logs - time_t const chatLogTime = ConfigServerUtility::getChatLogMinutes() * 60; + uint32_t const chatLogTime = ConfigServerUtility::getChatLogMinutes() * 60; int chatLogCount = static_cast(m_chatLog->size()); ChatLog::iterator iterChatLog = m_chatLog->begin(); while (!m_chatLog->empty()) { - const time_t messageTime = iterChatLog->m_time; + const uint32_t messageTime = iterChatLog->m_time; if (messageTime < (currentTime - chatLogTime) || (chatLogCount > ConfigServerUtility::getPlayerMaxChatLogLines())) { @@ -6115,7 +6115,7 @@ void PlayerObject::getByteStreamFromAutoVariable(const std::string & name, Archi { if(name == "quests") { - Archive::AutoDeltaMap(m_quests).pack(target); + Archive::AutoDeltaMap(m_quests).pack(target); } else if(name == "completedQuests") { @@ -6202,11 +6202,11 @@ void PlayerObject::setAutoVariableFromByteStream(const std::string & name, const Archive::ReadIterator ri(source); if(name == "quests") { - typedef Archive::AutoDeltaMap::Command Commands; + typedef Archive::AutoDeltaMap::Command Commands; std::vector quests; m_quests.clear(); - Archive::AutoDeltaMap(m_quests).unpack(ri, quests); + Archive::AutoDeltaMap(m_quests).unpack(ri, quests); for (std::vector::const_iterator questIter = quests.begin(); questIter != quests.end(); ++questIter) { @@ -6337,14 +6337,14 @@ void PlayerObject::setPlayedTimeAccumOnly(float playedTimeAccum) // ---------------------------------------------------------------------- -unsigned long PlayerObject::getSessionPlayTimeDuration() const +int32_t PlayerObject::getSessionPlayTimeDuration() const { - time_t const sessionStartPlayTime = static_cast(m_sessionStartPlayTime.get()); + int32_t const sessionStartPlayTime = m_sessionStartPlayTime.get(); if (sessionStartPlayTime > 0) { - time_t const now = ::time(nullptr); + int32_t const now = ::time(nullptr); if (now > sessionStartPlayTime) - return static_cast(now - sessionStartPlayTime); + return (now - sessionStartPlayTime); } return 0; @@ -6352,16 +6352,16 @@ unsigned long PlayerObject::getSessionPlayTimeDuration() const // ---------------------------------------------------------------------- -unsigned long PlayerObject::getSessionActivePlayTimeDuration() const +int32_t PlayerObject::getSessionActivePlayTimeDuration() const { - unsigned long activePlayTimeDuration = m_sessionActivePlayTimeDuration.get(); + int32_t activePlayTimeDuration = m_sessionActivePlayTimeDuration.get(); - time_t const sessionLastActiveTime = static_cast(m_sessionLastActiveTime.get()); + int32_t const sessionLastActiveTime = m_sessionLastActiveTime.get(); if (sessionLastActiveTime > 0) { - time_t const now = ::time(nullptr); + int32_t const now = ::time(nullptr); if (now > sessionLastActiveTime) - activePlayTimeDuration += static_cast(now - sessionLastActiveTime); + activePlayTimeDuration += (now - sessionLastActiveTime); } return activePlayTimeDuration; @@ -6369,7 +6369,7 @@ unsigned long PlayerObject::getSessionActivePlayTimeDuration() const // ---------------------------------------------------------------------- -void PlayerObject::setSessionPlayTimeInfo(int32 sessionStartPlayTime, int32 sessionLastActiveTime, unsigned long sessionActivePlayTimeDuration) +void PlayerObject::setSessionPlayTimeInfo(int32 sessionStartPlayTime, int32 sessionLastActiveTime, uint32_t sessionActivePlayTimeDuration) { // shouldn't be calling this on a non-auth object if (!isAuthoritative()) @@ -6447,7 +6447,7 @@ int PlayerObject::getRoleIconChoice() const void PlayerObject::setAggroImmuneDuration(int const time) { - m_aggroImmuneDuration = static_cast(time); + m_aggroImmuneDuration = static_cast(time); m_aggroImmuneStartTime = Os::getRealSystemTime(); } @@ -6455,7 +6455,7 @@ void PlayerObject::setAggroImmuneDuration(int const time) bool PlayerObject::isAggroImmune() const { - time_t const elapsedTime = Os::getRealSystemTime() - m_aggroImmuneStartTime.get(); + uint32_t const elapsedTime = Os::getRealSystemTime() - m_aggroImmuneStartTime.get(); return (elapsedTime < m_aggroImmuneDuration.get()); } @@ -7185,7 +7185,7 @@ void PlayerObject::setNextGcwRatingCalcTime(bool const alwaysSendMessageToForRec { if (m_nextGcwRatingCalcTime.get() <= 0) { - time_t const nextCalcTime = CalendarTime::getNextGMTTimeOcurrence(static_cast(now), ConfigServerGame::getGcwRecalcTimeDayOfWeek(), ConfigServerGame::getGcwRecalcTimeHour(), ConfigServerGame::getGcwRecalcTimeMinute(), ConfigServerGame::getGcwRecalcTimeSecond()); + uint32_t const nextCalcTime = CalendarTime::getNextGMTTimeOcurrence(static_cast(now), ConfigServerGame::getGcwRecalcTimeDayOfWeek(), ConfigServerGame::getGcwRecalcTimeHour(), ConfigServerGame::getGcwRecalcTimeMinute(), ConfigServerGame::getGcwRecalcTimeSecond()); if (nextCalcTime > 0) { m_nextGcwRatingCalcTime = static_cast(nextCalcTime); @@ -7250,14 +7250,14 @@ void PlayerObject::handleRecalculateGcwRating() totalRatingAdjustment = Pvp::calculateRatingAdjustment(static_cast(points), static_cast(currentRating), totalEarnedRating, totalEarnedRatingAfterDecay, cappedRatingAdjustment); // don't apply rating loss if we are in a "rating loss exclusion interval" - if ((totalRatingAdjustment < 0) && (Pvp::isInGcwRankDecayExclusionInterval(static_cast(nextCalcInterval)))) + if ((totalRatingAdjustment < 0) && (Pvp::isInGcwRankDecayExclusionInterval(static_cast(nextCalcInterval)))) { // CS log LOG("CustomerService", ("PvP_Ranking:%s|NOT APPLYING RATING LOSS|interval %ld (%s) (%s)|current rating=%ld|points=%ld|total earned rating=%ld|total earned rating after decay=%ld|capped rating adjustment=%ld|final rating adjustment=%ld", getAccountDescription().c_str(), nextCalcInterval, - CalendarTime::convertEpochToTimeStringGMT(static_cast(nextCalcInterval)).c_str(), - CalendarTime::convertEpochToTimeStringLocal(static_cast(nextCalcInterval)).c_str(), + CalendarTime::convertEpochToTimeStringGMT(static_cast(nextCalcInterval)).c_str(), + CalendarTime::convertEpochToTimeStringLocal(static_cast(nextCalcInterval)).c_str(), currentRating, points, totalEarnedRating, @@ -7279,8 +7279,8 @@ void PlayerObject::handleRecalculateGcwRating() LOG("CustomerService", ("PvP_Ranking:%s|interval %ld (%s) (%s)|current rating=%ld|new rating=%ld|points=%ld|total earned rating=%ld|total earned rating after decay=%ld|capped rating adjustment=%ld|final rating adjustment=%ld", getAccountDescription().c_str(), nextCalcInterval, - CalendarTime::convertEpochToTimeStringGMT(static_cast(nextCalcInterval)).c_str(), - CalendarTime::convertEpochToTimeStringLocal(static_cast(nextCalcInterval)).c_str(), + CalendarTime::convertEpochToTimeStringGMT(static_cast(nextCalcInterval)).c_str(), + CalendarTime::convertEpochToTimeStringLocal(static_cast(nextCalcInterval)).c_str(), previousRating, currentRating, points, @@ -7294,7 +7294,7 @@ void PlayerObject::handleRecalculateGcwRating() points = 0; // check to see if we need to do another calculation for the next interval - nextCalcInterval = static_cast(CalendarTime::getNextGMTTimeOcurrence(static_cast(nextCalcInterval)+1, ConfigServerGame::getGcwRecalcTimeDayOfWeek(), ConfigServerGame::getGcwRecalcTimeHour(), ConfigServerGame::getGcwRecalcTimeMinute(), ConfigServerGame::getGcwRecalcTimeSecond())); + nextCalcInterval = static_cast(CalendarTime::getNextGMTTimeOcurrence(static_cast(nextCalcInterval)+1, ConfigServerGame::getGcwRecalcTimeDayOfWeek(), ConfigServerGame::getGcwRecalcTimeHour(), ConfigServerGame::getGcwRecalcTimeMinute(), ConfigServerGame::getGcwRecalcTimeSecond())); if (nextCalcInterval <= 0) break; @@ -7406,7 +7406,7 @@ void PlayerObject::addSessionActivity(uint32 activity) { CreatureObject * const owner = getCreatureObject(); if (owner) - owner->sendControllerMessageToAuthServer(CM_addSessionActivity, new MessageQueueGenericValueType(static_cast(activity))); + owner->sendControllerMessageToAuthServer(CM_addSessionActivity, new MessageQueueGenericValueType(static_cast(activity))); } } @@ -7618,7 +7618,7 @@ bool PlayerObject::modifyCollectionSlotValue(std::string const & slotName, int64 if (currentSlotValue != newSlotValue) { BitArray b = collections->get(); - b.setValue(slotInfo->beginSlotId, slotInfo->endSlotId, static_cast(newSlotValue)); + b.setValue(slotInfo->beginSlotId, slotInfo->endSlotId, static_cast(newSlotValue)); collections->set(b); LOG("CustomerService", ("Collection:%s modified collection %d-%d (%s/%s/%s/%s) from %lu to %lu", @@ -7629,10 +7629,10 @@ bool PlayerObject::modifyCollectionSlotValue(std::string const & slotName, int64 slotInfo->collection.page.name.c_str(), slotInfo->collection.name.c_str(), slotInfo->name.c_str(), - static_cast(currentSlotValue), - static_cast(newSlotValue))); + static_cast(currentSlotValue), + static_cast(newSlotValue))); - bool const completedCollectionSlot = hasCompletedCollectionSlot(*slotInfo, static_cast(newSlotValue)); + bool const completedCollectionSlot = hasCompletedCollectionSlot(*slotInfo, static_cast(newSlotValue)); // for "server first" tracking, we need to check if the collection // is completed *BEFORE* triggering script, because script may clear @@ -7692,7 +7692,7 @@ bool PlayerObject::modifyCollectionSlotValue(std::string const & slotName, int64 // ---------------------------------------------------------------------- -bool PlayerObject::getCollectionSlotValue(std::string const & slotName, unsigned long & value) const +bool PlayerObject::getCollectionSlotValue(std::string const & slotName, uint32_t & value) const { value = 0; @@ -7708,7 +7708,7 @@ bool PlayerObject::getCollectionSlotValue(std::string const & slotName, unsigned // ---------------------------------------------------------------------- -bool PlayerObject::getCollectionSlotValue(CollectionsDataTable::CollectionInfoSlot const & slotInfo, unsigned long & value) const +bool PlayerObject::getCollectionSlotValue(CollectionsDataTable::CollectionInfoSlot const & slotInfo, uint32_t & value) const { // bit-type slot if (!slotInfo.counterTypeSlot) @@ -7795,7 +7795,7 @@ bool PlayerObject::hasCompletedCollectionSlot(CollectionsDataTable::CollectionIn // ---------------------------------------------------------------------- -bool PlayerObject::hasCompletedCollectionSlot(CollectionsDataTable::CollectionInfoSlot const & slotInfo, unsigned long slotValue) +bool PlayerObject::hasCompletedCollectionSlot(CollectionsDataTable::CollectionInfoSlot const & slotInfo, uint32_t slotValue) { // bit-type slot if (!slotInfo.counterTypeSlot) @@ -8123,7 +8123,7 @@ void PlayerObject::updateChatSpamSpatialNumCharacters(NetworkId const & characte // sync chat character count with chat server if ((syncChatServer) || (timeNow > m_chatSpamNextTimeToSyncWithChatServer.get())) { - time_t timeUnsquelch = static_cast(getSecondsUntilUnsquelched()); + uint32_t timeUnsquelch = static_cast(getSecondsUntilUnsquelched()); if (timeUnsquelch > 0) timeUnsquelch += ::time(nullptr); @@ -8166,7 +8166,7 @@ void PlayerObject::handleChatStatisticsFromChatServer(NetworkId const & characte // sync chat character count with chat server if (syncChatServer || ((spatialNumCharacters != m_chatSpamSpatialNumCharacters.get()) && (timeNow > m_chatSpamNextTimeToSyncWithChatServer.get()))) { - time_t timeUnsquelch = static_cast(getSecondsUntilUnsquelched()); + uint32_t timeUnsquelch = static_cast(getSecondsUntilUnsquelched()); if (timeUnsquelch > 0) timeUnsquelch += ::time(nullptr); diff --git a/engine/server/library/serverGame/src/shared/object/PlayerObject.h b/engine/server/library/serverGame/src/shared/object/PlayerObject.h index eab82de30..598cdc3bc 100755 --- a/engine/server/library/serverGame/src/shared/object/PlayerObject.h +++ b/engine/server/library/serverGame/src/shared/object/PlayerObject.h @@ -60,7 +60,7 @@ class PlayerObject : public IntangibleObject ChatLogEntry(); int m_index; - time_t m_time; + uint32_t m_time; }; typedef std::list ChatLog; @@ -105,11 +105,11 @@ class PlayerObject : public IntangibleObject float getPlayedTimeAccumOnly() const; void setPlayedTimeAccumOnly(float playedTimeAccum); - unsigned long getSessionPlayTimeDuration() const; - unsigned long getSessionActivePlayTimeDuration() const; + int32_t getSessionPlayTimeDuration() const; + int32_t getSessionActivePlayTimeDuration() const; int32 getSessionStartPlayTime() const; int32 getSessionLastActiveTime() const; - void setSessionPlayTimeInfo(int32 sessionStartPlayTime, int32 sessionLastActiveTime, unsigned long sessionActivePlayTimeDuration); + void setSessionPlayTimeInfo(int32 sessionStartPlayTime, int32 sessionLastActiveTime, uint32_t sessionActivePlayTimeDuration); void setStationId(StationId account); void setCheaterLevel(float level); @@ -358,15 +358,15 @@ class PlayerObject : public IntangibleObject bool modifyCollectionSlotValue(std::string const & slotName, int64 delta); - bool getCollectionSlotValue(std::string const & slotName, unsigned long & value) const; - bool getCollectionSlotValue(CollectionsDataTable::CollectionInfoSlot const & slotInfo, unsigned long & value) const; + bool getCollectionSlotValue(std::string const & slotName, uint32_t & value) const; + bool getCollectionSlotValue(CollectionsDataTable::CollectionInfoSlot const & slotInfo, uint32_t & value) const; bool hasCompletedCollectionSlotPrereq(std::string const & slotName, std::vector * collectionInfo = nullptr) const; bool hasCompletedCollectionSlotPrereq(CollectionsDataTable::CollectionInfoSlot const & slotInfo, std::vector * collectionInfo = nullptr) const; bool hasCompletedCollectionSlot(std::string const & slotName) const; bool hasCompletedCollectionSlot(CollectionsDataTable::CollectionInfoSlot const & slotInfo) const; - static bool hasCompletedCollectionSlot(CollectionsDataTable::CollectionInfoSlot const & slotInfo, unsigned long slotValue); + static bool hasCompletedCollectionSlot(CollectionsDataTable::CollectionInfoSlot const & slotInfo, uint32_t slotValue); bool hasCompletedCollection(std::string const & collectionName) const; @@ -395,8 +395,8 @@ class PlayerObject : public IntangibleObject int getChatSpamTimeEndInterval() const; - time_t getChatSpamNextTimeToNotifyPlayerWhenLimited() const; - void setChatSpamNextTimeToNotifyPlayerWhenLimited(time_t chatSpamNextTimeToNotifyPlayerWhenLimited); + int32_t getChatSpamNextTimeToNotifyPlayerWhenLimited() const; + void setChatSpamNextTimeToNotifyPlayerWhenLimited(int32_t chatSpamNextTimeToNotifyPlayerWhenLimited); // citizenship info void updateCitizenshipInfo(); @@ -554,7 +554,7 @@ class PlayerObject : public IntangibleObject // cached here for use by the game server Archive::AutoDeltaVariable m_sessionStartPlayTime; // time when the player started playing the character Archive::AutoDeltaVariable m_sessionLastActiveTime; // the client will detect when the player is "active" or "inactive"; this keeps track of the last time that the client said the player was "active"; if 0, it means the client is currently "inactive" - Archive::AutoDeltaVariable m_sessionActivePlayTimeDuration; // total amount of play time player was active (i.e. at the mouse/keyboard/joystick) + Archive::AutoDeltaVariable m_sessionActivePlayTimeDuration; // total amount of play time player was active (i.e. at the mouse/keyboard/joystick) Archive::AutoDeltaVariable m_food; Archive::AutoDeltaVariable m_maxFood; @@ -581,8 +581,8 @@ class PlayerObject : public IntangibleObject Archive::AutoDeltaVariable m_theaterId; Archive::AutoDeltaVariable m_theaterLocationType; Archive::AutoDeltaVariable m_roleIconChoice; - Archive::AutoDeltaVariable m_aggroImmuneDuration; - Archive::AutoDeltaVariable m_aggroImmuneStartTime; + Archive::AutoDeltaVariable m_aggroImmuneDuration; + Archive::AutoDeltaVariable m_aggroImmuneStartTime; ChatLog * const m_chatLog; time_t m_chatLogPurgeTime; @@ -641,7 +641,7 @@ class PlayerObject : public IntangibleObject Archive::AutoDeltaVariable m_chatSpamNonSpatialNumCharacters; Archive::AutoDeltaVariable m_chatSpamTimeEndInterval; Archive::AutoDeltaVariable m_chatSpamNextTimeToSyncWithChatServer; - time_t m_chatSpamNextTimeToNotifyPlayerWhenLimited; + int32_t m_chatSpamNextTimeToNotifyPlayerWhenLimited; // citizenship info Archive::AutoDeltaVariable m_citizenshipCity; @@ -1053,14 +1053,14 @@ inline int PlayerObject::getChatSpamTimeEndInterval() const // ---------------------------------------------------------------------- -inline time_t PlayerObject::getChatSpamNextTimeToNotifyPlayerWhenLimited() const +inline int32_t PlayerObject::getChatSpamNextTimeToNotifyPlayerWhenLimited() const { return m_chatSpamNextTimeToNotifyPlayerWhenLimited; } // ---------------------------------------------------------------------- -inline void PlayerObject::setChatSpamNextTimeToNotifyPlayerWhenLimited(time_t chatSpamNextTimeToNotifyPlayerWhenLimited) +inline void PlayerObject::setChatSpamNextTimeToNotifyPlayerWhenLimited(int32_t chatSpamNextTimeToNotifyPlayerWhenLimited) { m_chatSpamNextTimeToNotifyPlayerWhenLimited = chatSpamNextTimeToNotifyPlayerWhenLimited; } diff --git a/engine/server/library/serverGame/src/shared/object/ResourcePoolObject.cpp b/engine/server/library/serverGame/src/shared/object/ResourcePoolObject.cpp index 82e2a710d..92d2404a6 100755 --- a/engine/server/library/serverGame/src/shared/object/ResourcePoolObject.cpp +++ b/engine/server/library/serverGame/src/shared/object/ResourcePoolObject.cpp @@ -54,7 +54,7 @@ ResourcePoolObject::~ResourcePoolObject() */ float ResourcePoolObject::harvest(float installedEfficiency, uint32 lastHarvestTime) const { - int elapsedTime=static_cast(std::min(ServerClock::getInstance().getGameTimeSeconds(),m_depletedTimestamp) - lastHarvestTime); + uint32_t elapsedTime=static_cast(std::min(ServerClock::getInstance().getGameTimeSeconds(),static_cast(m_depletedTimestamp)) - lastHarvestTime); if (elapsedTime < 0) return 0; float elapsedTicks =static_cast(elapsedTime) / static_cast(ConfigServerGame::getSecondsPerResourceTick()); diff --git a/engine/server/library/serverGame/src/shared/object/ServerObject.cpp b/engine/server/library/serverGame/src/shared/object/ServerObject.cpp index 28d56891e..33e44b0f9 100755 --- a/engine/server/library/serverGame/src/shared/object/ServerObject.cpp +++ b/engine/server/library/serverGame/src/shared/object/ServerObject.cpp @@ -241,7 +241,7 @@ namespace ServerObjectNamespace const std::string OBJVAR_OPEN_BANK_TERMINAL_ID("open_bank_location"); - unsigned long gs_objectCount = 0; + uint32_t gs_objectCount = 0; const char * const portalPropertyCrcObjectVariableName = "portalProperty.crc"; @@ -262,7 +262,7 @@ namespace ServerObjectNamespace // sentinel to keep the messageTo current being // handled from getting removed from m_messageTos - std::pair, MessageToId> s_currentMessageToBeingHandled = std::make_pair(std::make_pair(0, 0), MessageToId::cms_invalid); + std::pair, MessageToId> s_currentMessageToBeingHandled = std::make_pair(std::make_pair(0, 0), MessageToId::cms_invalid); // ---------------------------------------------------------------------- @@ -1295,7 +1295,7 @@ static const ConstCharCrcLowerString templateName("object/object/base/shared_obj //----------------------------------------------------------------------- -const unsigned long ServerObject::getObjectCount() +const uint32_t ServerObject::getObjectCount() { return gs_objectCount; } @@ -2350,9 +2350,9 @@ bool ServerObject::handleContentsSetup() //----------------------------------------------------------------------- -unsigned long ServerObject::getAndIncrementMoveSequenceNumber() +uint32_t ServerObject::getAndIncrementMoveSequenceNumber() { - unsigned long newValue = m_transformSequence.get(); + uint32_t newValue = m_transformSequence.get(); newValue++; m_transformSequence = newValue; return newValue; @@ -3431,7 +3431,7 @@ void ServerObject::sendToClientsInUpdateRange(const GameNetworkMessage & message Vector combatSpamAttackerPosition_w, combatSpamDefenderPosition_w; if (!clients.empty()) { - static unsigned long int const controllerMessageCrc = MessageDispatch::MessageBase::makeMessageTypeFromString("ObjControllerMessage"); + static uint32_t const controllerMessageCrc = MessageDispatch::MessageBase::makeMessageTypeFromString("ObjControllerMessage"); if (controllerMessageCrc == message.getType()) { ObjControllerMessage const & ocm = static_cast(message); @@ -5113,10 +5113,10 @@ bool ServerObject::setPackedObjVars(std::string const &packedVarString) std::string ServerObject::debugGetMessageToList() const { - unsigned long const now = ServerClock::getInstance().getGameTimeSeconds(); + uint32_t const now = ServerClock::getInstance().getGameTimeSeconds(); std::string result; - time_t const timeNow = ::time(nullptr); - for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end(); ++i) + uint32_t const timeNow = ::time(nullptr); + for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end(); ++i) { char temp[256]; @@ -5144,14 +5144,14 @@ std::string ServerObject::debugGetMessageToList() const * @return The delivery time of the next message, or 0 if there are no more messages */ -unsigned long ServerObject::processQueuedMessageTos(unsigned long effectiveMessageToTime) +uint32_t ServerObject::processQueuedMessageTos(uint32_t effectiveMessageToTime) { PROFILER_AUTO_BLOCK_DEFINE("ServerObject::processQueuedMessageTos"); if (isAuthoritative()) { int handledMessageCount = 0; - unsigned long startTime = Clock::timeMs(); + uint32_t startTime = Clock::timeMs(); while (!m_messageTos.empty() && m_messageTos.begin()->second.getCallTime() <= effectiveMessageToTime) { ++handledMessageCount; @@ -5161,7 +5161,7 @@ unsigned long ServerObject::processQueuedMessageTos(unsigned long effectiveMessa std::string nextTenMessages; { int count = 1; - for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator iter = m_messageTos.begin(); ((iter != m_messageTos.end()) && (count <= 10)); ++iter, ++count) + for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator iter = m_messageTos.begin(); ((iter != m_messageTos.end()) && (count <= 10)); ++iter, ++count) { nextTenMessages += iter->second.getMethod(); nextTenMessages += ", "; @@ -5180,7 +5180,7 @@ unsigned long ServerObject::processQueuedMessageTos(unsigned long effectiveMessa break; } - Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator message = m_messageTos.begin(); + Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator message = m_messageTos.begin(); // if the message is going to be recurring, create a // new messageTo to reschedule the recurring message @@ -5192,7 +5192,7 @@ unsigned long ServerObject::processQueuedMessageTos(unsigned long effectiveMessa message->second.getMessageId(), message->second.getMethod(), message->second.getPackedDataVector(), - ServerClock::getInstance().getGameTimeSeconds() + static_cast(message->second.getRecurringTime()), + ServerClock::getInstance().getGameTimeSeconds() + static_cast(message->second.getRecurringTime()), false, message->second.getDeliveryType(), NetworkId::cms_invalid, @@ -5408,7 +5408,7 @@ void ServerObject::handleCMessageTo(const MessageToPayload &message) else if (message.getMethod() == "CancelRecurringMessageTo") { std::string const & methodName = message.getDataAsString(); - for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end(); ++i) + for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end(); ++i) { if ((i->second.getRecurringTime() != 0) && (i->second.getMethod() == methodName) && (i->first != s_currentMessageToBeingHandled)) { @@ -7748,7 +7748,7 @@ void ServerObject::deliverMessageTo(MessageToPayload & message) { // Recurring messages can have only one instance each. Ignore // this message if there is already a recurring one with the same method name. - for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end(); ++i) + for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end(); ++i) { if ((i->second.getRecurringTime() != 0) && (i->second.getMethod() == message.getMethod())) return; @@ -7808,7 +7808,7 @@ int ServerObject::cancelMessageTo(std::string const & messageName) { removeCount = 0; - for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end();) + for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end();) { if ((i->second.getMethod() == messageName) && (i->first != s_currentMessageToBeingHandled)) { @@ -7842,7 +7842,7 @@ int ServerObject::cancelMessageToByMessageId(NetworkId const & messageId) { removeCount = 0; - for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end();) + for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end();) { if ((i->second.getMessageId() == messageId) && (i->first != s_currentMessageToBeingHandled)) { @@ -7872,14 +7872,14 @@ int ServerObject::cancelMessageToByMessageId(NetworkId const & messageId) // returns -1 if object doesn't have the messageTo int ServerObject::timeUntilMessageTo(std::string const & messageName) const { - for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end(); ++i) + for (Archive::AutoDeltaMap, MessageToId>, MessageToPayload>::const_iterator i=m_messageTos.begin(); i!=m_messageTos.end(); ++i) { if (i->second.getMethod() == messageName) { if ((i->first != s_currentMessageToBeingHandled) || (i->second.getRecurringTime() > 0)) { - unsigned long const now = ServerClock::getInstance().getGameTimeSeconds(); - unsigned long const callTime = i->second.getCallTime(); + uint32_t const now = ServerClock::getInstance().getGameTimeSeconds(); + uint32_t const callTime = i->second.getCallTime(); if (callTime > now) return static_cast(callTime - now); diff --git a/engine/server/library/serverGame/src/shared/object/ServerObject.h b/engine/server/library/serverGame/src/shared/object/ServerObject.h index 23e12f28b..7f8f9fa6b 100755 --- a/engine/server/library/serverGame/src/shared/object/ServerObject.h +++ b/engine/server/library/serverGame/src/shared/object/ServerObject.h @@ -260,7 +260,7 @@ class ServerObject : public Object int getConversionId () const; void setConversionId (int newConversionId); - static const unsigned long getObjectCount (); + static const uint32_t getObjectCount (); const bool getPositionChanged () const; const Sphere getLocalSphere () const; const Sphere & getSphereExtent () const; @@ -485,7 +485,7 @@ class ServerObject : public Object void attachStartupScripts (); void customize (const std::string & customName, int value); void serverObjectEndBaselines (bool fromDatabase); - unsigned long getAndIncrementMoveSequenceNumber (); + uint32_t getAndIncrementMoveSequenceNumber (); uint32 getAuthServerProcessId () const; const int getCacheVersion () const; Client * getClient () const; @@ -540,7 +540,7 @@ class ServerObject : public Object int cancelMessageTo (std::string const & messageName); int cancelMessageToByMessageId (NetworkId const & messageId); int timeUntilMessageTo (std::string const & messageName) const; - unsigned long processQueuedMessageTos (unsigned long effectiveMessageToTime); + uint32_t processQueuedMessageTos (uint32_t effectiveMessageToTime); std::string debugGetMessageToList () const; bool handleTeleportFixup (bool force); bool serverObjectInitializeFirstTimeObject(ServerObject *cell, Transform const &transform); @@ -551,7 +551,7 @@ class ServerObject : public Object virtual bool isVisibleOnClient (const Client & client) const = 0; virtual void kill (); - void performSocial (const NetworkId & target, unsigned long socialType, bool animationOk, bool textOk); + void performSocial (const NetworkId & target, uint32 socialType, bool animationOk, bool textOk); void performSocial (const MessageQueueSocial & socialMsg); void performCombatSpam (const MessageQueueCombatSpam & combatSpam, bool sendToSelf, bool sendToTarget, bool sendToBystanders); @@ -583,7 +583,7 @@ class ServerObject : public Object virtual void setOwnerId(const NetworkId &id); void setSceneIdOnThisAndContents (const std::string & sceneId); void setPlayerControlled (bool newValue); - void speakText (NetworkId const &target, unsigned long chatType, unsigned long mood, unsigned long flags, Unicode::String const &speech, int language, Unicode::String const &oob); + void speakText (NetworkId const &target, uint32 chatType, uint32 mood, uint32 flags, Unicode::String const &speech, int language, Unicode::String const &oob); virtual void speakText (MessageQueueSpatialChat const &spatialChat); virtual void hearText (ServerObject const &source, MessageQueueSpatialChat const &spatialChat, int chatMessageIndex); void teleportObject (Vector const & position_w, NetworkId const &targetContainer, std::string const &targetCellName, Vector const &position_p, std::string const &scriptCallback, bool forceLoadScreen = false); @@ -798,7 +798,7 @@ class ServerObject : public Object Archive::AutoDeltaVariableCallback m_authServerProcessId; Archive::AutoDeltaSet m_proxyServerProcessIds; - Archive::AutoDeltaVariable m_transformSequence; + Archive::AutoDeltaVariable m_transformSequence; Archive::AutoDeltaVariable m_cacheVersion; Archive::AutoDeltaVariable m_loadContents; @@ -844,7 +844,7 @@ class ServerObject : public Object private: Archive::AutoDeltaVector m_triggerVolumeInfo; - Archive::AutoDeltaMap, MessageToId>, MessageToPayload> m_messageTos; + Archive::AutoDeltaMap, MessageToId>, MessageToPayload> m_messageTos; Sphere m_worldSphere; diff --git a/engine/server/library/serverGame/src/shared/object/TangibleObject.cpp b/engine/server/library/serverGame/src/shared/object/TangibleObject.cpp index a547127b4..b5eabfa6f 100755 --- a/engine/server/library/serverGame/src/shared/object/TangibleObject.cpp +++ b/engine/server/library/serverGame/src/shared/object/TangibleObject.cpp @@ -570,7 +570,8 @@ TangibleObject::~TangibleObject() // look up the caller's file and line if (callStack[callStackOffset]) { - char lib[4 * 1024] = { '\0' }; + // unused. + // char lib[4 * 1024] = { '\0' }; char file[4 * 1024] = { '\0' }; int line = 0; REPORT_LOG(true, ("\tCall stack:")); @@ -2341,8 +2342,8 @@ void TangibleObject::addHateOverTime(NetworkId const & target, float const hate, if (isAuthoritative()) { - unsigned long const currentGameTime = ServerClock::getInstance().getGameTimeSeconds(); - unsigned long const endGameTime = currentGameTime + seconds; + uint32_t const currentGameTime = ServerClock::getInstance().getGameTimeSeconds(); + uint32_t const endGameTime = currentGameTime + seconds; IGNORE_RETURN(addHate(target, hate)); @@ -5149,9 +5150,9 @@ void TangibleObject::handleCMessageTo(const MessageToPayload &message) if (!m_hateOverTime.empty()) { std::list expired; - unsigned long const currentGameTime = ServerClock::getInstance().getGameTimeSeconds(); + uint32_t const currentGameTime = ServerClock::getInstance().getGameTimeSeconds(); - for (std::map > >::const_iterator iter = m_hateOverTime.begin(); iter != m_hateOverTime.end(); ++iter) + for (std::map > >::const_iterator iter = m_hateOverTime.begin(); iter != m_hateOverTime.end(); ++iter) { if (iter->second.second.first < currentGameTime) { diff --git a/engine/server/library/serverGame/src/shared/object/TangibleObject.h b/engine/server/library/serverGame/src/shared/object/TangibleObject.h index 338cc71a4..035fed012 100755 --- a/engine/server/library/serverGame/src/shared/object/TangibleObject.h +++ b/engine/server/library/serverGame/src/shared/object/TangibleObject.h @@ -153,7 +153,7 @@ class TangibleObject : public ServerObject void addHateOverTime(NetworkId const & target, float const hate, int const seconds); bool setHate(NetworkId const & target, float const hate); float getHate(NetworkId const & target) const; - std::map > > const & getHateOverTime() const; + std::map > > const & getHateOverTime() const; float getMaxHate() const; CachedNetworkId const & getHateTarget() const; void removeHateTarget(NetworkId const & target); @@ -576,10 +576,10 @@ class TangibleObject : public ServerObject HateList m_hateList; // for applying "hate over time" - Archive::AutoDeltaMap > > m_hateOverTime; + Archive::AutoDeltaMap > > m_hateOverTime; Archive::AutoDeltaVariableCallback m_inCombat; - Archive::AutoDeltaVariable m_combatStartTime; + Archive::AutoDeltaVariable m_combatStartTime; // allows script to make an object (i.e. like a turret) attackable Archive::AutoDeltaVariableCallback m_attackableOverride; @@ -813,7 +813,7 @@ inline std::set const & TangibleObject::getPassiveRevealPlayerCharact //---------------------------------------------------------------------- -inline std::map > > const & TangibleObject::getHateOverTime() const +inline std::map > > const & TangibleObject::getHateOverTime() const { return m_hateOverTime.getMap(); } diff --git a/engine/server/library/serverGame/src/shared/objectTemplate/ServerIntangibleObjectTemplate.h b/engine/server/library/serverGame/src/shared/objectTemplate/ServerIntangibleObjectTemplate.h index f4720ff02..a0e4d6e80 100644 --- a/engine/server/library/serverGame/src/shared/objectTemplate/ServerIntangibleObjectTemplate.h +++ b/engine/server/library/serverGame/src/shared/objectTemplate/ServerIntangibleObjectTemplate.h @@ -67,7 +67,7 @@ class ServerIntangibleObjectTemplate : public ServerObjectTemplate struct Ingredient { - enum IngredientType ingredientType; + enum IngredientType ingredientType; std::vector ingredients; float complexity; std::string skillCommand; diff --git a/engine/server/library/serverGame/src/shared/pvp/Pvp.cpp b/engine/server/library/serverGame/src/shared/pvp/Pvp.cpp index d6e291ae3..5f87f178a 100755 --- a/engine/server/library/serverGame/src/shared/pvp/Pvp.cpp +++ b/engine/server/library/serverGame/src/shared/pvp/Pvp.cpp @@ -843,14 +843,14 @@ int Pvp::calculateGcwImperialScorePercentile(std::string const & gcwCategory, st { std::map >::const_iterator const iterImperial = gcwImperialScore.find(gcwCategory); if (iterImperial != gcwImperialScore.end()) - totalImperial = static_cast(std::max(0ll, iterImperial->second.first)) + static_cast(std::max(0ll, iterImperial->second.second)); + totalImperial = static_cast(std::max((int64)0, iterImperial->second.first)) + static_cast(std::max((int64)0, iterImperial->second.second)); } uint64 total = totalImperial; { std::map >::const_iterator const iterRebel = gcwRebelScore.find(gcwCategory); if (iterRebel != gcwRebelScore.end()) - total += (static_cast(std::max(0ll, iterRebel->second.first)) + static_cast(std::max(0ll, iterRebel->second.second))); + total += (static_cast(std::max((int64)0, iterRebel->second.first)) + static_cast(std::max((int64)0, iterRebel->second.second))); } // if the score is less than 1, treat it as a tie; note that score is scaled by 1000 diff --git a/engine/server/library/serverNetworkMessages/src/shared/AvatarList.h b/engine/server/library/serverNetworkMessages/src/shared/AvatarList.h index 204161ee5..f21e4baed 100755 --- a/engine/server/library/serverNetworkMessages/src/shared/AvatarList.h +++ b/engine/server/library/serverNetworkMessages/src/shared/AvatarList.h @@ -21,7 +21,7 @@ struct AvatarRecord { Unicode::String m_name; - int m_objectTemplateId; + uint32_t m_objectTemplateId; NetworkId m_networkId; uint32 m_clusterId; int m_characterType; diff --git a/engine/server/library/serverNetworkMessages/src/shared/TaskConnectionIdMessage.h b/engine/server/library/serverNetworkMessages/src/shared/TaskConnectionIdMessage.h index ce5e57353..4ec6ff554 100755 --- a/engine/server/library/serverNetworkMessages/src/shared/TaskConnectionIdMessage.h +++ b/engine/server/library/serverNetworkMessages/src/shared/TaskConnectionIdMessage.h @@ -34,7 +34,7 @@ class TaskConnectionIdMessage : public GameNetworkMessage const unsigned char getServerType () const; const std::string & getCommandLine () const; const std::string & getClusterName () const; - const long getCurrentEpochTime() const; + const int32_t getCurrentEpochTime() const; private: TaskConnectionIdMessage & operator = (const TaskConnectionIdMessage & rhs); TaskConnectionIdMessage(const TaskConnectionIdMessage & source); @@ -42,7 +42,7 @@ class TaskConnectionIdMessage : public GameNetworkMessage Archive::AutoVariable serverType; Archive::AutoVariable commandLine; Archive::AutoVariable clusterName; - Archive::AutoVariable currentEpochTime; + Archive::AutoVariable currentEpochTime; }; //----------------------------------------------------------------------- @@ -68,7 +68,7 @@ inline const unsigned char TaskConnectionIdMessage::getServerType() const //----------------------------------------------------------------------- -inline const long TaskConnectionIdMessage::getCurrentEpochTime() const +inline const int32_t TaskConnectionIdMessage::getCurrentEpochTime() const { return currentEpochTime.get(); } diff --git a/engine/server/library/serverNetworkMessages/src/shared/centralGameServer/MessageToPayloadImpl.h b/engine/server/library/serverNetworkMessages/src/shared/centralGameServer/MessageToPayloadImpl.h index 98754843c..5da198c7a 100755 --- a/engine/server/library/serverNetworkMessages/src/shared/centralGameServer/MessageToPayloadImpl.h +++ b/engine/server/library/serverNetworkMessages/src/shared/centralGameServer/MessageToPayloadImpl.h @@ -68,7 +68,7 @@ class MessageToPayloadImpl MessageToId m_messageId; std::string m_method; std::vector m_packedData; - unsigned long m_callTime; + uint32_t m_callTime; bool m_guaranteed; bool m_persisted; MessageToPayload::DeliveryType m_deliveryType; diff --git a/engine/server/library/serverNetworkMessages/src/shared/core/SetupServerNetworkMessages.cpp b/engine/server/library/serverNetworkMessages/src/shared/core/SetupServerNetworkMessages.cpp index 007706a89..67af827e6 100755 --- a/engine/server/library/serverNetworkMessages/src/shared/core/SetupServerNetworkMessages.cpp +++ b/engine/server/library/serverNetworkMessages/src/shared/core/SetupServerNetworkMessages.cpp @@ -217,20 +217,20 @@ namespace SetupServerNetworkMessagesNamespace return result; } - void packUnsignedLong(const MessageQueue::Data * data, Archive::ByteStream & target) + void packUnsignedInt(const MessageQueue::Data * data, Archive::ByteStream & target) { - const MessageQueueGenericValueType * msg = safe_cast *>(data); + const MessageQueueGenericValueType * msg = safe_cast *>(data); if(msg) { Archive::put(target, msg->getValue()); } } - MessageQueue::Data * unpackUnsignedLong(Archive::ReadIterator & source) + MessageQueue::Data * unpackUnsignedInt(Archive::ReadIterator & source) { - unsigned long v; + uint32_t v; Archive::get(source, v); - return new MessageQueueGenericValueType(v); + return new MessageQueueGenericValueType(v); } void packUnicodeString(const MessageQueue::Data * data, Archive::ByteStream & target) @@ -1391,9 +1391,9 @@ void SetupServerNetworkMessages::internalInstall () ControllerMessageFactory::registerControllerMessageHandler(CM_setCombatTargets, packNetworkIdArray, unpackNetworkIdArray); ControllerMessageFactory::registerControllerMessageHandler(CM_setCurrentWeapon, packNetworkId, unpackNetworkId); ControllerMessageFactory::registerControllerMessageHandler(CM_setGroup, packBoolNetworkId, unpackBoolNetworkId); - ControllerMessageFactory::registerControllerMessageHandler(CM_setMood, packUnsignedLong, unpackUnsignedLong); + ControllerMessageFactory::registerControllerMessageHandler(CM_setMood, packUnsignedInt, unpackUnsignedInt); ControllerMessageFactory::registerControllerMessageHandler(CM_setIncapacitated, packBoolNetworkId, unpackBoolNetworkId); - ControllerMessageFactory::registerControllerMessageHandler(CM_setSayMode, packUnsignedLong, unpackUnsignedLong); + ControllerMessageFactory::registerControllerMessageHandler(CM_setSayMode, packUnsignedInt, unpackUnsignedInt); ControllerMessageFactory::registerControllerMessageHandler(CM_setAnimationMood, packString, unpackString); ControllerMessageFactory::registerControllerMessageHandler(CM_setScaleFactor, packFloat, unpackFloat); ControllerMessageFactory::registerControllerMessageHandler(CM_setShockWounds, packInt, unpackInt); @@ -1550,7 +1550,7 @@ void SetupServerNetworkMessages::internalInstall () ControllerMessageFactory::registerControllerMessageHandler(CM_modifyNextGcwRatingCalcTime, packInt, unpackInt); ControllerMessageFactory::registerControllerMessageHandler(CM_cancelMessageTo, packString, unpackString); ControllerMessageFactory::registerControllerMessageHandler(CM_clearSessionActivity, packNothing, unpackNothing); - ControllerMessageFactory::registerControllerMessageHandler(CM_addSessionActivity, packUnsignedLong, unpackUnsignedLong); + ControllerMessageFactory::registerControllerMessageHandler(CM_addSessionActivity, packUnsignedInt, unpackUnsignedInt); ControllerMessageFactory::registerControllerMessageHandler(CM_incrementKillMeter, packInt, unpackInt); ControllerMessageFactory::registerControllerMessageHandler(CM_addPassiveReveal, packIntIntNetworkId, unpackIntIntNetworkId); ControllerMessageFactory::registerControllerMessageHandler(CM_removePassiveReveal, packNetworkId, unpackNetworkId); diff --git a/engine/server/library/serverNetworkMessages/src/shared/gameConnectionServer/GameConnectionServerMessages.cpp b/engine/server/library/serverNetworkMessages/src/shared/gameConnectionServer/GameConnectionServerMessages.cpp index 6b8d1f5ad..8f9ebede8 100755 --- a/engine/server/library/serverNetworkMessages/src/shared/gameConnectionServer/GameConnectionServerMessages.cpp +++ b/engine/server/library/serverNetworkMessages/src/shared/gameConnectionServer/GameConnectionServerMessages.cpp @@ -86,7 +86,7 @@ TransferControlMessage::~TransferControlMessage() //----------------------------------------------------------------------- ControlAssumed::ControlAssumed(NetworkId oid, const std::string & newSceneName, const bool skipLoadScreen, const Vector &startPos, const float startYaw, const std::string & templateName, - const int64 t) : + const int64_t t) : GameNetworkMessage("ControlAssumed"), m_oid(oid), m_sceneName(newSceneName), @@ -223,7 +223,7 @@ GameClientMessage::GameClientMessage(const std::vector & d, bool newR if (reportMessages) { Archive::ReadIterator ri = byteStream.get().begin(); - unsigned long cmdCrc; + uint32_t cmdCrc; Archive::get(ri, cmdCrc); NetworkHandler::reportMessage("send.GameClientMessage." + GameNetworkMessage::getCmdName(cmdCrc), byteStream.get().getSize()); } @@ -246,7 +246,7 @@ GameClientMessage::GameClientMessage(Archive::ReadIterator & source) : if (reportMessages) { Archive::ReadIterator ri = byteStream.get().begin(); - unsigned long cmdCrc; + uint32_t cmdCrc; Archive::get(ri, cmdCrc); NetworkHandler::reportMessage("send.GameClientMessage." + GameNetworkMessage::getCmdName(cmdCrc), byteStream.get().getSize()); } diff --git a/engine/server/library/serverNetworkMessages/src/shared/gameConnectionServer/GameConnectionServerMessages.h b/engine/server/library/serverNetworkMessages/src/shared/gameConnectionServer/GameConnectionServerMessages.h index c81e6ae82..9eddc3130 100755 --- a/engine/server/library/serverNetworkMessages/src/shared/gameConnectionServer/GameConnectionServerMessages.h +++ b/engine/server/library/serverNetworkMessages/src/shared/gameConnectionServer/GameConnectionServerMessages.h @@ -118,7 +118,7 @@ class ControlAssumed : public GameNetworkMessage public: explicit ControlAssumed(NetworkId oid, const std::string & newSceneName, const bool skipLoadScreen, const Vector &startPos, const float startYaw, const std::string & templateName, - const int64 timeSeconds); + const int64_t timeSeconds); ControlAssumed(Archive::ReadIterator & source); virtual ~ControlAssumed(); @@ -128,7 +128,7 @@ class ControlAssumed : public GameNetworkMessage const Vector & getStartPosition () const; const float getStartYaw () const; const std::string & getTemplateName () const; - const int64 getTimeSeconds () const; + const int64_t getTimeSeconds () const; private: Archive::AutoVariable m_oid; @@ -137,7 +137,7 @@ class ControlAssumed : public GameNetworkMessage Archive::AutoVariable m_startPosition; Archive::AutoVariable m_startYaw; Archive::AutoVariable m_templateName; - Archive::AutoVariable m_timeSeconds; + Archive::AutoVariable m_timeSeconds; ControlAssumed(); @@ -188,7 +188,7 @@ inline const std::string & ControlAssumed::getTemplateName() const //----------------------------------------------------------------------- -inline const int64 ControlAssumed::getTimeSeconds() const +inline const int64_t ControlAssumed::getTimeSeconds() const { return m_timeSeconds.get(); } diff --git a/engine/server/library/serverPathfinding/src/shared/CityPathGraph.cpp b/engine/server/library/serverPathfinding/src/shared/CityPathGraph.cpp index 8ec08af53..b8ed9a839 100755 --- a/engine/server/library/serverPathfinding/src/shared/CityPathGraph.cpp +++ b/engine/server/library/serverPathfinding/src/shared/CityPathGraph.cpp @@ -709,32 +709,32 @@ void CityPathGraph::setLinkDistance ( float dist ) // we cast the addresses of all the neighbors to ints, multiply them // by a random large prime number, then xor the bits together. -int CityPathGraph::getNeighborCode ( int whichNode ) const -{ - CityPathNode const * node = _getNode(whichNode); - - if(node == nullptr) return 0; - - int edgeCount = node->getEdgeCount(); - - int code = 0; - - for(int i = 0; i < edgeCount; i++) - { - int neighborId = node->getNeighbor(i); - - CityPathNode const * neighbor = _getNode(neighborId); - - if(neighbor == nullptr) continue; - - int neighborInt = reinterpret_cast(neighbor); - - int mungedInt = neighborInt * 1295183; - - code ^= mungedInt; - } - - return code; -} +//int CityPathGraph::getNeighborCode ( int whichNode ) const +//{ +// CityPathNode const * node = _getNode(whichNode); +// +// if(node == nullptr) return 0; +// +// int edgeCount = node->getEdgeCount(); +// +// int code = 0; +// +// for(int i = 0; i < edgeCount; i++) +// { +// int neighborId = node->getNeighbor(i); +// +// CityPathNode const * neighbor = _getNode(neighborId); +// +// if(neighbor == nullptr) continue; +// +// int neighborInt = reinterpret_cast(neighbor); +// +// int mungedInt = neighborInt * 1295183; +// +// code ^= mungedInt; +// } +// +// return code; +//} // ---------------------------------------------------------------------- diff --git a/engine/server/library/serverPathfinding/src/shared/CityPathGraph.h b/engine/server/library/serverPathfinding/src/shared/CityPathGraph.h index 322f653c8..89835c999 100755 --- a/engine/server/library/serverPathfinding/src/shared/CityPathGraph.h +++ b/engine/server/library/serverPathfinding/src/shared/CityPathGraph.h @@ -84,7 +84,7 @@ class CityPathGraph : public DynamicPathGraph static float getLinkDistance ( void ); static void setLinkDistance ( float dist ); - int getNeighborCode ( int whichNode ) const; +// int getNeighborCode ( int whichNode ) const; protected: diff --git a/engine/server/library/serverScript/src/shared/GameScriptObject.cpp b/engine/server/library/serverScript/src/shared/GameScriptObject.cpp index ab118b52b..5eefb97eb 100755 --- a/engine/server/library/serverScript/src/shared/GameScriptObject.cpp +++ b/engine/server/library/serverScript/src/shared/GameScriptObject.cpp @@ -100,8 +100,9 @@ bool GameScriptObject::installScriptEngine(void) ms_scriptDataMap = new GameScriptObject::ScriptDataMap; Scripting::InitScriptFuncHashMap(); JavaLibrary::install(); - if (JavaLibrary::instance() == nullptr) + if (JavaLibrary::instance() == nullptr) { return false; + } enableNewJediTracking(ConfigServerGame::getEnableNewJedi()); return true; } // GameScriptObject::installScriptEngine diff --git a/engine/server/library/serverScript/src/shared/JavaLibrary.cpp b/engine/server/library/serverScript/src/shared/JavaLibrary.cpp index 75f83e68f..f5f415b79 100755 --- a/engine/server/library/serverScript/src/shared/JavaLibrary.cpp +++ b/engine/server/library/serverScript/src/shared/JavaLibrary.cpp @@ -790,7 +790,7 @@ void JavaLibrary::fatalHandler(int signum) char lib1[BUFLEN], lib2[BUFLEN]; char file1[BUFLEN], file2[BUFLEN]; int line1, line2; - bool result1 = DebugHelp::lookupAddress(reinterpret_cast(crashAddress1), lib1, file1, BUFLEN, line1); + bool result1 = DebugHelp::lookupAddress(reinterpret_cast(crashAddress1), lib1, file1, BUFLEN, line1); // do a second test based on the return address // it turns out that in some java crashes we don't even have 2 return @@ -801,31 +801,36 @@ void JavaLibrary::fatalHandler(int signum) void *crashAddress2c = nullptr; void *frameAddressA = nullptr; void *frameAddressB = nullptr; - uint32 frameAddressHigh = (reinterpret_cast(frameAddress) >> 16); + uint64 frameAddressHigh = (reinterpret_cast(frameAddress) >> 16); crashAddress2a = __builtin_return_address(0); +// Suppress Wframe-address for these lines - we could crash the program calling __builtin_return_address and frame_address +// with non-zero values. However, we likely don't care as we're crashing at this point anyway due to bad Java. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wframe-address" if (crashAddress2a != nullptr) { frameAddressA = __builtin_frame_address(1); if (frameAddressA != nullptr && - (reinterpret_cast(frameAddressA) >> 16 == frameAddressHigh)) + (reinterpret_cast(frameAddressA) >> 16 == frameAddressHigh)) { crashAddress2b = __builtin_return_address(1); if (crashAddress2b != nullptr) { frameAddressB = __builtin_frame_address(2); if (frameAddressB != nullptr && - (reinterpret_cast(frameAddressB) >> 16 == frameAddressHigh)) + (reinterpret_cast(frameAddressB) >> 16 == frameAddressHigh)) { crashAddress2c = __builtin_return_address(2); if (crashAddress2c != nullptr) { - result2 = DebugHelp::lookupAddress(reinterpret_cast( + result2 = DebugHelp::lookupAddress(reinterpret_cast( crashAddress2c), lib2, file2, BUFLEN, line2); } } } } } +#pragma GCC diagnostic pop bool javaCrash = true; if ((result1 || result2) && strstr(lib1, "libjvm.so") == nullptr && strstr(lib2, "libjvm.so") == nullptr) @@ -1955,6 +1960,7 @@ bool JavaLibrary::registerNatives(const JNINativeMethod natives[], int count) { ms_env->ExceptionClear(); DEBUG_REPORT_LOG(true, ("RegisterNatives failed: %s: %s\n", natives[i].name, natives[i].signature)); + WARNING(true, ("RegisterNatives failed: could not register Java method: %s: with signature %s (does it exist in the codebase?)\n", natives[i].name, natives[i].signature)); result = lresult; } } diff --git a/engine/server/library/serverScript/src/shared/ScriptMethodsCollection.cpp b/engine/server/library/serverScript/src/shared/ScriptMethodsCollection.cpp index 080d7994c..2e6ded6d8 100755 --- a/engine/server/library/serverScript/src/shared/ScriptMethodsCollection.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptMethodsCollection.cpp @@ -90,7 +90,7 @@ bool ScriptMethodsCollectionNamespace::install() JF("getCollectionSlotCategoryInfo", "(Ljava/lang/String;)[Ljava/lang/String;", getCollectionSlotCategoryInfo), JF("getCollectionSlotPrereqInfo", "(Ljava/lang/String;)[Ljava/lang/String;", getCollectionSlotPrereqInfo), JF("getCollectionSlotName", "(I)Ljava/lang/String;", getCollectionSlotName), - JF("getCollectionSlotMaxValue", "(Ljava/lang/String;)J", getCollectionSlotMaxValue), + //JF("getCollectionSlotMaxValue", "(Ljava/lang/String;)J", getCollectionSlotMaxValue), JF("getAllCollectionSlotsInCollection", "(Ljava/lang/String;)[Ljava/lang/String;", getAllCollectionSlotsInCollection), JF("getAllCollectionSlotsInPage", "(Ljava/lang/String;)[Ljava/lang/String;", getAllCollectionSlotsInPage), JF("getAllCollectionsInPage", "(Ljava/lang/String;)[Ljava/lang/String;", getAllCollectionsInPage), @@ -150,7 +150,7 @@ jlong JNICALL ScriptMethodsCollectionNamespace::getCollectionSlotValue(JNIEnv *e std::string slotNameString; JavaLibrary::convert(localSlotName, slotNameString); - unsigned long value; + uint32_t value; if (!playerObject->getCollectionSlotValue(slotNameString, value)) return static_cast(-1); diff --git a/engine/server/library/serverScript/src/shared/ScriptMethodsCombat.cpp b/engine/server/library/serverScript/src/shared/ScriptMethodsCombat.cpp index fdb842bc5..f8700fc5c 100755 --- a/engine/server/library/serverScript/src/shared/ScriptMethodsCombat.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptMethodsCombat.cpp @@ -1680,7 +1680,7 @@ jboolean JNICALL ScriptMethodsCombatNamespace::doCombatResults(JNIEnv *env, jobj if (!ClientCombatManagerSupport::doesCombatActionNameExist(TemporaryCrcString(animationString.c_str(), true))) { - WARNING(true, ("doCombatResults(): caller passed in unsupported combat action name [%s]! Continuing to send combat action. Call stack follows in stdout.", animationString.c_str())); + DEBUG_WARNING(true, ("doCombatResults(): caller passed in unsupported combat action name [%s]! Continuing to send combat action. Call stack follows in stdout.", animationString.c_str())); // @todo make this go to the log rather than stdout; otherwise, we're going to have to do a lot more work to see this info. JavaLibrary::printJavaStack(); } diff --git a/engine/server/library/serverScript/src/shared/ScriptMethodsPermissions.cpp b/engine/server/library/serverScript/src/shared/ScriptMethodsPermissions.cpp index 45e0981e5..3d2c7d2fb 100755 --- a/engine/server/library/serverScript/src/shared/ScriptMethodsPermissions.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptMethodsPermissions.cpp @@ -66,7 +66,7 @@ const JNINativeMethod NATIVES[] = { JF("_permissionsMakePublic", "(J)V", permissionsMakePublic), JF("_permissionsMakePrivate", "(J)V", permissionsMakePrivate), JF("_expelFromBuilding", "(J)V", expelFromBuilding), - JF("_sendDirtyCellPermissionsUpdateToClient", "(JJZ)V", sendDirtyCellPermissionsUpdateToClient), + //JF("_sendDirtyCellPermissionsUpdateToClient", "(JJZ)V", sendDirtyCellPermissionsUpdateToClient), }; return JavaLibrary::registerNatives(NATIVES, sizeof(NATIVES)/sizeof(NATIVES[0])); diff --git a/engine/server/library/serverScript/src/shared/ScriptMethodsPlayerAccount.cpp b/engine/server/library/serverScript/src/shared/ScriptMethodsPlayerAccount.cpp index 6fe97302f..ec6fcc478 100755 --- a/engine/server/library/serverScript/src/shared/ScriptMethodsPlayerAccount.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptMethodsPlayerAccount.cpp @@ -1002,25 +1002,18 @@ jstring JNICALL ScriptMethodsPlayerAccountNamespace::getPlayerUsername(JNIEnv *e NOT_NULL(env); CreatureObject const * creatureObject = nullptr; - if (!JavaLibrary::getObject(player, creatureObject) || !creatureObject) - { - DEBUG_WARNING(true, ("JavaLibrary::getPlayerUsername: bad CreatureObject")); - return nullptr; - } - - if(creatureObject) + JavaLibrary::getObject(player, creatureObject); + DEBUG_WARNING(!creatureObject, ("JavaLibrary::getPlayerUsername: could not get creatureObject for player %d", player)); + if (creatureObject) { const Client * playerClient = creatureObject->getClient(); + DEBUG_WARNING(!playerClient, ("JavaLibrary::getPlayerUsername: could not get playerClient for player %d", player)); if(playerClient) { return JavaString(playerClient->getAccountName()).getReturnValue(); } - else { - DEBUG_WARNING(true, ("JavaLibrary::getPlayerUsername: bad playerClient")); - return nullptr; - } } - + return nullptr; } // ====================================================================== diff --git a/engine/server/library/serverScript/src/shared/ScriptMethodsSystem.cpp b/engine/server/library/serverScript/src/shared/ScriptMethodsSystem.cpp index 47c662cf1..d3395b849 100755 --- a/engine/server/library/serverScript/src/shared/ScriptMethodsSystem.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptMethodsSystem.cpp @@ -50,7 +50,7 @@ const JNINativeMethod NATIVES[] = { JF("_saveBytesOnClient", "(JLjava/lang/String;[B)V", saveBytesOnClient), JF("_launchClientWebBrowser", "(JLjava/lang/String;)V", launchClientWebBrowser), JF("_playCutScene", "(JLjava/lang/String;)V", playCutScene), - JF("_triggerServerWarning", "(Ljava/lang/String;)V", triggerServerWarning), + // JF("_triggerServerWarning", "(Ljava/lang/String;)V", triggerServerWarning), }; return JavaLibrary::registerNatives(NATIVES, sizeof(NATIVES)/sizeof(NATIVES[0])); diff --git a/engine/server/library/serverUtility/src/shared/ChatLogManager.cpp b/engine/server/library/serverUtility/src/shared/ChatLogManager.cpp index c883063eb..da6a508a3 100755 --- a/engine/server/library/serverUtility/src/shared/ChatLogManager.cpp +++ b/engine/server/library/serverUtility/src/shared/ChatLogManager.cpp @@ -33,7 +33,7 @@ namespace ChatLogManagerNamespace { public: - ChatLogEntry(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const *text, Unicode::String const &channel, time_t const time) + ChatLogEntry(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const *text, Unicode::String const &channel, uint32_t const time) : m_fromPlayer(Unicode::toLower(fromPlayer)) , m_toPlayer(Unicode::toLower(toPlayer)) , m_text(text) @@ -62,7 +62,7 @@ namespace ChatLogManagerNamespace return m_channel; } - time_t getTime() const + uint32_t getTime() const { return m_time; } @@ -73,14 +73,14 @@ namespace ChatLogManagerNamespace Unicode::String m_toPlayer; Unicode::String const *m_text; Unicode::String m_channel; - time_t m_time; + uint32_t m_time; // Disabled ChatLogEntry(); }; - typedef std::list > TimeLog; + typedef std::list > TimeLog; typedef std::map ChatLog; typedef std::map PlayerLog; typedef std::map MessageList; // Second parameter is the reference count @@ -89,14 +89,14 @@ namespace ChatLogManagerNamespace ChatLog s_chatLog; PlayerLog s_playerLog; MessageList s_chatMessageList; - time_t s_purgeTime = 0; + uint32_t s_purgeTime = 0; int s_currentIndex = 0; - time_t s_chatLogMemoryTimer = 0; + uint32_t s_chatLogMemoryTimer = 0; int s_cacheHits = 0; int s_cacheMisses = 0; void printPlayerLog(); - void addChatLogEntry(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, int const messageIndex, time_t const time); + void addChatLogEntry(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, int const messageIndex, uint32_t const time); bool removeChatLogEntry(int const messageIndex); void purgeChatLog(); std::string getTimeString(time_t const time); @@ -120,7 +120,7 @@ void ChatLogManagerNamespace::printPlayerLog() } //----------------------------------------------------------------------------- -void ChatLogManagerNamespace::addChatLogEntry(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, int const messageIndex, time_t const time) +void ChatLogManagerNamespace::addChatLogEntry(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, int const messageIndex, uint32_t const time) { ChatLog::const_iterator iterChatLog = s_chatLog.find(messageIndex); @@ -238,20 +238,20 @@ void ChatLogManagerNamespace::purgeChatLog() { // This purges the list of old data once a second - time_t const systemTime = Os::getRealSystemTime(); + uint32_t const systemTime = Os::getRealSystemTime(); if (s_purgeTime != systemTime) { s_purgeTime = systemTime; - time_t const chatLogPurgeTime = static_cast(ConfigServerUtility::getChatLogMinutes() * 60); + uint32_t const chatLogPurgeTime = static_cast(ConfigServerUtility::getChatLogMinutes() * 60); TimeLog::iterator iterTimeLog = s_timeLog.begin(); int chatLogCount = static_cast(s_timeLog.size()); int purgedMessages = 0; for (; iterTimeLog != s_timeLog.end(); ++iterTimeLog) { - time_t const time = iterTimeLog->first; + uint32_t const time = iterTimeLog->first; if ( (time < (systemTime - chatLogPurgeTime)) || (static_cast(s_chatMessageList.size()) > ConfigServerUtility::getServerMaxChatLogLines())) @@ -346,7 +346,7 @@ void ChatLogManager::remove() } //----------------------------------------------------------------------------- -void ChatLogManager::logChat(Unicode::String const & fromPlayer, Unicode::String const & toPlayer, Unicode::String const & message, Unicode::String const & channel, int const messageIndex, time_t const time) +void ChatLogManager::logChat(Unicode::String const & fromPlayer, Unicode::String const & toPlayer, Unicode::String const & message, Unicode::String const & channel, int const messageIndex, uint32_t const time) { addChatLogEntry(fromPlayer, toPlayer, message, channel, messageIndex, time); purgeChatLog(); @@ -386,7 +386,7 @@ bool ChatLogManager::getChatMessage(int const messageIndex, Unicode::String &cha } //----------------------------------------------------------------------------- -bool ChatLogManager::getChatMessage(int const messageIndex, Unicode::String &fromPlayer, Unicode::String &toPlayer, Unicode::String &text, Unicode::String &channel, time_t &time) +bool ChatLogManager::getChatMessage(int const messageIndex, Unicode::String &fromPlayer, Unicode::String &toPlayer, Unicode::String &text, Unicode::String &channel, uint32_t &time) { bool result = false; @@ -412,7 +412,7 @@ bool ChatLogManager::getChatMessage(int const messageIndex, Unicode::String &fro } //----------------------------------------------------------------------------- -void ChatLogManager::buildLogEntry(Unicode::String &result, Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, time_t const time) +void ChatLogManager::buildLogEntry(Unicode::String &result, Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, uint32_t const time) { result.clear(); result.append(Unicode::narrowToWide(getTimeStringShort(time))); diff --git a/engine/server/library/serverUtility/src/shared/ChatLogManager.h b/engine/server/library/serverUtility/src/shared/ChatLogManager.h index 62ab60ad1..978fe3ca0 100755 --- a/engine/server/library/serverUtility/src/shared/ChatLogManager.h +++ b/engine/server/library/serverUtility/src/shared/ChatLogManager.h @@ -18,11 +18,11 @@ class ChatLogManager static void install(); static void remove(); - static void logChat(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, int const messageIndex, time_t const time); - static bool getChatMessage(int const messageIndex, Unicode::String &fromPlayer, Unicode::String &toPlayer, Unicode::String &text, Unicode::String &channel, time_t &time); + static void logChat(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, int const messageIndex, uint32_t const time); + static bool getChatMessage(int const messageIndex, Unicode::String &fromPlayer, Unicode::String &toPlayer, Unicode::String &text, Unicode::String &channel, uint32_t &time); static bool getChatMessage(int const messageIndex, Unicode::String &chatMessage); - static int getNextMessageIndex(); - static void buildLogEntry(Unicode::String &result, Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, time_t const time); + static int getNextMessageIndex(); + static void buildLogEntry(Unicode::String &result, Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, uint32_t const time); static bool isPlayerInLogs(Unicode::String const &player); static void getReportHeader(Unicode::String & header, std::string const &reportingPlayer, NetworkId const &reportingPlayerNetworkId, std::string const &reportingPlayerStationName, uint32 reportingPlayerStationId, std::string const &harassingPlayer, NetworkId const &harassingPlayerNetworkId, std::string const &harassingPlayerStationName, uint32 harassingPlayerStationId); diff --git a/engine/server/library/serverUtility/src/shared/PopulationList.cpp b/engine/server/library/serverUtility/src/shared/PopulationList.cpp index 80db4b1eb..1209b786f 100755 --- a/engine/server/library/serverUtility/src/shared/PopulationList.cpp +++ b/engine/server/library/serverUtility/src/shared/PopulationList.cpp @@ -115,9 +115,9 @@ namespace Archive { void get(ReadIterator & source, PopulationList & target) { - size_t numEntries; + int32_t numEntries; get(source,numEntries); - for (size_t count=0; count < numEntries; ++count) + for (int32_t count=0; count < numEntries; ++count) { std::string scene; int x; @@ -133,7 +133,7 @@ namespace Archive void put(ByteStream & target, const PopulationList & source) { - put(target,source.m_populationMap.size()); + put(target, static_cast (source.m_populationMap.size())); for (PopulationList::PopulationMapType::const_iterator i=source.m_populationMap.begin(); i!=source.m_populationMap.end(); ++i) { put(target,i->first.getScene()); diff --git a/engine/server/library/serverUtility/src/shared/ServerClock.cpp b/engine/server/library/serverUtility/src/shared/ServerClock.cpp index a5a13a8a5..a8d7c73f4 100755 --- a/engine/server/library/serverUtility/src/shared/ServerClock.cpp +++ b/engine/server/library/serverUtility/src/shared/ServerClock.cpp @@ -12,7 +12,7 @@ // ---------------------------------------------------------------------- -const unsigned long ServerClock::cms_endOfTime = static_cast(-1); +const int32_t ServerClock::cms_endOfTime = static_cast(-1); //----------------------------------------------------------------------- @@ -31,10 +31,10 @@ ServerClock::~ServerClock() //----------------------------------------------------------------------- -const unsigned long ServerClock::getGameTimeSeconds() const +const uint32_t ServerClock::getGameTimeSeconds() const { FATAL(!isSet(), ("ServerClock::getGameTimeSeconds: Clock was not set.")); - return int(lastTime - subtractInterval); + return static_cast(lastTime - subtractInterval); } //----------------------------------------------------------------------- @@ -52,16 +52,16 @@ void ServerClock::incrementServerFrame() //----------------------------------------------------------------------- -void ServerClock::setSubtractInterval(const unsigned long newSubtractInterval) +void ServerClock::setSubtractInterval(const uint32_t newSubtractInterval) { subtractInterval = newSubtractInterval; } //----------------------------------------------------------------------- -void ServerClock::setGameTimeSeconds(const unsigned long newGameTime) +void ServerClock::setGameTimeSeconds(const uint32_t newGameTime) { - subtractInterval = int(time(0) - newGameTime); + subtractInterval = static_cast(time(0) - newGameTime); LOG("ServerClock", ("Game time set to %lu (subtract interval %lu)", newGameTime, subtractInterval)); } @@ -79,11 +79,11 @@ ServerClock &ServerClock::getInstance() * Given a time in seconds, make a string that expresses how long it is. * For debug output only. In English, not localized. Not thread-safe. */ -std::string ServerClock::getDebugPrintableTimeframe(unsigned long const timeInSeconds) +std::string ServerClock::getDebugPrintableTimeframe(uint32_t const timeInSeconds) { - unsigned long const dayInSeconds = 60 * 60 * 24; - unsigned long const hourInSeconds = 60 * 60; - unsigned long const minuteInSeconds = 60; + uint32_t const dayInSeconds = 60 * 60 * 24; + uint32_t const hourInSeconds = 60 * 60; + uint32_t const minuteInSeconds = 60; static char buffer[256]; diff --git a/engine/server/library/serverUtility/src/shared/ServerClock.h b/engine/server/library/serverUtility/src/shared/ServerClock.h index 36ee93b98..9f64c3bb1 100755 --- a/engine/server/library/serverUtility/src/shared/ServerClock.h +++ b/engine/server/library/serverUtility/src/shared/ServerClock.h @@ -10,36 +10,36 @@ class ServerClock static ServerClock &getInstance(); ~ServerClock(); - const unsigned long getGameTimeSeconds () const; - const unsigned long getServerFrame() const; - const unsigned long getSubtractInterval() const; + const uint32_t getGameTimeSeconds () const; + const uint32_t getServerFrame() const; + const uint32_t getSubtractInterval() const; void incrementServerFrame(); - void setSubtractInterval(const unsigned long newSubtractInterval); - void setGameTimeSeconds (unsigned long newGameTime); + void setSubtractInterval(const uint32_t newSubtractInterval); + void setGameTimeSeconds (uint32_t newGameTime); bool isSet () const; - std::string getDebugPrintableTimeframe (const unsigned long timeInSeconds); + std::string getDebugPrintableTimeframe (const uint32_t timeInSeconds); - static const unsigned long cms_endOfTime; + static const int32_t cms_endOfTime; protected: ServerClock(); private: - unsigned long serverFrame; - unsigned long subtractInterval; + uint32_t serverFrame; + uint32_t subtractInterval; mutable time_t lastTime; }; //----------------------------------------------------------------------- -inline const unsigned long ServerClock::getServerFrame() const +inline const uint32_t ServerClock::getServerFrame() const { return serverFrame; } //----------------------------------------------------------------------- -inline const unsigned long ServerClock::getSubtractInterval() const +inline const uint32_t ServerClock::getSubtractInterval() const { return subtractInterval; } diff --git a/engine/server/library/serverUtility/src/shared/ServerConnection.cpp b/engine/server/library/serverUtility/src/shared/ServerConnection.cpp index 2ea7eeb06..8b3f3fd76 100755 --- a/engine/server/library/serverUtility/src/shared/ServerConnection.cpp +++ b/engine/server/library/serverUtility/src/shared/ServerConnection.cpp @@ -290,7 +290,7 @@ void ServerConnection::onConnectionStalled(const unsigned long stallTimeMs) // ---------------------------------------------------------------------- -void ServerConnection::setProcessId(const uint32 newProcessId) +void ServerConnection::setProcessId(const uint32_t newProcessId) { processId = newProcessId; } diff --git a/engine/server/library/serverUtility/src/shared/ServerConnection.h b/engine/server/library/serverUtility/src/shared/ServerConnection.h index d7fd6519c..adc14b1d3 100755 --- a/engine/server/library/serverUtility/src/shared/ServerConnection.h +++ b/engine/server/library/serverUtility/src/shared/ServerConnection.h @@ -31,8 +31,8 @@ class ServerConnection: public Connection, public MessageDispatch::Emitter static const unsigned long makeProcessId (); static bool isMessageForwardable (unsigned long int type); - const unsigned long getProcessId () const; - const unsigned long getOsProcessId () const; + const uint32_t getProcessId () const; + const uint32_t getOsProcessId () const; virtual void onConnectionClosed (); virtual void onConnectionOpened (); virtual void onConnectionOverflowing (const unsigned int bytesPending); @@ -40,8 +40,8 @@ class ServerConnection: public Connection, public MessageDispatch::Emitter virtual void onReceive (const Archive::ByteStream & message); virtual void reportReceive (const Archive::ByteStream & bs); virtual void reportSend (const Archive::ByteStream & bs); - virtual void send (const GameNetworkMessage & message, const bool reliable); - virtual void setProcessId (const unsigned long newProcessId); + virtual void send (const GameNetworkMessage & message, const bool reliable); + virtual void setProcessId (const uint32_t newProcessId); public: class MessageConnectionCallback: public MessageDispatch::MessageBase @@ -67,20 +67,20 @@ class ServerConnection: public Connection, public MessageDispatch::Emitter ServerConnection &operator=(const ServerConnection&); //disable private: - unsigned long processId; - unsigned long osProcessId; // remote's operating system assigned PID + uint32_t processId; + uint32_t osProcessId; // remote's operating system assigned PID }; //----------------------------------------------------------------------- -inline const unsigned long ServerConnection::getProcessId(void) const +inline const uint32_t ServerConnection::getProcessId(void) const { return processId; } //----------------------------------------------------------------------- -inline const unsigned long ServerConnection::getOsProcessId() const +inline const uint32_t ServerConnection::getOsProcessId() const { return osProcessId; } diff --git a/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.cpp b/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.cpp index 3ad1949b8..c22ce195f 100755 --- a/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.cpp +++ b/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.cpp @@ -9,7 +9,7 @@ //----------------------------------------------------------------------- -SystemAssignedProcessId::SystemAssignedProcessId(const unsigned long id) : +SystemAssignedProcessId::SystemAssignedProcessId(const uint32_t id) : GameNetworkMessage("SystemAssignedProcessId"), m_id(id) { @@ -34,7 +34,7 @@ SystemAssignedProcessId::~SystemAssignedProcessId() //----------------------------------------------------------------------- -const unsigned long SystemAssignedProcessId::getId() const +const uint32_t SystemAssignedProcessId::getId() const { return m_id.get(); } diff --git a/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.h b/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.h index 2ecbf8b05..3d27bb257 100755 --- a/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.h +++ b/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.h @@ -14,17 +14,17 @@ class SystemAssignedProcessId : public GameNetworkMessage { public: - explicit SystemAssignedProcessId(const unsigned long id); + explicit SystemAssignedProcessId(const uint32_t id); explicit SystemAssignedProcessId(Archive::ReadIterator & source); ~SystemAssignedProcessId(); - const unsigned long getId () const; + const uint32_t getId () const; private: SystemAssignedProcessId & operator = (const SystemAssignedProcessId & rhs); SystemAssignedProcessId(const SystemAssignedProcessId & source); - Archive::AutoVariable m_id; + Archive::AutoVariable m_id; }; //----------------------------------------------------------------------- diff --git a/engine/shared/library/sharedCollision/src/shared/core/CollisionProperty.cpp b/engine/shared/library/sharedCollision/src/shared/core/CollisionProperty.cpp index b8cc93323..3aa8d90fd 100755 --- a/engine/shared/library/sharedCollision/src/shared/core/CollisionProperty.cpp +++ b/engine/shared/library/sharedCollision/src/shared/core/CollisionProperty.cpp @@ -549,7 +549,9 @@ BaseExtent * convertToSimpleExtent ( BaseExtent const * sourceExtent ) { Extent const * extent = safe_cast(sourceExtent); - if(!extent) return nullptr; + if(!extent) { + return nullptr; + } return new SimpleExtent( MultiShape( extent->getShape() ) ); } @@ -558,7 +560,9 @@ BaseExtent * convertToSimpleExtent ( BaseExtent const * sourceExtent ) { CylinderExtent const * extent = safe_cast(sourceExtent); - if(!extent) return nullptr; + if(!extent) { + return nullptr; + } return new SimpleExtent( MultiShape( extent->getShape() ) ); } @@ -567,7 +571,9 @@ BaseExtent * convertToSimpleExtent ( BaseExtent const * sourceExtent ) { BoxExtent const * extent = safe_cast(sourceExtent); - if(!extent) return nullptr; + if(!extent) { + return nullptr; + } return new SimpleExtent( MultiShape( extent->getShape() ) ); } @@ -576,7 +582,9 @@ BaseExtent * convertToSimpleExtent ( BaseExtent const * sourceExtent ) { MeshExtent const * extent = safe_cast(sourceExtent); - if(!extent) return nullptr; + if(!extent) { + return nullptr; + } return extent->clone(); } @@ -585,7 +593,9 @@ BaseExtent * convertToSimpleExtent ( BaseExtent const * sourceExtent ) { DetailExtent const * extent = safe_cast(sourceExtent); - if(!extent) return nullptr; + if(!extent) { + return nullptr; + } DetailExtent * newExtent = new DetailExtent(); @@ -603,7 +613,9 @@ BaseExtent * convertToSimpleExtent ( BaseExtent const * sourceExtent ) { ComponentExtent const * extent = safe_cast(sourceExtent); - if(!extent) return nullptr; + if(!extent) { + return nullptr; + } ComponentExtent * newExtent = new ComponentExtent(); diff --git a/engine/shared/library/sharedCollision/src/shared/core/CollisionWorld.cpp b/engine/shared/library/sharedCollision/src/shared/core/CollisionWorld.cpp index 71a06f867..e6973d1b7 100755 --- a/engine/shared/library/sharedCollision/src/shared/core/CollisionWorld.cpp +++ b/engine/shared/library/sharedCollision/src/shared/core/CollisionWorld.cpp @@ -1128,27 +1128,30 @@ void CollisionWorld::addObject(Object * object) name = appearance->getAppearanceTemplateName(); } } - - int index = 0; - switch (query) - { - case SpatialDatabase::Q_Static: - index = 1; - break; - case SpatialDatabase::Q_Dynamic: - index = 2; - break; - case SpatialDatabase::Q_Barriers: - index = 3; - break; - case SpatialDatabase::Q_Doors: - index = 4; - break; - default: - break; +#if _DEBUG + if(ConfigSharedCollision::getReportChanges()) { + int index = 0; + switch (query) + { + case SpatialDatabase::Q_Static: + index = 1; + break; + case SpatialDatabase::Q_Dynamic: + index = 2; + break; + case SpatialDatabase::Q_Barriers: + index = 3; + break; + case SpatialDatabase::Q_Doors: + index = 4; + break; + default: + break; + } + + DEBUG_REPORT_LOG(true, ("Added object %s to collision world [%s] at (%f,%f,%f)\n", name, ms_sptatialDatabaseNames[index], object->getPosition_w().x, object->getPosition_w().y, object->getPosition_w().z)); } - - DEBUG_REPORT_LOG(ConfigSharedCollision::getReportChanges(), ("Added object %s to collision world [%s] at (%f,%f,%f)\n", name, ms_sptatialDatabaseNames[index], object->getPosition_w().x, object->getPosition_w().y, object->getPosition_w().z)); +#endif } } diff --git a/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableBase.cpp b/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableBase.cpp index 98cd481f8..f93a990e1 100755 --- a/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableBase.cpp +++ b/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableBase.cpp @@ -8,6 +8,9 @@ #include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h" #include "sharedDatabaseInterface/DbBindableBase.h" +#include +#include + // ====================================================================== using namespace DB; @@ -35,7 +38,7 @@ Bindable::Bindable(int _indicator) : bool Bindable::isNull() const { - return (indicator==-1); + return (indicator == -1); } // ---------------------------------------------------------------------- diff --git a/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableLong.cpp b/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableLong.cpp index 2aa0818e6..8c5975456 100755 --- a/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableLong.cpp +++ b/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableLong.cpp @@ -18,7 +18,7 @@ BindableLong::BindableLong() : Bindable(), value(-999) { } -BindableLong::BindableLong(long int _value) : Bindable(sizeof(value)), value(_value) +BindableLong::BindableLong(long _value) : Bindable(sizeof(value)), value(_value) { } @@ -29,14 +29,15 @@ void *BindableLong::getBuffer() // ---------------------------------------------------------------------- -long int BindableLong::getValue() const + +long BindableLong::getValue() const { return value; } // ---------------------------------------------------------------------- -BindableLong &BindableLong::operator=(long int rhs) +BindableLong &BindableLong::operator=(long rhs) { indicator=sizeof(value); value=rhs; @@ -45,7 +46,7 @@ BindableLong &BindableLong::operator=(long int rhs) // ---------------------------------------------------------------------- -void BindableLong::setValue(long int rhs) +void BindableLong::setValue(long rhs) { indicator=sizeof(value); value=rhs; diff --git a/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableLong.h b/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableLong.h index f4dc519c3..cd043c983 100755 --- a/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableLong.h +++ b/engine/shared/library/sharedDatabaseInterface/src/shared/core/DbBindableLong.h @@ -3,6 +3,12 @@ // DBBindableLong.h // copyright (c) 2001 Sony Online Entertainment // +// NOTE: This class needs to be flexible with the compiler such that +// when compiling using 32 bit OCI libraries this class is 4 bytes +// in size. When compiling using 64 bit OCI libraries, this class +// must be 8 bytes in size simply because the OCI libraries read +// the data type from the database of a NUMBER field and convert to +// either 4 bytes or 8 bytes depending on architecture used. // ====================================================================== #ifndef INCLUDED_DBBindableLong_H @@ -23,71 +29,85 @@ namespace DB { { public: BindableLong(); - explicit BindableLong(long int _value); + explicit BindableLong(long _value); - long int getValue() const; - void setValue(const long int rhs); - BindableLong &operator=(const long int rhs); + long getValue() const; + void setValue(const long rhs); + BindableLong &operator=(const long rhs); // following alternate getValue's are provided for convenience, particularly in // the auto-generated code: - void getValue(unsigned int &buffer) const; - void getValue(uint32 &buffer) const; // for some reason, our compiler is convinced that uint32 != unsigned int - void getValue(long int &buffer) const; + void getValue(int8_t &buffer) const; + void getValue(uint8_t &buffer) const; + void getValue(int16_t &buffer) const; + void getValue(uint16_t &buffer) const; void getValue(int &buffer) const; - void getValue(int8 &buffer) const; - void getValue(uint8 &buffer) const; + void getValue(unsigned int &buffer) const; + void getValue(long &buffer) const; + void getValue(unsigned long &buffer) const; void *getBuffer(); virtual std::string outputValue() const; private: - long int value; + long value; }; //lint !e1721 !e1509 // no virtual destructor, unusual operator = } // ---------------------------------------------------------------------- -inline void DB::BindableLong::getValue(unsigned int &buffer) const +inline void DB::BindableLong::getValue(int8_t &buffer) const { - buffer=static_cast(getValue()); + buffer=static_cast(getValue()); } // ---------------------------------------------------------------------- -inline void DB::BindableLong::getValue(uint32 &buffer) const +inline void DB::BindableLong::getValue(uint8_t &buffer) const { - buffer=static_cast(getValue()); + buffer=static_cast(getValue()); } - // ---------------------------------------------------------------------- -inline void DB::BindableLong::getValue(long int &buffer) const +inline void DB::BindableLong::getValue(int16_t &buffer) const { buffer=getValue(); } // ---------------------------------------------------------------------- +inline void DB::BindableLong::getValue(uint16_t &buffer) const +{ + buffer=static_cast(getValue()); +} + +// ---------------------------------------------------------------------- + inline void DB::BindableLong::getValue(int &buffer) const { - buffer=getValue(); + buffer=static_cast(getValue()); } // ---------------------------------------------------------------------- -inline void DB::BindableLong::getValue(int8 &buffer) const +inline void DB::BindableLong::getValue(unsigned int &buffer) const { - buffer=static_cast(getValue()); + buffer=static_cast(getValue()); +} +// ---------------------------------------------------------------------- + +inline void DB::BindableLong::getValue(long &buffer) const +{ + buffer=getValue(); } // ---------------------------------------------------------------------- -inline void DB::BindableLong::getValue(uint8 &buffer) const +inline void DB::BindableLong::getValue(unsigned long &buffer) const { - buffer=static_cast(getValue()); + buffer=static_cast(getValue()); } // ====================================================================== diff --git a/engine/shared/library/sharedDatabaseInterface/src/shared/queue/DbTaskRequest.cpp b/engine/shared/library/sharedDatabaseInterface/src/shared/queue/DbTaskRequest.cpp index d4b6f7104..016bb8896 100755 --- a/engine/shared/library/sharedDatabaseInterface/src/shared/queue/DbTaskRequest.cpp +++ b/engine/shared/library/sharedDatabaseInterface/src/shared/queue/DbTaskRequest.cpp @@ -48,7 +48,7 @@ void DB::TaskRequest::workerThreadLoop(DB::Session *ses) { if (qry.fetch() > 0) { - int result; + long result; qry.value.getValue(result); if (result == 1) { diff --git a/engine/shared/library/sharedDatabaseInterface/src_oci/DbBindableVarray.cpp b/engine/shared/library/sharedDatabaseInterface/src_oci/DbBindableVarray.cpp index b0cec73dd..255c4105f 100755 --- a/engine/shared/library/sharedDatabaseInterface/src_oci/DbBindableVarray.cpp +++ b/engine/shared/library/sharedDatabaseInterface/src_oci/DbBindableVarray.cpp @@ -13,6 +13,7 @@ #include "sharedFoundation/NetworkId.h" #include "sharedLog/Log.h" #include +#include // ====================================================================== @@ -56,8 +57,10 @@ bool BindableVarray::create(DB::Session *session, const std::string &name, const 0, OCI_DURATION_SESSION, OCI_TYPEGET_HEADER, - &m_tdo)))) + &m_tdo)))) { + LOG("DatabaseError", ("Could not create BindableVarray (OCITypeByName) for name - %s", name.c_str())); return false; + } if (! (localSession->m_server->checkerr(*localSession, OCIObjectNew (localSession->envhp, @@ -67,8 +70,10 @@ bool BindableVarray::create(DB::Session *session, const std::string &name, const m_tdo, nullptr, OCI_DURATION_DEFAULT, true, - reinterpret_cast(&m_data))))) - return false; + reinterpret_cast(&m_data))))) { + LOG("DatabaseError", ("Could not create BindableVarray (OCIObjectNew) for name - %s", name.c_str())); + return false; + } NOT_NULL(m_tdo); NOT_NULL(m_data); @@ -82,9 +87,11 @@ void BindableVarray::free() { OCISession *localSession = safe_cast(m_session); - IGNORE_RETURN(localSession->m_server->checkerr(*localSession, + if(!(localSession->m_server->checkerr(*localSession, OCIObjectFree (localSession->envhp, - localSession->errhp, m_data, 0))); + localSession->errhp, m_data, 0)))) { + LOG("DatabaseError", ("Could not free up DB object")); + }; m_initialized = false; m_tdo=nullptr; m_data=nullptr; @@ -98,10 +105,14 @@ void BindableVarray::clear() OCISession *localSession = safe_cast(m_session); sb4 size=0; - if (! (localSession->m_server->checkerr(*localSession, OCICollSize(localSession->envhp, localSession->errhp, m_data, &size)))) - return; - if (! (localSession->m_server->checkerr(*localSession, OCICollTrim(localSession->envhp, localSession->errhp, size, m_data)))) - return; + if (! (localSession->m_server->checkerr(*localSession, OCICollSize(localSession->envhp, localSession->errhp, m_data, &size)))) { + LOG("DatabaseError", ("Could not clear bindablevarray - OCICollSize")); + return; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollTrim(localSession->envhp, localSession->errhp, size, m_data)))) { + LOG("DatabaseError", ("Could not clear bindablevarray - OCICollTrim")); + return; + } } // ---------------------------------------------------------------------- @@ -120,7 +131,7 @@ OCIType* BindableVarray::getTDO() // ---------------------------------------------------------------------- -bool BindableVarrayNumber::push_back(int value) +bool BindableVarrayNumber::push_back(int16_t value) { OCINumber buffer; @@ -128,17 +139,21 @@ bool BindableVarrayNumber::push_back(int value) OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVArray int16 value OCINumberFromInt - %d", value)); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVArray int16 value OCICollAppend - %d", value)); + return false; + } return true; } // ---------------------------------------------------------------------- -bool BindableVarrayNumber::push_back(long int value) +bool BindableVarrayNumber::push_back(int32_t value) { OCINumber buffer; @@ -146,27 +161,35 @@ bool BindableVarrayNumber::push_back(long int value) OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVArray int32 value OCINumberFromInt - %d", value)); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVArray int32 value OCINumberFromInt - %d", value)); + return false; + } return true; } // ---------------------------------------------------------------------- -bool BindableVarrayNumber::push_back(int64 value) +bool BindableVarrayNumber::push_back(int64_t value) { OCINumber buffer; - + OCIInd buffer_indicator (OCI_IND_NOTNULL); - + OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVArray int64 value OCINumberFromInt - %d", value)); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVArray int64 value OCINumberFromInt - %d", value)); + return false; + } return true; } @@ -194,17 +217,21 @@ bool BindableVarrayNumber::push_back(double value) OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCINumberFromReal(localSession->errhp, &value, sizeof(value), &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCINumberFromReal(localSession->errhp, &value, sizeof(value), &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVArray double value OCINumberFromInt - %d", value)); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVArray double value OCINumberFromInt - %d", value)); + return false; + } return true; } // ---------------------------------------------------------------------- -bool BindableVarrayNumber::push_back(bool IsNULL, int value) +bool BindableVarrayNumber::push_back(bool IsNULL, int16_t value) { OCINumber buffer; @@ -220,17 +247,21 @@ bool BindableVarrayNumber::push_back(bool IsNULL, int value) } OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayNumber int16 value OCINumberFromInt - %d", value)); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayNumber int16 value OCINumberFromInt - %d", value)); + return false; + } return true; } // ---------------------------------------------------------------------- -bool BindableVarrayNumber::push_back(bool IsNULL, long int value) +bool BindableVarrayNumber::push_back(bool IsNULL, int32_t value) { OCINumber buffer; @@ -247,19 +278,23 @@ bool BindableVarrayNumber::push_back(bool IsNULL, long int value) OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayNumber int32 value OCINumberFromInt - %d", value)); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayNumber int32 value OCINumberFromInt - %d", value)); + return false; + } return true; } // ---------------------------------------------------------------------- -bool BindableVarrayNumber::push_back(bool IsNULL, int64 value) +bool BindableVarrayNumber::push_back(bool IsNULL, int64_t value) { OCINumber buffer; - + OCIInd buffer_indicator; if ( IsNULL ) @@ -270,13 +305,17 @@ bool BindableVarrayNumber::push_back(bool IsNULL, int64 value) { buffer_indicator = OCI_IND_NOTNULL; } - + OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayNumber int64 value OCINumberFromInt - %d", value)); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayNumber int64 value OCINumberFromInt - %d", value)); + return false; + } return true; } @@ -313,10 +352,14 @@ bool BindableVarrayNumber::push_back(bool IsNULL, double value) OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCINumberFromReal(localSession->errhp, &value, sizeof(value), &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCINumberFromReal(localSession->errhp, &value, sizeof(value), &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayNumber double value OCINumberFromInt - %d", value)); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayNumber double value OCINumberFromInt - %d", value)); + return false; + } return true; } @@ -337,8 +380,10 @@ std::string BindableVarrayNumber::outputValue() const sb4 size; std::string result("["); - if (! (localSession->m_server->checkerr(*localSession, OCICollSize(localSession->envhp, localSession->errhp, m_data, &size)))) + if (! (localSession->m_server->checkerr(*localSession, OCICollSize(localSession->envhp, localSession->errhp, m_data, &size)))) { + LOG("DatabaseError", ("Could not get outputValue - OCICollSize - %d", size)); return "[*ERROR*]"; + } for (sb4 i=0; i < size; ++i) { @@ -365,15 +410,19 @@ std::string BindableVarrayNumber::outputValue() const buffer[sizeof(buffer)-1]='\0'; result += buffer; } - else + else { + LOG("DatabaseError", ("Could not get output value from OCINumberToReal - %d", value)); result += "*ERROR*"; + } } } else result += "*NO ELEMENT*"; } - else - result += "*ERROR*"; + else { + LOG("DatabaseError", ("Could not get output value from OCICollGetElem")); + result += "*ERROR*"; + } } result+=']'; return result; @@ -419,10 +468,14 @@ bool BindableVarrayString::push_back(const std::string &value) } } - if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast(const_cast(value.c_str())), effectiveLength, &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast(const_cast(value.c_str())), effectiveLength, &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayString string value (OCIStringAssignText) - %s", value.c_str())); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayString string value (OCICollAppend) - %s", value.c_str())); + return false; + } return true; } @@ -441,10 +494,14 @@ bool BindableVarrayString::push_back(bool bvalue) OCIInd buffer_indicator (OCI_IND_NOTNULL); OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast(const_cast(value.c_str())), value.length(), &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast(const_cast(value.c_str())), value.length(), &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayString string value (OCIStringAssignText) - %s", value.c_str())); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayString string value (OCICollAppend) - %s", value.c_str())); + return false; + } return true; } @@ -497,10 +554,14 @@ bool BindableVarrayString::push_back(bool IsNULL, const std::string &value) OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast(const_cast(value.c_str())), effectiveLength, &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data)))) - return false; + if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast(const_cast(value.c_str())), effectiveLength, &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayString string value (OCIStringAssignText) - %s", value.c_str())); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayString string value (OCICollAppend) - %s", value.c_str())); + return false; + } return true; } @@ -528,11 +589,14 @@ bool BindableVarrayString::push_back(bool IsNULL, bool bvalue) OCISession *localSession = safe_cast(m_session); - if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast(const_cast(value.c_str())), value.length(), &buffer)))) - return false; - if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data)))) - return false; - + if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast(const_cast(value.c_str())), value.length(), &buffer)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayString boolean value (OCIStringAssignText) - %s", value.c_str())); + return false; + } + if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data)))) { + LOG("DatabaseError", ("Could not push back BindableVarrayString boolean value (OCICollAppend) - %s", value.c_str())); + return false; + } return true; } @@ -551,8 +615,10 @@ std::string BindableVarrayString::outputValue() const sb4 size; std::string result("["); - if (! (localSession->m_server->checkerr(*localSession, OCICollSize(localSession->envhp, localSession->errhp, m_data, &size)))) + if (! (localSession->m_server->checkerr(*localSession, OCICollSize(localSession->envhp, localSession->errhp, m_data, &size)))) { + LOG("DatabaseError", ("Could not get outputValue BindableVarrayString (OCICollSize)")); return "[*ERROR*]"; + } for (sb4 i=0; i < size; ++i) { @@ -581,8 +647,10 @@ std::string BindableVarrayString::outputValue() const else result += "*NO ELEMENT*"; } - else - result += "*ERROR*"; + else { + LOG("DatabaseError", ("Could not get outputValue BindableVarrayString OCICollGetElem")); + return "[*ERROR*]"; + } } result+=']'; return result; diff --git a/engine/shared/library/sharedDatabaseInterface/src_oci/DbBindableVarray.h b/engine/shared/library/sharedDatabaseInterface/src_oci/DbBindableVarray.h index a9233b6f2..f29cca66b 100755 --- a/engine/shared/library/sharedDatabaseInterface/src_oci/DbBindableVarray.h +++ b/engine/shared/library/sharedDatabaseInterface/src_oci/DbBindableVarray.h @@ -57,14 +57,14 @@ namespace DB class BindableVarrayNumber : public BindableVarray { public: - bool push_back(bool IsNULL, int value); + bool push_back(bool IsNULL, int16_t value); bool push_back(bool IsNULL, double value); - bool push_back(bool IsNULL, long int value); - bool push_back(bool IsNULL, int64 value); - bool push_back(int value); + bool push_back(bool IsNULL, int32_t value); + bool push_back(bool IsNULL, int64_t value); + bool push_back(int16_t value); bool push_back(double value); - bool push_back(long int value); - bool push_back(int64 value); + bool push_back(int32_t value); + bool push_back(int64_t value); virtual std::string outputValue() const; }; diff --git a/engine/shared/library/sharedDatabaseInterface/src_oci/OciQueryImplementation.cpp b/engine/shared/library/sharedDatabaseInterface/src_oci/OciQueryImplementation.cpp index b4486dc8c..18f06e538 100755 --- a/engine/shared/library/sharedDatabaseInterface/src_oci/OciQueryImplementation.cpp +++ b/engine/shared/library/sharedDatabaseInterface/src_oci/OciQueryImplementation.cpp @@ -9,6 +9,7 @@ #include "OciQueryImplementation.h" #include +#include #include "sharedDatabaseInterface/Bindable.h" #include "sharedDatabaseInterface/DbBindableVarray.h" @@ -62,8 +63,10 @@ bool DB::OCIQueryImpl::setup(Session *session) if (!m_server->checkerr(*m_session, OCIHandleAlloc( m_session->envhp, reinterpret_cast(&m_stmthp), - OCI_HTYPE_STMT, 0, 0))) - return false; + OCI_HTYPE_STMT, 0, 0))) { + LOG("DatabaseError", ("Could not setup query")); + return false; + } m_cursorhp=m_stmthp; // later on, we'll separate these two if needed @@ -87,15 +90,19 @@ bool DB::OCIQueryImpl::prepare() reinterpret_cast(const_cast(m_sql.c_str())), m_sql.length(), (ub4) OCI_NTV_SYNTAX, - (ub4) OCI_DEFAULT))) - return false; + (ub4) OCI_DEFAULT))) { + LOG("DatabaseError", ("Could not prepare statement - %s", m_sql.c_str())); + return false; + } if (m_query->getMode()==Query::MODE_PLSQL_REFCURSOR) { m_cursorhp=0; // may not be necessary -- OCI docs unclear if (!m_server->checkerr(*m_session, OCIHandleAlloc( m_session->envhp, (dvoid **) &m_cursorhp, - OCI_HTYPE_STMT, 0, 0))) + OCI_HTYPE_STMT, 0, 0))) { + LOG("DatabaseError", ("Could not prepare statement - could not allocate handle for statement - %s", m_sql.c_str())); return false; - + } + if (!m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, &m_procBind, @@ -109,8 +116,10 @@ bool DB::OCIQueryImpl::prepare() 0, 0, 0, - OCI_DEFAULT))) + OCI_DEFAULT))) { + LOG("DatabaseError", ("Could not prepare statement - could not bind by position on statement - %s", m_sql.c_str())); return false; + } } return true; @@ -188,8 +197,10 @@ bool DB::OCIQueryImpl::exec() { WARNING_STRICT_FATAL(!m_session->isOkToFetch(),("Calling fetch after commit, without an execute in between (may cause Oracle to crash).")); sword status=OCIStmtFetch (m_cursorhp, m_session->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT); - if (!m_server->checkerr(*m_session,status)) - return false; + if (!m_server->checkerr(*m_session,status)) { + LOG("DatabaseError", ("Could not establish session when executing statement (NO Data) - %s", m_sql.c_str())); + return false; + } } m_endOfData=true; } @@ -212,8 +223,10 @@ bool DB::OCIQueryImpl::exec() m_dataReady=true; } } - else - return false; + else { + LOG("DatabaseError", ("Could not establish session when executing statement (Data) - %s", m_sql.c_str())); + return false; + } } m_inUse=true; @@ -246,8 +259,10 @@ int DB::OCIQueryImpl::fetch() (dvoid *)& rows, (ub4 *) &sizep, OCI_ATTR_ROWS_FETCHED, m_session->errhp); sword status=OCIStmtFetch (m_cursorhp, m_session->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT); // cancel the cursor - if (!m_server->checkerr(*m_session,status)) - return -1; + if (!m_server->checkerr(*m_session,status)) { + LOG("DatabaseError", ("Could not fetch from query (NO Data) - %s", m_sql.c_str())); + return -1; + } m_endOfData=true; if (rows!=0) { @@ -259,8 +274,10 @@ int DB::OCIQueryImpl::fetch() } else { - if (!m_server->checkerr(*m_session,status)) - return -1; + if (!m_server->checkerr(*m_session,status)) { + LOG("DatabaseError", ("Could not fetch from query (Data) - %s", m_sql.c_str())); + return -1; + } } ub4 rows; @@ -323,8 +340,11 @@ void DB::OCIQueryImpl::done() { NOT_NULL(m_stmthp); - if (m_autocommit) - m_server->checkerr(*m_session, OCITransCommit(m_session->svchp, m_session->errhp, 0)); + if (m_autocommit) { + if(!(m_server->checkerr(*m_session, OCITransCommit(m_session->svchp, m_session->errhp, 0)))) { + LOG("DatabaseError", ("Could not complete transaction - %s", m_sql.c_str())); + } + } OCIHandleFree(m_stmthp, OCI_HTYPE_STMT); if (m_cursorhp!=m_stmthp) @@ -354,7 +374,9 @@ int DB::OCIQueryImpl::rowCount() int value; - m_server->checkerr(*m_session, OCIAttrGet (m_cursorhp, OCI_HTYPE_STMT,&value,0,OCI_ATTR_ROW_COUNT,m_session->errhp)); + if(!(m_server->checkerr(*m_session, OCIAttrGet (m_cursorhp, OCI_HTYPE_STMT,&value,0,OCI_ATTR_ROW_COUNT,m_session->errhp)))) { + LOG("DatabaseError", ("Could not get row count from query - %s", m_sql.c_str())); + } return value; } @@ -452,7 +474,7 @@ bool DB::OCIQueryImpl::bindCol(BindableLong &buffer) { BindRec *br=addBindRec(buffer); - m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, + if(!(m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, &(br->defnp), m_session->errhp, nextColumn++, @@ -462,16 +484,20 @@ bool DB::OCIQueryImpl::bindCol(BindableLong &buffer) br->getIndicatorPointer(), br->getLengthPointer(), (ub2 *)0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind column (by position) - %s", m_sql.c_str())); + } if (m_numElements > 1) { - m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, + if(!(m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, m_session->errhp, m_skipSize, br->getIndicatorSkipSize(), br->getLengthSkipSize(), - 0)); + 0)))) { + LOG("DatabaseError", ("Could not bind column (define array) - %s", m_sql.c_str())); + } } return true; } @@ -482,7 +508,7 @@ bool DB::OCIQueryImpl::bindParameter(BindableLong &buffer) { BindRec *br=addBindRec(buffer); - return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, + if(!(m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, &(br->bindp), m_session->errhp, nextParameter++, @@ -494,7 +520,11 @@ bool DB::OCIQueryImpl::bindParameter(BindableLong &buffer) 0, 0, 0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind parameter of statement - %s", m_sql.c_str())); + return false; + } + return true; } // ---------------------------------------------------------------------- @@ -503,7 +533,7 @@ bool DB::OCIQueryImpl::bindCol(BindableStringBase &buffer) { BindRec *br=addBindRec(buffer); - m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, + if(!(m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, &(br->defnp), m_session->errhp, nextColumn++, @@ -513,16 +543,20 @@ bool DB::OCIQueryImpl::bindCol(BindableStringBase &buffer) br->getIndicatorPointer(), br->getLengthPointer(), (ub2 *)0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind column of statement (by position) - %s", m_sql.c_str())); + } if (m_numElements > 1) { - m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, + if(!(m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, m_session->errhp, m_skipSize, br->getIndicatorSkipSize(), br->getLengthSkipSize(), - 0)); + 0)))) { + LOG("DatabaseError", ("Could not bind column of statement (by array) - %s", m_sql.c_str())); + } } return true; } @@ -534,7 +568,7 @@ bool DB::OCIQueryImpl::bindParameter(BindableStringBase &buffer) BindRec *br=addBindRec(buffer); br->stringAdjust=true; - return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, + if(!(m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, &(br->bindp), m_session->errhp, nextParameter++, @@ -546,7 +580,11 @@ bool DB::OCIQueryImpl::bindParameter(BindableStringBase &buffer) 0, 0, 0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind parameter of statement (by position) - %s", m_sql.c_str())); + return false; + } + return true; } // ---------------------------------------------------------------------- @@ -555,7 +593,7 @@ bool DB::OCIQueryImpl::bindCol(BindableUnicodeBase &buffer) { BindRec *br=addBindRec(buffer); - m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, + if(!(m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, &(br->defnp), m_session->errhp, nextColumn++, @@ -565,16 +603,20 @@ bool DB::OCIQueryImpl::bindCol(BindableUnicodeBase &buffer) br->getIndicatorPointer(), br->getLengthPointer(), (ub2 *)0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind column of statement (by position) (BindableUnicodeBase) - %s", m_sql.c_str())); + } if (m_numElements > 1) { - m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, + if(!(m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, m_session->errhp, m_skipSize, br->getIndicatorSkipSize(), br->getLengthSkipSize(), - 0)); + 0)))) { + LOG("DatabaseError", ("Could not bind column of statement (by array) (BindableUnicodeBase) - %s", m_sql.c_str())); + } } return true; } @@ -587,7 +629,7 @@ bool DB::OCIQueryImpl::bindParameter(BindableUnicodeBase &buffer) br->stringAdjust=true; br->length=static_cast(*(buffer.getIndicator())); - return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, + if(!(m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, &(br->bindp), m_session->errhp, nextParameter++, @@ -599,7 +641,11 @@ bool DB::OCIQueryImpl::bindParameter(BindableUnicodeBase &buffer) 0, 0, 0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind parameter of statement (by position) (BindableUnicodeBase) - %s", m_sql.c_str())); + return false; + } + return true; } // ====================================================================== @@ -608,7 +654,7 @@ bool DB::OCIQueryImpl::bindCol(BindableDouble &buffer) { BindRec *br=addBindRec(buffer); - m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, + if(!(m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, &(br->defnp), m_session->errhp, nextColumn++, @@ -618,15 +664,19 @@ bool DB::OCIQueryImpl::bindCol(BindableDouble &buffer) br->getIndicatorPointer(), br->getLengthPointer(), (ub2 *)0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind column of statement (by position) (BindableDouble) - %s", m_sql.c_str())); + } if (m_numElements > 1) { - m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, + if(!(m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, m_session->errhp, m_skipSize, br->getIndicatorSkipSize(), br->getLengthSkipSize(), - 0)); + 0)))) { + LOG("DatabaseError", ("Could not bind column of statement (by array) (BindableDouble) - %s", m_sql.c_str())); + } } return true; } @@ -637,7 +687,7 @@ bool DB::OCIQueryImpl::bindParameter(BindableDouble &buffer) { BindRec *br=addBindRec(buffer); - return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, + if(!(m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, &(br->bindp), m_session->errhp, nextParameter++, @@ -649,7 +699,11 @@ bool DB::OCIQueryImpl::bindParameter(BindableDouble &buffer) 0, 0, 0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind parameter of statement (by position) (BindableDouble) - %s", m_sql.c_str())); + return false; + } + return true; } // ---------------------------------------------------------------------- @@ -658,7 +712,7 @@ bool DB::OCIQueryImpl::bindCol(BindableBool &buffer) { BindRec *br=addBindRec(buffer); - m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, + if(!(m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp, &(br->defnp), m_session->errhp, nextColumn++, @@ -668,16 +722,20 @@ bool DB::OCIQueryImpl::bindCol(BindableBool &buffer) br->getIndicatorPointer(), br->getLengthPointer(), (ub2 *)0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind column of statement (by position) (BindableBool) - %s", m_sql.c_str())); + } if (m_numElements > 1) { - m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, + if(!(m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp, m_session->errhp, m_skipSize, br->getIndicatorSkipSize(), br->getLengthSkipSize(), - 0)); + 0)))) { + LOG("DatabaseError", ("Could not bind column of statement (by array) (BindableBool) - %s", m_sql.c_str())); + } } return true; } @@ -689,7 +747,7 @@ bool DB::OCIQueryImpl::bindParameter(BindableBool &buffer) BindRec *br=addBindRec(buffer); br->stringAdjust=true; - return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, + if(!(m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, &(br->bindp), m_session->errhp, nextParameter++, @@ -701,7 +759,11 @@ bool DB::OCIQueryImpl::bindParameter(BindableBool &buffer) 0, 0, 0, - OCI_DEFAULT)); + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind parameter of statement (by array) (BindableBool) - %s", m_sql.c_str())); + return false; + } + return true; } // ---------------------------------------------------------------------- @@ -710,7 +772,7 @@ bool DB::OCIQueryImpl::bindParameter(BindableVarray &buffer) { BindRec *br=addBindRec(buffer); - bool result = m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, + if(!(m_server->checkerr(*m_session, OCIBindByPos (m_stmthp, &(br->bindp), m_session->errhp, nextParameter++, @@ -722,18 +784,22 @@ bool DB::OCIQueryImpl::bindParameter(BindableVarray &buffer) 0, 0, 0, - OCI_DEFAULT)); - - if (!result) - return false; + OCI_DEFAULT)))) { + LOG("DatabaseError", ("Could not bind parameter of statement (by array) (BindableVarray) - %s", m_sql.c_str())); + return false; + } - return m_server->checkerr(*m_session, OCIBindObject (br->bindp, + if(!(m_server->checkerr(*m_session, OCIBindObject (br->bindp, m_session->errhp, buffer.getTDO(), reinterpret_cast(buffer.getBuffer()), 0, 0, - 0)); + 0)))) { + LOG("DatabaseError", ("Could not bind parameter of statement (by object) (BindableVarray) - %s", m_sql.c_str())); + return false; + } + return true; } // ---------------------------------------------------------------------- diff --git a/engine/shared/library/sharedDatabaseInterface/src_oci/OciServer.cpp b/engine/shared/library/sharedDatabaseInterface/src_oci/OciServer.cpp index ed5d8ddf9..9f821b530 100755 --- a/engine/shared/library/sharedDatabaseInterface/src_oci/OciServer.cpp +++ b/engine/shared/library/sharedDatabaseInterface/src_oci/OciServer.cpp @@ -79,7 +79,7 @@ bool DB::OCIServer::checkerr(OCISession const & session, int status) REPORT_LOG(true,("Database Error - %.*s\n", 512, errbuf)); return false; default: - FATAL(true,("Unhandled Database Error - %.*s\n", 512, errbuf)); + REPORT_LOG(true,("Unhandled Database Error - %.*s\n", 512, errbuf)); break; } diff --git a/engine/shared/library/sharedDatabaseInterface/src_oci/OciSession.cpp b/engine/shared/library/sharedDatabaseInterface/src_oci/OciSession.cpp index eb6e9d2c7..e5d6ecbec 100755 --- a/engine/shared/library/sharedDatabaseInterface/src_oci/OciSession.cpp +++ b/engine/shared/library/sharedDatabaseInterface/src_oci/OciSession.cpp @@ -32,28 +32,6 @@ using namespace DB::OCISessionNamespace; // ====================================================================== -static dvoid *mallocHook(dvoid *, size_t size) -{ - return reinterpret_cast(new char[size]); -} - -// ---------------------------------------------------------------------- - -static dvoid *reallocHook(dvoid *, dvoid *memptr, size_t newsize) -{ - return reinterpret_cast(realloc(memptr, newsize)); -} - -// ---------------------------------------------------------------------- - -static void freeHook(dvoid *, dvoid *memptr) -{ - if (memptr) - delete [] reinterpret_cast(memptr); -} - -// ====================================================================== - DB::OCISession::OCISession(DB::OCIServer *server) : m_server(server), envhp(nullptr), @@ -119,6 +97,7 @@ bool DB::OCISession::connect() if (! connected) { ++retryCount; + LOG("DatabaseError", ("Could not connect to the database (DSN=%s) after %d attempts.", m_server->getDSN(), retryCount)); DEBUG_REPORT_LOG(retryCount<5,("Retrying database connection\n")); Os::sleep(1000); } @@ -162,6 +141,7 @@ bool DB::OCISession::connect() } else { + LOG("DatabaseError", ("Invalid password provided when connecting to the database - disconnecting.")); disconnect(); // cleanup connected=false; } @@ -233,12 +213,20 @@ bool DB::OCISession::setAutoCommitMode(bool autocommit) bool DB::OCISession::commitTransaction() { m_okToFetch = false; - return m_server->checkerr(*this, OCITransCommit(svchp, errhp, 0)); + if(!(m_server->checkerr(*this, OCITransCommit(svchp, errhp, 0)))) { + LOG("DatabaseError", ("Unable to commit transaction.")); + return false; + } + return true; } bool DB::OCISession::rollbackTransaction() { - return m_server->checkerr(*this, OCITransRollback(svchp, errhp, 0)); + if(!(m_server->checkerr(*this, OCITransRollback(svchp, errhp, 0)))) { + LOG("DatabaseError", ("Unable to rollback transaction.")); + return false; + } + return true; } bool DB::OCISession::reset() diff --git a/engine/shared/library/sharedDebug/src/linux/DebugHelp.cpp b/engine/shared/library/sharedDebug/src/linux/DebugHelp.cpp index c1639ebde..e7a2fb7b9 100755 --- a/engine/shared/library/sharedDebug/src/linux/DebugHelp.cpp +++ b/engine/shared/library/sharedDebug/src/linux/DebugHelp.cpp @@ -174,6 +174,14 @@ inline unsigned int dwarfGet(char const *src, u_int32_t &dest) // ---------------------------------------------------------------------- +inline unsigned int dwarfGet(char const *src, u_int64_t &dest) +{ + memcpy(&dest, src, sizeof(u_int64_t)); + return sizeof(u_int64_t); +} + +// ---------------------------------------------------------------------- + class LEB128 { public: @@ -294,7 +302,7 @@ static bool dwarfSearch(char const *dwarfLines, unsigned int linesLength, void c { int progFile = 0; int progLine = 1; - u_int32_t progAddr = 0; + u_int64_t progAddr = 0; bool done = false; bool valid = false; @@ -384,9 +392,9 @@ static bool dwarfSearch(char const *dwarfLines, unsigned int linesLength, void c if (valid) { - unsigned int addrOffset = 0; - if (progAddr < reinterpret_cast(info.dli_fbase)) - addrOffset = reinterpret_cast(info.dli_fbase); + u_int64_t addrOffset = 0; + if (progAddr < reinterpret_cast(info.dli_fbase)) + addrOffset = reinterpret_cast(info.dli_fbase); const void *testAddr = reinterpret_cast(progAddr+addrOffset); if (testAddr >= addr) { @@ -509,12 +517,12 @@ static bool stabSearch(Stab const *stab, unsigned int stabSize, char const *stab if (reinterpret_cast(stab->n_value) > info.dli_fbase) funcBase = reinterpret_cast(stab->n_value); else - funcBase = reinterpret_cast(reinterpret_cast(info.dli_fbase)+stab->n_value); + funcBase = reinterpret_cast(reinterpret_cast(info.dli_fbase)+stab->n_value); foundSrcLine = -1; } else if (stab->n_type == N_SLINE && addr >= funcBase) // source line { - if (stab->n_value < reinterpret_cast(addr)-reinterpret_cast(funcBase)) + if (stab->n_value < reinterpret_cast(addr)-reinterpret_cast(funcBase)) foundSrcLine = stab->n_desc; else { @@ -667,7 +675,7 @@ void DebugHelp::remove() // ---------------------------------------------------------------------- -bool DebugHelp::lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line) +bool DebugHelp::lookupAddress(uint64 address, char *libName, char *fileName, int fileNameLength, int &line) { return lookupAddressInfo(reinterpret_cast(address), libName, fileName, line, fileNameLength); } diff --git a/engine/shared/library/sharedDebug/src/linux/DebugHelp.h b/engine/shared/library/sharedDebug/src/linux/DebugHelp.h index 972b49790..e297f8ebf 100755 --- a/engine/shared/library/sharedDebug/src/linux/DebugHelp.h +++ b/engine/shared/library/sharedDebug/src/linux/DebugHelp.h @@ -20,7 +20,7 @@ class DebugHelp static void remove(); static void getCallStack(uint32 *callStack, int sizeOfCallStack); - static bool lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line); + static bool lookupAddress(uint64 address, char *libName, char *fileName, int fileNameLength, int &line); }; // ====================================================================== diff --git a/engine/shared/library/sharedDebug/src/win32/DebugHelp.h b/engine/shared/library/sharedDebug/src/win32/DebugHelp.h index ead64d75b..74e379abe 100755 --- a/engine/shared/library/sharedDebug/src/win32/DebugHelp.h +++ b/engine/shared/library/sharedDebug/src/win32/DebugHelp.h @@ -10,7 +10,7 @@ // ====================================================================== -typedef unsigned long uint32; +typedef uint32_t uint32; // ====================================================================== diff --git a/engine/shared/library/sharedFile/src/shared/FileManifest.cpp b/engine/shared/library/sharedFile/src/shared/FileManifest.cpp index c55527755..ebbd84572 100755 --- a/engine/shared/library/sharedFile/src/shared/FileManifest.cpp +++ b/engine/shared/library/sharedFile/src/shared/FileManifest.cpp @@ -40,10 +40,13 @@ namespace FileManifestNamespace static TransitionVector s_transitionVector; static bool s_installed = false; static bool s_updateManifest = false; + static std::string s_currentSceneId = "none"; + +#if PRODUCTION == 0 static int s_accessThreshold = -1; - static std::string s_currentSceneId = "none"; static bool s_isValidScene = false; static bool s_isTransitionScene = true; +#endif const static std::string s_manifestDataTable = "datatables/manifest/skufree.iff"; @@ -213,8 +216,10 @@ void FileManifest::remove() DEBUG_REPORT_LOG_PRINT((i->second)->accesses <= s_accessThreshold, ("FileManifestAccessReport:\t%s\t%s\t%i\t%i\n", ((i->second)->name).c_str(), ((i->second)->scene).c_str(), (i->second)->size, (i->second)->accesses)); // delete the actual entry - delete i->second; - i->second = 0; + if(i->second != 0) { + delete i->second; + i->second = 0; + } } std::sort(manifestEntries.begin(), manifestEntries.end()); @@ -231,8 +236,10 @@ void FileManifest::remove() for (ManifestMap::iterator i = s_manifest.begin(); i != s_manifest.end(); ++i) { // delete the actual entry - delete i->second; - i->second = 0; + if(i->second != 0) { + delete i->second; + i->second = 0; + } } s_transitionVector.clear(); diff --git a/engine/shared/library/sharedFile/src/shared/Iff.cpp b/engine/shared/library/sharedFile/src/shared/Iff.cpp index 48eaeed12..36e34d150 100755 --- a/engine/shared/library/sharedFile/src/shared/Iff.cpp +++ b/engine/shared/library/sharedFile/src/shared/Iff.cpp @@ -744,10 +744,10 @@ void Iff::insertForm(Tag name, bool shouldEnterForm) void Iff::insertChunk(Tag name, bool shouldEnterChunk) { - const int CHUNK_OVERHEAD = sizeof(Tag) + sizeof(uint32); + const int32_t CHUNK_OVERHEAD = sizeof(Tag) + sizeof(uint32); Tag t; - int offset; + int32 offset; NOT_NULL(data); IFF_DEBUG_FATAL(inChunk, "inside chunk"); diff --git a/engine/shared/library/sharedFoundation/src/linux/PlatformGlue.h b/engine/shared/library/sharedFoundation/src/linux/PlatformGlue.h index 867d7086f..374994cd6 100755 --- a/engine/shared/library/sharedFoundation/src/linux/PlatformGlue.h +++ b/engine/shared/library/sharedFoundation/src/linux/PlatformGlue.h @@ -10,7 +10,7 @@ #include typedef unsigned short int WORD; -typedef unsigned long int DWORD; +typedef uint32_t DWORD; typedef bool BOOL; typedef long long __int64; //lint !e13 !e19 // Error: 13 (Bad type), Error: 19 (Useless declaration) // -TRF- Lint preprocessor discrepency, @todo look into this. typedef __int64 LARGE_INTEGER; diff --git a/engine/shared/library/sharedFoundation/src/shared/CommandLine.cpp b/engine/shared/library/sharedFoundation/src/shared/CommandLine.cpp index 5209d788d..8fba42e97 100755 --- a/engine/shared/library/sharedFoundation/src/shared/CommandLine.cpp +++ b/engine/shared/library/sharedFoundation/src/shared/CommandLine.cpp @@ -1385,12 +1385,11 @@ void CommandLine::absorbString(const char *newString) DEBUG_FATAL(!newString, ("nullptr newString arg")); const int stringLength = static_cast(strlen(newString)); - int requiredBufferSpace; + if (absorbedStringCount) - requiredBufferSpace = stringLength + 2; + DEBUG_FATAL(bufferSize + stringLength + 2 >= STATIC_BUFFER_SIZE, ("newString too large by %d bytes", bufferSize + stringLength + 2 - STATIC_BUFFER_SIZE)); else - requiredBufferSpace = stringLength + 1; - DEBUG_FATAL(bufferSize + requiredBufferSpace >= STATIC_BUFFER_SIZE, ("newString too large by %d bytes", bufferSize + requiredBufferSpace - STATIC_BUFFER_SIZE)); + DEBUG_FATAL(bufferSize + stringLength + 1 >= STATIC_BUFFER_SIZE, ("newString too large by %d bytes", bufferSize + stringLength + 1 - STATIC_BUFFER_SIZE)); if (absorbedStringCount) { diff --git a/engine/shared/library/sharedFoundation/src/shared/FormattedString.h b/engine/shared/library/sharedFoundation/src/shared/FormattedString.h index d778be27b..7d5b80016 100755 --- a/engine/shared/library/sharedFoundation/src/shared/FormattedString.h +++ b/engine/shared/library/sharedFoundation/src/shared/FormattedString.h @@ -18,8 +18,8 @@ class FormattedString FormattedString(); - char const * sprintf(char const * format, ...); - char const * vsprintf(char const * format, va_list const & va); + char const * sprintf(const char * format, ...); + char const * vsprintf(const char * format, va_list va); private: @@ -40,7 +40,7 @@ inline FormattedString::FormattedString() //----------------------------------------------------------------------------- template -inline char const * FormattedString::sprintf(char const * const format, ...) +inline char const * FormattedString::sprintf(const char * format, ...) { char const * result = nullptr; va_list va; @@ -56,7 +56,7 @@ inline char const * FormattedString::sprintf(char const * const form // ---------------------------------------------------------------------- template -inline char const * FormattedString::vsprintf(char const * const format, va_list const & va) +inline char const * FormattedString::vsprintf(const char * format, va_list va) { // Format the string diff --git a/engine/shared/library/sharedFoundation/src/shared/Misc.h b/engine/shared/library/sharedFoundation/src/shared/Misc.h index 1c29b6edb..d0e70c941 100755 --- a/engine/shared/library/sharedFoundation/src/shared/Misc.h +++ b/engine/shared/library/sharedFoundation/src/shared/Misc.h @@ -230,7 +230,7 @@ inline void *memmove(void *destination, const void *source, int length) { DEBUG_FATAL(!destination, ("nullptr destination arg")); DEBUG_FATAL(!source, ("nullptr source arg")); - return memmove(destination, source, static_cast(length)); + return memmove(destination, source, static_cast(length)); } // ---------------------------------------------------------------------- diff --git a/engine/shared/library/sharedFoundation/src/shared/NetworkId.h b/engine/shared/library/sharedFoundation/src/shared/NetworkId.h index 18ada6192..112fc96c6 100755 --- a/engine/shared/library/sharedFoundation/src/shared/NetworkId.h +++ b/engine/shared/library/sharedFoundation/src/shared/NetworkId.h @@ -68,8 +68,8 @@ class NetworkId friend class DB::BindableNetworkId; - private: - explicit NetworkId(int value); // catch people who incorrectly try to construct one of these from an int +// private: +// explicit NetworkId(int value); // catch people who incorrectly try to construct one of these from an int // also makes constructing one of these from any other incorrect numeric type ambiguous }; diff --git a/engine/shared/library/sharedFoundationTypes/src/linux/FoundationTypesLinux.h b/engine/shared/library/sharedFoundationTypes/src/linux/FoundationTypesLinux.h index 386c4ffb4..347b06b4a 100755 --- a/engine/shared/library/sharedFoundationTypes/src/linux/FoundationTypesLinux.h +++ b/engine/shared/library/sharedFoundationTypes/src/linux/FoundationTypesLinux.h @@ -10,18 +10,19 @@ #define PLATFORM_LINUX #include +#include // ====================================================================== // basic types that we assume to be around -typedef unsigned int uint; +typedef uint32_t uint; typedef unsigned char uint8; typedef unsigned short uint16; -typedef unsigned long uint32; +typedef uint32_t uint32; typedef signed char int8; typedef signed short int16; -typedef signed long int32; -typedef signed long long int int64; -typedef unsigned long long int uint64; +typedef int32_t int32; +typedef int64_t int64; +typedef uint64_t uint64; typedef float real; typedef FILE* FILE_HANDLE; diff --git a/engine/shared/library/sharedFoundationTypes/src/win32/FoundationTypesWin32.h b/engine/shared/library/sharedFoundationTypes/src/win32/FoundationTypesWin32.h index 622039d8b..43a297abd 100755 --- a/engine/shared/library/sharedFoundationTypes/src/win32/FoundationTypesWin32.h +++ b/engine/shared/library/sharedFoundationTypes/src/win32/FoundationTypesWin32.h @@ -15,17 +15,18 @@ #define PLATFORM_WIN32 +#include // ====================================================================== // basic types that we assume to be around typedef unsigned char uint8; typedef unsigned short uint16; -typedef unsigned long uint32; -typedef unsigned __int64 uint64; +typedef uint32_t uint32; +typedef uint64_t uint64; typedef signed char int8; typedef signed short int16; -typedef signed long int32; -typedef signed __int64 int64; +typedef int32_t int32; +typedef int64_t int64; typedef int FILE_HANDLE; // ====================================================================== diff --git a/engine/shared/library/sharedGame/src/shared/core/TextManager.cpp b/engine/shared/library/sharedGame/src/shared/core/TextManager.cpp index 741f494e2..3f522fcdd 100755 --- a/engine/shared/library/sharedGame/src/shared/core/TextManager.cpp +++ b/engine/shared/library/sharedGame/src/shared/core/TextManager.cpp @@ -120,7 +120,7 @@ void TextManagerNamespace::getAppropriateWord(Unicode::String &text) // Sub-string search time for words that are listed for sub-string searches Unicode::String lowerText(Unicode::toLower(text)); - unsigned int findStartPosition = 0; + size_t findStartPosition = 0; for (;;) { @@ -137,7 +137,7 @@ void TextManagerNamespace::getAppropriateWord(Unicode::String &text) continue; } - unsigned int index = lowerText.find(cussWord, findStartPosition); + size_t index = lowerText.find(cussWord, findStartPosition); if (index != Unicode::String::npos) { @@ -145,10 +145,10 @@ void TextManagerNamespace::getAppropriateWord(Unicode::String &text) // Found a bad word, replace the word - unsigned int const letterCount = cussWord.size(); + size_t const letterCount = cussWord.size(); Unicode::String filterLetter; - for (unsigned int i = 0; i < letterCount; ++i) + for (size_t i = 0; i < letterCount; ++i) { getFilterLetter(filterLetter); @@ -297,8 +297,8 @@ Unicode::String TextManager::filterText(Unicode::String const &text) { Unicode::String result(text); Unicode::String::const_iterator iterText = text.begin(); - int startIndex = Unicode::String::npos; - int currentIndex = 0; + size_t startIndex = Unicode::String::npos; + size_t currentIndex = 0; { // Walk through the text finding sections of alpha characters. @@ -309,12 +309,12 @@ Unicode::String TextManager::filterText(Unicode::String const &text) { Unicode::unicode_char_t const character = (*iterText); - if ( (static_cast(startIndex) == Unicode::String::npos) + if ( (startIndex == Unicode::String::npos) && isAlpha(character)) { startIndex = currentIndex; } - else if ( (static_cast(startIndex) != Unicode::String::npos) + else if ( (startIndex != Unicode::String::npos) && !isAlpha(character)) { checkText(result, startIndex, currentIndex); @@ -327,7 +327,7 @@ Unicode::String TextManager::filterText(Unicode::String const &text) // Possibly check the last word - if (static_cast(startIndex) != Unicode::String::npos) + if (startIndex != Unicode::String::npos) { checkText(result, startIndex, currentIndex); } @@ -346,12 +346,12 @@ Unicode::String TextManager::filterText(Unicode::String const &text) { Unicode::unicode_char_t const character = (*iterText); - if ( (static_cast(startIndex) == Unicode::String::npos) + if ( (startIndex == Unicode::String::npos) && character != static_cast(' ')) { startIndex = currentIndex; } - else if ( (static_cast(startIndex) != Unicode::String::npos) + else if ( (startIndex != Unicode::String::npos) && character == static_cast(' ')) { checkText(result, startIndex, currentIndex); @@ -364,7 +364,7 @@ Unicode::String TextManager::filterText(Unicode::String const &text) // Possibly check the last word - if (static_cast(startIndex) != Unicode::String::npos) + if (startIndex != Unicode::String::npos) { checkText(result, startIndex, currentIndex); } diff --git a/engine/shared/library/sharedGame/src/shared/quest/PlayerQuestData.cpp b/engine/shared/library/sharedGame/src/shared/quest/PlayerQuestData.cpp index 841f584b4..29f20d491 100755 --- a/engine/shared/library/sharedGame/src/shared/quest/PlayerQuestData.cpp +++ b/engine/shared/library/sharedGame/src/shared/quest/PlayerQuestData.cpp @@ -259,8 +259,8 @@ namespace Archive char temp[200]; Command c; - size_t commandCount; - size_t baselineCommandCount; //lint !e578 hides a symbol elsewhere + int32_t commandCount; + int32_t baselineCommandCount; //lint !e578 hides a symbol elsewhere Archive::get(source, commandCount); Archive::get(source, baselineCommandCount); @@ -274,7 +274,7 @@ namespace Archive // We need to sort the quests by age SortableQuestList sortedQuests; - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { Archive::get(source, c.cmd); Archive::get(source, c.key); @@ -314,8 +314,8 @@ namespace Archive char temp[200]; AutoDeltaMap::Command c; - Archive::put(target, countCharacter(buffer,':')); - Archive::put(target, static_cast(0)); // baselineCommandCount + Archive::put(target, static_cast (countCharacter(buffer,':'))); + Archive::put(target, static_cast (0)); // baselineCommandCount int tempPos = 0; for (std::string::const_iterator i=buffer.begin(); i!=buffer.end(); ++i) diff --git a/engine/shared/library/sharedMessageDispatch/src/shared/Message.cpp b/engine/shared/library/sharedMessageDispatch/src/shared/Message.cpp index f3d6f4b5e..5cca2bafb 100755 --- a/engine/shared/library/sharedMessageDispatch/src/shared/Message.cpp +++ b/engine/shared/library/sharedMessageDispatch/src/shared/Message.cpp @@ -24,9 +24,9 @@ namespace MessageDispatch Returns an STL hash of the type name. */ -const unsigned long int MessageBase::makeMessageTypeFromString(const char * const idString) +const uint32_t MessageBase::makeMessageTypeFromString(const char * const idString) { - unsigned long int result = 0; + uint32_t result = 0; #if PRODUCTION == 0 result = LabelHash::hashLabel("MessageDispatch", idString); #else @@ -59,7 +59,7 @@ type(0) @author Justin Randall */ -MessageBase::MessageBase(const unsigned long int newType) : +MessageBase::MessageBase(const uint32_t newType) : type(newType) { } diff --git a/engine/shared/library/sharedMessageDispatch/src/shared/Message.h b/engine/shared/library/sharedMessageDispatch/src/shared/Message.h index 0a355f1f9..50dfcfdc9 100755 --- a/engine/shared/library/sharedMessageDispatch/src/shared/Message.h +++ b/engine/shared/library/sharedMessageDispatch/src/shared/Message.h @@ -26,16 +26,16 @@ namespace MessageDispatch { public: explicit MessageBase(const char * const typeName); - explicit MessageBase(const unsigned long int type); + explicit MessageBase(const uint32_t type); virtual ~MessageBase(); - static const unsigned long int makeMessageTypeFromString(const char * const id); - const unsigned long int getType() const; + static const uint32_t makeMessageTypeFromString(const char * const id); + const uint32_t getType() const; const bool isType(const char * const typeName) const; - void setType(const unsigned long int newType); + void setType(const uint32_t newType); void setType(const char * const typeName); private: MessageBase(); - unsigned long int type; + uint32_t type; }; /** @@ -50,9 +50,9 @@ namespace MessageDispatch { public: explicit Message(const char * const typeName=""); - explicit Message(const unsigned long int type); + explicit Message(const uint32_t type); Message(const char * const typeName, const ValueType & value); - Message(const unsigned long int type, const ValueType & value); + Message(const uint32_t type, const ValueType & value); explicit Message(const Message & source); virtual ~Message(); Message & operator = (const Message & rhs); @@ -69,7 +69,7 @@ namespace MessageDispatch @return the type of the Message. The type is an STL hash of the type name. */ - inline const unsigned long int MessageBase::getType() const + inline const uint32_t MessageBase::getType() const { return type; } @@ -85,7 +85,7 @@ namespace MessageDispatch /** @brief set or reset the type identifier */ - inline void MessageBase::setType(const unsigned long newType) + inline void MessageBase::setType(const uint32_t newType) { type = newType; } @@ -116,7 +116,7 @@ namespace MessageDispatch } template - inline Message::Message(const unsigned long int type) : + inline Message::Message(const uint32_t type) : MessageBase(type), value() { @@ -142,7 +142,7 @@ namespace MessageDispatch } template - inline Message::Message(const unsigned long int type, const ValueType & newValue) : + inline Message::Message(const uint32_t type, const ValueType & newValue) : MessageBase(type), value(newValue) { diff --git a/engine/shared/library/sharedNetwork/src/linux/Sock.cpp b/engine/shared/library/sharedNetwork/src/linux/Sock.cpp index 22b293589..5ff32be6e 100755 --- a/engine/shared/library/sharedNetwork/src/linux/Sock.cpp +++ b/engine/shared/library/sharedNetwork/src/linux/Sock.cpp @@ -1,6 +1,12 @@ //--------------------------------------------------------------------- #pragma warning(disable : 4127) +#ifdef NDEBUG +#define SWG_ASSERT(exp) ((void) (exp)) +#else +#define SWG_ASSERT assert +#endif + #include "FirstSharedNetwork.h" #include #include "Sock.h" @@ -28,9 +34,8 @@ Sock::~Sock() { // ensure we don't block, and that pending // data is sent with a graceful shutdown - int err; - err = close(handle); - assert(err == 0); + int err = close(handle); + SWG_ASSERT(err == 0); handle = INVALID_SOCKET; } @@ -55,7 +60,7 @@ bool Sock::bind(const Address & newBindAddress) struct sockaddr_in a; int r; r = getsockname(handle, reinterpret_cast(&a), &namelen); - assert(r == 0); + SWG_ASSERT(r == 0); bindAddress = a; } else @@ -83,9 +88,8 @@ bool Sock::bind() if(err == 0) { result = true; - int r; - r = getsockname(handle, reinterpret_cast(&a), &namelen); - assert(r == 0); + int r = getsockname(handle, reinterpret_cast(&a), &namelen); + SWG_ASSERT(r == 0); bindAddress = a; } assert(err == 0); @@ -144,9 +148,8 @@ bool Sock::canSend() const const unsigned int Sock::getInputBytesPending() const { unsigned long int bytes = 0; - int err; - err = ioctl(handle, FIONREAD, &bytes); //lint !e1924 (I don't know WHAT Microsoft is doing here!) - assert(err == 0); + int err = ioctl(handle, FIONREAD, &bytes); //lint !e1924 (I don't know WHAT Microsoft is doing here!) + SWG_ASSERT(err == 0); return bytes; } @@ -199,9 +202,8 @@ const std::string Sock::getLastError() const void Sock::getPeerName(struct sockaddr_in & target, int s) { socklen_t namelen = sizeof(struct sockaddr_in); - int err; - err = getpeername(s, reinterpret_cast(&(target)), &namelen); - assert(err != -1); + int err = getpeername(s, reinterpret_cast(&(target)), &namelen); + SWG_ASSERT(err != -1); } //----------------------------------------------------------------------- @@ -227,9 +229,8 @@ void Sock::setNonBlocking() const { assert(handle != INVALID_SOCKET); unsigned long int nb = 1; - int err; - err = ioctl(handle, FIONBIO, &nb); //lint !e569 // loss of precision in the FIONBIO macro, beyond my control - assert(err == 0); + int err = ioctl(handle, FIONBIO, &nb); //lint !e569 // loss of precision in the FIONBIO macro, beyond my control + SWG_ASSERT(err == 0); } //--------------------------------------------------------------------- diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/chat/ChatOnRequestLog.h b/engine/shared/library/sharedNetworkMessages/src/shared/chat/ChatOnRequestLog.h index 776ac4859..01eceb9ba 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/chat/ChatOnRequestLog.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/chat/ChatOnRequestLog.h @@ -38,7 +38,7 @@ struct ChatLogEntry Unicode::String m_to; Unicode::String m_channel; Unicode::String m_message; - time_t m_time; + uint32_t m_time; }; namespace Archive diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/AuctionData.h b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/AuctionData.h index 58021cc60..ac21588cc 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/AuctionData.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/AuctionData.h @@ -56,7 +56,7 @@ namespace Auction uint16 highBidderNameKey; int32 maxProxyBid; int32 myBid; - long itemType; + int32_t itemType; int resourceContainerClassCrc; int32 flags; int32 entranceCharge; @@ -97,7 +97,7 @@ namespace Auction std::string highBidderName; int32 maxProxyBid; int32 myBid; - long itemType; + uint32_t itemType; int resourceContainerClassCrc; int32 flags; int32 entranceCharge; diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/BuffBuilderChangeMessage.cpp b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/BuffBuilderChangeMessage.cpp index bb737fde8..b253fe03c 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/BuffBuilderChangeMessage.cpp +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/BuffBuilderChangeMessage.cpp @@ -85,7 +85,7 @@ MessageQueue::Data* BuffBuilderChangeMessage::unpack(Archive::ReadIterator & sou NetworkId tempId; bool tempBool = false; int tempInt = 0; - time_t tempTime = 0; + uint32_t tempTime = 0; Archive::get(source, tempId); msg->setBufferId(tempId); diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/BuffBuilderChangeMessage.h b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/BuffBuilderChangeMessage.h index 824febe40..2a981cdfb 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/BuffBuilderChangeMessage.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/BuffBuilderChangeMessage.h @@ -33,7 +33,7 @@ class BuffBuilderChangeMessage : public MessageQueue::Data //accessors NetworkId const & getBufferId() const; NetworkId const & getRecipientId() const; - time_t getStartingTime() const; + uint32_t getStartingTime() const; int getBufferRequiredCredits() const; bool getAccepted() const; Origin getOrigin() const; @@ -56,7 +56,7 @@ class BuffBuilderChangeMessage : public MessageQueue::Data private: NetworkId m_bufferId; NetworkId m_recipientId; - time_t m_startingTime; + uint32_t m_startingTime; int m_bufferRequiredCredits; bool m_accepted; Origin m_origin; @@ -79,7 +79,7 @@ inline NetworkId const & BuffBuilderChangeMessage::getRecipientId() const //----------------------------------------------------------------------- -inline time_t BuffBuilderChangeMessage::getStartingTime() const +inline uint32_t BuffBuilderChangeMessage::getStartingTime() const { return m_startingTime; } diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/GalaxyLoopTimesResponse.h b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/GalaxyLoopTimesResponse.h index 56d447c54..b1c47ddf2 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/GalaxyLoopTimesResponse.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/GalaxyLoopTimesResponse.h @@ -25,8 +25,8 @@ class GalaxyLoopTimesResponse : public GameNetworkMessage GalaxyLoopTimesResponse & operator = (const GalaxyLoopTimesResponse & rhs); GalaxyLoopTimesResponse(const GalaxyLoopTimesResponse & source); - Archive::AutoVariable currentFrameMilliseconds; - Archive::AutoVariable lastFrameMilliseconds; + Archive::AutoVariable currentFrameMilliseconds; + Archive::AutoVariable lastFrameMilliseconds; }; //----------------------------------------------------------------------- diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ImageDesignChangeMessage.cpp b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ImageDesignChangeMessage.cpp index a4c05ea5e..11a53950d 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ImageDesignChangeMessage.cpp +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ImageDesignChangeMessage.cpp @@ -157,7 +157,7 @@ MessageQueue::Data* ImageDesignChangeMessage::unpack(Archive::ReadIterator & sou bool tempBool = false; std::string tempStr; int tempInt = 0; - time_t tempTime = 0; + uint32_t tempTime = 0; Archive::get(source, tempId); msg->setDesignerId(tempId); diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ImageDesignChangeMessage.h b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ImageDesignChangeMessage.h index 07c176e08..9bc3c3929 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ImageDesignChangeMessage.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ImageDesignChangeMessage.h @@ -47,7 +47,7 @@ class ImageDesignChangeMessage : public MessageQueue::Data std::string const & getNewHairAsset() const; std::string const & getHairCustomizationData() const; DesignType getDesignType() const; - time_t getStartingTime() const; + uint32_t getStartingTime() const; int getDesignerRequiredCredits() const; int getRecipientPaidCredits() const; bool getAccepted() const; @@ -95,7 +95,7 @@ class ImageDesignChangeMessage : public MessageQueue::Data std::string m_newHairAsset; std::string m_hairCustomizationData; DesignType m_designType; - time_t m_startingTime; + uint32_t m_startingTime; int m_designerRequiredCredits; int m_recipientPaidCredits; bool m_accepted; @@ -160,7 +160,7 @@ inline ImageDesignChangeMessage::DesignType ImageDesignChangeMessage::getDesignT //----------------------------------------------------------------------- -inline time_t ImageDesignChangeMessage::getStartingTime() const +inline uint32_t ImageDesignChangeMessage::getStartingTime() const { return m_startingTime; } diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/MessageQueueSlowDownEffect.cpp b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/MessageQueueSlowDownEffect.cpp index 8089e4b20..7557ca3d7 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/MessageQueueSlowDownEffect.cpp +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/MessageQueueSlowDownEffect.cpp @@ -68,7 +68,7 @@ MessageQueue::Data * MessageQueueSlowDownEffect::unpack(Archive::ReadIterator & float coneLength; float coneAngle; float slopeAngle; - unsigned long expireTime; + uint32_t expireTime; Archive::get(source, target); Archive::get(source, coneLength); diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/MessageQueueSlowDownEffect.h b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/MessageQueueSlowDownEffect.h index fc4e9a67b..3511063cf 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/MessageQueueSlowDownEffect.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/MessageQueueSlowDownEffect.h @@ -32,7 +32,7 @@ class MessageQueueSlowDownEffect: public MessageQueue::Data float getConeLength() const; float getConeAngle() const; float getSlopeAngle() const; - unsigned long getExpireTime() const; + uint32_t getExpireTime() const; private: MessageQueueSlowDownEffect(); @@ -42,7 +42,7 @@ class MessageQueueSlowDownEffect: public MessageQueue::Data float m_coneLength; float m_coneAngle; float m_slopeAngle; - unsigned long m_expireTime; + uint32_t m_expireTime; }; // ---------------------------------------------------------------------- @@ -67,7 +67,7 @@ inline float MessageQueueSlowDownEffect::getSlopeAngle() const return m_slopeAngle; } -inline unsigned long MessageQueueSlowDownEffect::getExpireTime() const +inline uint32_t MessageQueueSlowDownEffect::getExpireTime() const { return m_expireTime; } diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/SlowDownEffectMessage.h b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/SlowDownEffectMessage.h index effac2e71..035e081ec 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/SlowDownEffectMessage.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/SlowDownEffectMessage.h @@ -45,7 +45,7 @@ class SlowDownEffectMessage : public GameNetworkMessage Archive::AutoVariable m_coneLength; Archive::AutoVariable m_coneAngle; Archive::AutoVariable m_slopeAngle; - Archive::AutoVariable m_expireTime; + Archive::AutoVariable m_expireTime; }; //----------------------------------------------------------------------- diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/common/FrameEndMessage.h b/engine/shared/library/sharedNetworkMessages/src/shared/common/FrameEndMessage.h index d65192e61..7fb4a4bcb 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/common/FrameEndMessage.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/common/FrameEndMessage.h @@ -28,7 +28,7 @@ class FrameEndMessage: public GameNetworkMessage private: Archive::AutoVariable m_processId; - Archive::AutoVariable m_frameTime; + Archive::AutoVariable m_frameTime; Archive::AutoVariable m_profilerData; FrameEndMessage(); diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/common/GameNetworkMessage.cpp b/engine/shared/library/sharedNetworkMessages/src/shared/common/GameNetworkMessage.cpp index bd1a5db36..651c01ae9 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/common/GameNetworkMessage.cpp +++ b/engine/shared/library/sharedNetworkMessages/src/shared/common/GameNetworkMessage.cpp @@ -122,7 +122,7 @@ std::string const &GameNetworkMessage::getCmdName() const // ---------------------------------------------------------------------- -std::string const &GameNetworkMessage::getCmdName(unsigned long cmdCrc) // static +std::string const &GameNetworkMessage::getCmdName(uint32_t cmdCrc) // static { std::string &val = s_messageTypes[cmdCrc]; if (val.empty()) diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/common/GameNetworkMessage.h b/engine/shared/library/sharedNetworkMessages/src/shared/common/GameNetworkMessage.h index 3e8f93b40..2ee7de9b9 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/common/GameNetworkMessage.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/common/GameNetworkMessage.h @@ -39,11 +39,11 @@ class GameNetworkMessage: public Archive::AutoByteStream, public MessageDispatch std::string const &getCmdName() const; static std::vector > const getMessageCount(); - static std::string const &getCmdName(unsigned long cmdCrc); + static std::string const &getCmdName(uint32_t cmdCrc); private: GameNetworkMessage(); - Archive::AutoVariable cmd; + Archive::AutoVariable cmd; }; // ====================================================================== diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/planetWatch/ServerInfo.h b/engine/shared/library/sharedNetworkMessages/src/shared/planetWatch/ServerInfo.h index ca3b6b1ed..1640c0bf5 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/planetWatch/ServerInfo.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/planetWatch/ServerInfo.h @@ -10,8 +10,8 @@ struct ServerInfo { std::string ipAddress; - unsigned long serverId; - unsigned long systemPid; + uint32_t serverId; + uint32_t systemPid; std::string sceneId; }; diff --git a/engine/shared/library/sharedObject/src/shared/object/AlterScheduler.cpp b/engine/shared/library/sharedObject/src/shared/object/AlterScheduler.cpp index dc2a932c4..5bd64e9bc 100755 --- a/engine/shared/library/sharedObject/src/shared/object/AlterScheduler.cpp +++ b/engine/shared/library/sharedObject/src/shared/object/AlterScheduler.cpp @@ -111,10 +111,10 @@ namespace AlterSchedulerNamespace // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float const cs_schedulerTicksPerSecond = 1000.0f; // # schedule ticks per second. Frame rates will not be able to exceed this. + float const cs_schedulerTicksPerSecond = 2000.0f; // # schedule ticks per second. Frame rates will not be able to exceed this. float const cs_secondsPerSchedulerTick = 1.0f / cs_schedulerTicksPerSecond; - uint32 const cs_freeFillPattern = 0xEFEFEFEF; // this should match MemoryManager's free fill pattern. + uint64_t const cs_freeFillPattern = 0xEFEFEFEFEFEFEFEF; // this should match MemoryManager's free fill pattern. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -291,7 +291,7 @@ void AlterSchedulerNamespace::validateObject(Object const *object) #ifdef _DEBUG //-- Check if object memory is deleted. - if (*reinterpret_cast(object) == cs_freeFillPattern) //lint !e740 // unusual pointer cast // Yes. + if (*reinterpret_cast(object) == cs_freeFillPattern) //lint !e740 // unusual pointer cast // Yes. { DEBUG_WARNING(true, ("validateObject(): alter scheduler found deleted object (object memory starts with 4 bytes of free-fill pattern).")); //lint !e740 // unusual pointer cast from incompatible indirect types // okay, I'm doing something unusual. isInvalid = true; @@ -313,7 +313,7 @@ void AlterSchedulerNamespace::validateObject(Object const *object) } catch (...) { //lint !e1775 // catch block does not declare any exception // that's right: I want to catch it all. - WARNING(true, ("validateObject(): Object-derived class with address [%x] failed to return valid C++ type info; likely a deleted Object.", reinterpret_cast(object))); + WARNING(true, ("validateObject(): Object-derived class with address [%x] failed to return valid C++ type info; likely a deleted Object.", reinterpret_cast(object))); isInvalid = true; } } diff --git a/engine/shared/library/sharedObject/src/shared/object/Object.cpp b/engine/shared/library/sharedObject/src/shared/object/Object.cpp index e59224302..04713352f 100755 --- a/engine/shared/library/sharedObject/src/shared/object/Object.cpp +++ b/engine/shared/library/sharedObject/src/shared/object/Object.cpp @@ -149,7 +149,9 @@ Object::NotificationList::NotificationList(const NotificationList &otherList, co m_notificationList.push_back(add); } - DEBUG_FATAL(!deletedOtherEntry, ("didn't find notification [0x%08x] in source list for deletion", &otherEntry)); + if(!deletedOtherEntry) { + DEBUG_FATAL(true, ("didn't find notification [0x%08x] in source list for deletion", &otherEntry)); + } DEBUG_FATAL(m_notificationList.size() != otherList.m_notificationList.size() - 1, ("failed to build new notification list correctly")); } diff --git a/engine/shared/library/sharedObject/src/shared/object/ObjectTemplateList.cpp b/engine/shared/library/sharedObject/src/shared/object/ObjectTemplateList.cpp index 823629063..2b6484a8b 100755 --- a/engine/shared/library/sharedObject/src/shared/object/ObjectTemplateList.cpp +++ b/engine/shared/library/sharedObject/src/shared/object/ObjectTemplateList.cpp @@ -16,6 +16,7 @@ #include "sharedObject/Object.h" #include "sharedFoundation/ConstCharCrcString.h" #include "sharedFoundation/CrcStringTable.h" +#include "sharedFoundation/Crc.h" #include "sharedFoundation/DataResourceList.h" #include @@ -174,7 +175,7 @@ void ObjectTemplateList::loadCrcStringTable(const char *fileName) ConstCharCrcString const ObjectTemplateList::lookUp(const char * string) { ConstCharCrcString result = ms_crcStringTable.lookUp(string); - WARNING(result.isEmpty(), ("ObjectTemplateList::lookUp objectTemplate %s not found in table", string)); + WARNING(result.isEmpty(), ("ObjectTemplateList::lookUp objectTemplate %s (CRC 0x%08x) not found in table", string, Crc::calculate(string))); return result; } diff --git a/engine/shared/library/sharedPathfinding/src/shared/PathNode.h b/engine/shared/library/sharedPathfinding/src/shared/PathNode.h index fd62f52c3..aeaeaaf75 100755 --- a/engine/shared/library/sharedPathfinding/src/shared/PathNode.h +++ b/engine/shared/library/sharedPathfinding/src/shared/PathNode.h @@ -67,8 +67,8 @@ class PathNode int getUserId ( void ) const; void setUserId ( int newId ) const; - int getMark ( int whichMark ) const; - void setMark ( int whichMark, int newValue ) const; + int64_t getMark ( int whichMark ) const; + void setMark ( int whichMark, int64_t newValue ) const; void clearMarks ( void ) const; // ---------- @@ -95,8 +95,8 @@ class PathNode // These are used to speed up some algorithms. They're not persisted. // Code that uses the marks MUST clear them after use. - mutable int m_userId; - mutable int m_marks[4]; + mutable int m_userId; + mutable int64_t m_marks[4]; }; // ---------------------------------------------------------------------- @@ -214,12 +214,12 @@ inline void PathNode::setUserId ( int newId ) const // ---------- -inline int PathNode::getMark ( int whichMark ) const +inline int64_t PathNode::getMark ( int whichMark ) const { return m_marks[whichMark]; } -inline void PathNode::setMark ( int whichMark, int newMark ) const +inline void PathNode::setMark ( int whichMark, int64_t newMark ) const { m_marks[whichMark] = newMark; } diff --git a/engine/shared/library/sharedPathfinding/src/shared/PathSearch.cpp b/engine/shared/library/sharedPathfinding/src/shared/PathSearch.cpp index e09a5cab6..3713625ce 100755 --- a/engine/shared/library/sharedPathfinding/src/shared/PathSearch.cpp +++ b/engine/shared/library/sharedPathfinding/src/shared/PathSearch.cpp @@ -182,7 +182,7 @@ PathSearchNode * PathSearchNode::createSearchNode( PathNode const * node ) PathSearchNode * oldNode = nullptr; - int mark = node->getMark(3); + int64_t mark = node->getMark(3); if(mark != -1) { @@ -193,7 +193,7 @@ PathSearchNode * PathSearchNode::createSearchNode( PathNode const * node ) PathSearchNode * searchNode = new PathSearchNode(m_search,m_graph,node); - node->setMark( 3, (int)((void*)searchNode) ); + node->setMark( 3, (int64_t)((void*)searchNode) ); m_search->m_visitedNodes->push_back(node); @@ -208,7 +208,7 @@ PathSearchNode * PathSearchNode::getSearchNode( PathNode const * node ) PathSearchNode * searchNode = nullptr; - int mark = node->getMark(3); + int64_t mark = node->getMark(3); if(mark != -1) { @@ -493,7 +493,7 @@ void PathSearch::cleanup ( void ) { PathNode const * visitedNode = m_visitedNodes->at(i); - int mark = visitedNode->getMark(3); + int64_t mark = visitedNode->getMark(3); if(mark != -1) { diff --git a/engine/shared/library/sharedRandom/src/shared/FastRandomGenerator.h b/engine/shared/library/sharedRandom/src/shared/FastRandomGenerator.h index 7896ca5ae..131694e44 100755 --- a/engine/shared/library/sharedRandom/src/shared/FastRandomGenerator.h +++ b/engine/shared/library/sharedRandom/src/shared/FastRandomGenerator.h @@ -16,18 +16,18 @@ class FastRandomGenerator { public: FastRandomGenerator() { m_I=ZERO_ALT; } - FastRandomGenerator(long s) { setSeed(s); } + FastRandomGenerator(uint32 s) { setSeed(s); } - void setSeed(long s) + void setSeed(uint32 s) { - const long ps = s&0x7fffffff; + const uint32 ps = s&0x7fffffff; m_I = (ps==0) ? ZERO_ALT : ps; } // return a random number r where 0<=r<1 float randomFloat() { - long f = (_rand()>>8)|IEEE_FLOAT_BITS; + float f = static_cast((_rand()>>8)|IEEE_FLOAT_BITS); return (*(float *)(void *)&f)-1.0f; } float randomFloat(float range) { return randomFloat()*range; } @@ -49,9 +49,9 @@ class FastRandomGenerator ZERO_ALT = 123459876 }; - long _rand() + uint32 _rand() { - long k; + uint32 k; k=m_I/IQ; m_I=IA*(m_I-k*IQ)-IR*k; if (m_I<0) m_I += IM; @@ -59,9 +59,9 @@ class FastRandomGenerator return k; } - long _randMax() { return IM-1; } + uint32 _randMax() { return IM-1; } - long m_I; + uint32 m_I; }; // ====================================================================== diff --git a/engine/shared/library/sharedTerrain/src/shared/generator/CoordinateHash.cpp b/engine/shared/library/sharedTerrain/src/shared/generator/CoordinateHash.cpp index e6d8c6f50..d1c9393b7 100755 --- a/engine/shared/library/sharedTerrain/src/shared/generator/CoordinateHash.cpp +++ b/engine/shared/library/sharedTerrain/src/shared/generator/CoordinateHash.cpp @@ -183,28 +183,28 @@ namespace //=================================================================== -unsigned long CoordinateHash::hashTuple(float x, float z) +uint32 CoordinateHash::hashTuple(float x, float z) { - const uint32 ix = (*(uint32 *)&x); - const uint32 iz = (*(uint32 *)&z)^0xa5a5a5a5; + const uint32 ix = (*reinterpret_cast(&x)); + const uint32 iz = (*reinterpret_cast(&z)) ^ 0xa5a5a5a5; - const uint32 hx = inthash(ix); - const uint32 hz = inthash(iz); + const uint32 hx = inthash(ix); + const uint32 hz = inthash(iz); - const uint32 h = inthash(hx^hz); + const uint32 h = inthash(hx ^ hz); - return h; + return h; } -float CoordinateHash::makeFloat(unsigned long hash) +float CoordinateHash::makeFloat(uint32 hash) { enum { IEEE_FLOAT_BITS=0x3f800000 }; const uint32 mask = ~uint32(0xff800000); const uint32 maskedHash = (hash + (hash>>9))&mask; - const uint32 iFloat = IEEE_FLOAT_BITS | maskedHash; - const float returnValue = (*(float *)&iFloat) - 1.0f; + uint32 iFloat = static_cast(IEEE_FLOAT_BITS) | maskedHash; + const float returnValue = (*reinterpret_cast(&iFloat)) - 1.0F; return returnValue; } diff --git a/engine/shared/library/sharedTerrain/src/shared/generator/CoordinateHash.h b/engine/shared/library/sharedTerrain/src/shared/generator/CoordinateHash.h index f01d06455..7e70609d9 100755 --- a/engine/shared/library/sharedTerrain/src/shared/generator/CoordinateHash.h +++ b/engine/shared/library/sharedTerrain/src/shared/generator/CoordinateHash.h @@ -19,8 +19,8 @@ class CoordinateHash { public: - static unsigned long hashTuple(float x, float z); - static float makeFloat(unsigned long hash); + static uint32 hashTuple(float x, float z); + static float makeFloat(uint32 hash); }; //=================================================================== diff --git a/engine/shared/library/sharedUtility/src/shared/DataTable.cpp b/engine/shared/library/sharedUtility/src/shared/DataTable.cpp index 2a0974c73..2f2e65cd2 100755 --- a/engine/shared/library/sharedUtility/src/shared/DataTable.cpp +++ b/engine/shared/library/sharedUtility/src/shared/DataTable.cpp @@ -185,7 +185,7 @@ int DataTable::getIntValue(const std::string & column, int row) const //---------------------------------------------------------------------------- -int DataTable::getIntValue(int column, int row) const +int32 DataTable::getIntValue(int column, int row) const { DEBUG_FATAL(row < 0 || row >= getNumRows(), ("DataTable [%s] getIntValue(): Invalid row number [%d]. Rows=[%d]\n", m_name.c_str(), row, getNumRows())); DEBUG_FATAL(column < 0 || column >= getNumColumns(), ("DataTable [%s] getIntValue(): Invalid col number [%d]. Cols=[%d]\n", m_name.c_str(), column, getNumColumns())); @@ -210,7 +210,7 @@ int DataTable::getIntValue(int column, int row) const //---------------------------------------------------------------------------- -int DataTable::getIntDefaultForColumn(const std::string & column) const +int32 DataTable::getIntDefaultForColumn(const std::string & column) const { int const columnIndex = findColumnNumber(column); DEBUG_FATAL(columnIndex < 0 || columnIndex >= getNumColumns(), ("DataTable [%s] getIntDefaultForColumn(): Invalid col number [%d]. Cols=[%d]\n", m_name.c_str(), columnIndex, getNumColumns())); @@ -219,7 +219,7 @@ int DataTable::getIntDefaultForColumn(const std::string & column) const //---------------------------------------------------------------------------- -int DataTable::getIntDefaultForColumn(int column) const +int32 DataTable::getIntDefaultForColumn(int column) const { DEBUG_FATAL(column < 0 || column >= getNumColumns(), ("DataTable [%s] getIntDefaultForColumn(): Invalid col number [%d]. Cols=[%d]\n", m_name.c_str(), column, getNumColumns())); DEBUG_FATAL(m_types[static_cast(column)]->getBasicType() != DataTableColumnType::DT_Int, ("Wrong data type for column %d.", column)); @@ -405,7 +405,7 @@ void DataTable::_readCell(Iff & iff, int column, int row) { case DataTableColumnType::DT_Int: { - int tmp = iff.read_int32(); + int32 tmp = iff.read_int32(); new (cell) DataTableCell(tmp); break; @@ -626,7 +626,7 @@ int DataTable::searchColumnString( int column, const std::string & searchValue ) int valueCrc = getIntValue(column,i); IGNORE_RETURN ( indexPair->second.insert(std::pair(valueCrc, i)) ); if (retval == -1 && valueString == searchValue) - retval = i; + retval = i; // don't return here because we're adding indexes for everything in this table as we've not indexed it before. } } else @@ -634,7 +634,7 @@ int DataTable::searchColumnString( int column, const std::string & searchValue ) std::pair, std::multimap > * indexPair = static_cast, std::multimap > *>(voidIndex); std::multimap::iterator iter = indexPair->first.find(searchValue); if (iter != indexPair->first.end()) - retval = iter->second; + return iter->second; // if we find our value, return here instead of iterating through the rest of the table. } return retval; @@ -677,7 +677,7 @@ int DataTable::searchColumnFloat( int column, float searchValue ) const // ---------- -int DataTable::searchColumnInt( int column, int searchValue ) const +int DataTable::searchColumnInt( int column, int32 searchValue ) const { DEBUG_FATAL(column < 0 || column >= getNumColumns(), ("DataTable [%s] searchColumnInt(): Invalid col number [%d]. Cols=[%d]\n", m_name.c_str(), column, getNumColumns())); diff --git a/engine/shared/library/sharedUtility/src/shared/DataTable.h b/engine/shared/library/sharedUtility/src/shared/DataTable.h index ef9c3fe3b..13b3988d1 100755 --- a/engine/shared/library/sharedUtility/src/shared/DataTable.h +++ b/engine/shared/library/sharedUtility/src/shared/DataTable.h @@ -31,10 +31,10 @@ class DataTable DataTableColumnType const &getDataTypeForColumn(const std::string& column) const; DataTableColumnType const &getDataTypeForColumn(int column) const; - int getIntValue(const std::string & column, int row) const; - int getIntValue(int column, int row) const; - int getIntDefaultForColumn(const std::string & column) const; - int getIntDefaultForColumn(int column) const; + int32 getIntValue(const std::string & column, int row) const; + int32 getIntValue(int column, int row) const; + int32 getIntDefaultForColumn(const std::string & column) const; + int32 getIntDefaultForColumn(int column) const; float getFloatValue(const std::string & column, int row) const; float getFloatValue(int column, int row) const; float getFloatDefaultForColumn(const std::string & column) const; @@ -63,7 +63,7 @@ class DataTable int searchColumnString(int column, const std::string & searchValue) const; int searchColumnFloat(int column, float searchValue) const; - int searchColumnInt(int column, int searchValue) const; + int searchColumnInt(int column, int32 searchValue) const; std::string const & getName() const; diff --git a/engine/shared/library/sharedUtility/src/shared/DataTableCell.cpp b/engine/shared/library/sharedUtility/src/shared/DataTableCell.cpp index 625730695..c0b9f8fa1 100755 --- a/engine/shared/library/sharedUtility/src/shared/DataTableCell.cpp +++ b/engine/shared/library/sharedUtility/src/shared/DataTableCell.cpp @@ -55,7 +55,7 @@ void DataTableCell::operator delete(void *pointer) // ---------------------------------------------------------------------- -DataTableCell::DataTableCell(int value) +DataTableCell::DataTableCell(int32 value) : m_type(CT_int) { m_value.m_i=value; diff --git a/engine/shared/library/sharedUtility/src/shared/DataTableCell.h b/engine/shared/library/sharedUtility/src/shared/DataTableCell.h index 5021b5f86..1cd4b616f 100755 --- a/engine/shared/library/sharedUtility/src/shared/DataTableCell.h +++ b/engine/shared/library/sharedUtility/src/shared/DataTableCell.h @@ -31,16 +31,16 @@ class DataTableCell ,CT_float }; - explicit DataTableCell(int value); + explicit DataTableCell(int32 value); explicit DataTableCell(float value); explicit DataTableCell(const char *value); ~DataTableCell(); - CellType getType() const { return m_type; } - int getIntValue() const { return m_value.m_i; } - float getFloatValue() const { return m_value.m_f; } - const char *getStringValue() const; - int getStringValueCrc() const { return m_value.m_s.m_crc; } + CellType getType() const { return m_type; } + int32 getIntValue() const { return m_value.m_i; } + float getFloatValue() const { return m_value.m_f; } + const char *getStringValue() const; + int32 getStringValueCrc() const { return m_value.m_s.m_crc; } private: const CellType m_type; @@ -48,12 +48,12 @@ class DataTableCell { union { - int m_i; + int32 m_i; float m_f; struct { const char *m_sz; - int m_crc; + int32 m_crc; } m_s; }; } m_value; diff --git a/engine/shared/library/sharedUtility/src/shared/DataTableWriter.cpp b/engine/shared/library/sharedUtility/src/shared/DataTableWriter.cpp index 795c86964..5d3d6e6d6 100755 --- a/engine/shared/library/sharedUtility/src/shared/DataTableWriter.cpp +++ b/engine/shared/library/sharedUtility/src/shared/DataTableWriter.cpp @@ -728,7 +728,7 @@ DataTableCell *DataTableWriter::_getNewCell(DataTableColumnType const &columnTyp switch (columnType.getBasicType()) { case DataTableColumnType::DT_Int: - return new DataTableCell(static_cast(strtol(value.c_str(), nullptr, 0))); + return new DataTableCell(static_cast(strtol(value.c_str(), nullptr, 0))); break; case DataTableColumnType::DT_Float: return new DataTableCell(static_cast(atof(value.c_str()))); @@ -859,7 +859,7 @@ void DataTableWriter::_saveRows(NamedDataTable * ndt, Iff& iff) const iff.insertChunk(TAG(R,O,W,S)); int numRows = static_cast(ndt->m_rows.size()); - iff.insertChunkData(&numRows, sizeof(int)); + iff.insertChunkData(&numRows, sizeof(int32)); std::vector::iterator i = ndt->m_rows.begin(); for (; i!= ndt->m_rows.end(); ++i) { @@ -873,8 +873,8 @@ void DataTableWriter::_saveRows(NamedDataTable * ndt, Iff& iff) const { const DataTableCell * cell = *j; NOT_NULL(cell); - int tmp = cell->getIntValue(); - iff.insertChunkData(&tmp, sizeof(int)); + int32 tmp = cell->getIntValue(); + iff.insertChunkData(&tmp, sizeof(int32)); break; } case DataTableColumnType::DT_Float: diff --git a/external/3rd/library/platform/utils/Base/Archive.cpp b/external/3rd/library/platform/utils/Base/Archive.cpp index fa1ec78ea..ec1a8c8b9 100755 --- a/external/3rd/library/platform/utils/Base/Archive.cpp +++ b/external/3rd/library/platform/utils/Base/Archive.cpp @@ -81,7 +81,7 @@ namespace Base { } - ByteStream::ReadIterator::~ReadIterator() + Base::ReadIterator::~ReadIterator() { stream = 0; } @@ -152,7 +152,7 @@ namespace Base return *this; } - void ByteStream::get(void * target, ReadIterator & readIterator, const unsigned long int targetSize) const + void ByteStream::get(void * target, ReadIterator & readIterator, const uint32_t targetSize) const { assert(readIterator.getReadPosition() + targetSize <= allocatedSize); memcpy(target, &data->buffer[readIterator.getReadPosition()], targetSize); diff --git a/external/3rd/library/platform/utils/Base/Archive.h b/external/3rd/library/platform/utils/Base/Archive.h index c461f4d74..1020a05dc 100755 --- a/external/3rd/library/platform/utils/Base/Archive.h +++ b/external/3rd/library/platform/utils/Base/Archive.h @@ -63,7 +63,7 @@ const unsigned MAX_ARRAY_SIZE = 1024; ReadIterator & operator = (const ReadIterator & source); void advance (const unsigned int distance); - void get (void * target, const unsigned long int readSize); + void get (void * target, const uint32_t readSize); const unsigned int getSize () const; const unsigned char * const getBuffer () const; const unsigned int getReadPosition () const; @@ -92,7 +92,7 @@ const unsigned MAX_ARRAY_SIZE = 1024; void ref (); protected: unsigned char * buffer; - unsigned long size; + uint32_t size; private: struct DataFreeList { @@ -132,7 +132,7 @@ const unsigned MAX_ARRAY_SIZE = 1024; void put(const void * const source, const unsigned int sourceSize); private: - void get(void * target, ReadIterator & readIterator, const unsigned long int readSize) const; + void get(void * target, ReadIterator & readIterator, const uint32_t readSize) const; void growToAtLeast(const unsigned int targetSize); void reAllocate(const unsigned int newSize); @@ -255,7 +255,7 @@ const unsigned MAX_ARRAY_SIZE = 1024; return *this; } - inline void ByteStream::ReadIterator::get(void * target, const unsigned long int readSize) + inline void ByteStream::ReadIterator::get(void * target, const uint32_t readSize) { assert(stream); stream->get(target, *this, readSize); @@ -656,8 +656,9 @@ const unsigned MAX_ARRAY_SIZE = 1024; Base::get(source, arraySize); ValueType v; - if (arraySize > MAX_ARRAY_SIZE) + if (arraySize > MAX_ARRAY_SIZE) { arraySize = 0; + } using Base::get; for(unsigned int i = 0; i < arraySize; ++i) diff --git a/external/3rd/library/platform/utils/Base/BlockAllocator.h b/external/3rd/library/platform/utils/Base/BlockAllocator.h index bbfbf2738..f9f9f8632 100755 --- a/external/3rd/library/platform/utils/Base/BlockAllocator.h +++ b/external/3rd/library/platform/utils/Base/BlockAllocator.h @@ -17,7 +17,7 @@ namespace Base BlockAllocator(); ~BlockAllocator(); void *getBlock(unsigned accum); - void returnBlock(unsigned *handle); + void returnBlock(uintptr_t *handle); private: uintptr_t *m_blocks[31]; diff --git a/external/3rd/library/platform/utils/Base/linux/BlockAllocator.cpp b/external/3rd/library/platform/utils/Base/linux/BlockAllocator.cpp index 29d910749..f4042d1f6 100755 --- a/external/3rd/library/platform/utils/Base/linux/BlockAllocator.cpp +++ b/external/3rd/library/platform/utils/Base/linux/BlockAllocator.cpp @@ -23,8 +23,8 @@ namespace Base { while(m_blocks[i] != nullptr) { - unsigned *tmp = m_blocks[i]; - m_blocks[i] = (unsigned *)*m_blocks[i]; + uintptr_t *tmp = m_blocks[i]; + m_blocks[i] = (uintptr_t *)*m_blocks[i]; free(tmp); } } @@ -36,7 +36,7 @@ namespace Base void *BlockAllocator::getBlock(unsigned bytes) { unsigned accum = 16, bits = 16; - unsigned *handle = nullptr; + uintptr_t *handle = nullptr; // Perform a binary search looking for the highest bit. @@ -79,7 +79,7 @@ namespace Base if(m_blocks[accum] == 0) { // remove the pre allocated block from the linked list - handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned)); + handle = (uintptr_t *)calloc(((1 << accum) / 4) + 2, sizeof(uintptr_t)); handle[1] = accum; handle[0] = 0; } @@ -87,20 +87,20 @@ namespace Base { // Allocate a new block handle = m_blocks[accum]; - m_blocks[accum] = (unsigned *)handle[0]; + m_blocks[accum] = (uintptr_t *)handle[0]; handle[0] = 0; } // return a pointer that skips over the header used for the allocator's purposes return(handle + 2); } - void BlockAllocator::returnBlock(unsigned *handle) + void BlockAllocator::returnBlock(uintptr_t *handle) { // C++ allows for safe deletion of a nullptr pointer if(handle) { // Update the allocator linked list, insert this entry at the head - *(handle - 2) = (unsigned)m_blocks[*(handle - 1)]; + *(handle - 2) = (uintptr_t)m_blocks[*(handle - 1)]; // Add this entry to the proper linked list node m_blocks[*(handle - 1)] = (handle - 2); } diff --git a/external/3rd/library/platform/utils/Base/linux/Types.h b/external/3rd/library/platform/utils/Base/linux/Types.h index 6ee504505..574ee5caa 100755 --- a/external/3rd/library/platform/utils/Base/linux/Types.h +++ b/external/3rd/library/platform/utils/Base/linux/Types.h @@ -11,7 +11,8 @@ #ifndef BASE_LINUX_TYPES_H #define BASE_LINUX_TYPES_H -#include +//#include +#include #ifdef EXTERNAL_DISTRO namespace NAMESPACE @@ -27,13 +28,13 @@ namespace Base typedef signed char int8; typedef unsigned char uint8; -typedef signed short int16; -typedef unsigned short uint16; +typedef int16_t int16; +typedef uint16_t uint16; typedef int32_t int32; -typedef u_int32_t uint32; +typedef uint32_t uint32; typedef int64_t int64; -typedef u_int64_t uint64; +typedef uint64_t uint64; } #ifdef EXTERNAL_DISTRO }; diff --git a/external/3rd/library/platform/utils/Base/win32/Types.h b/external/3rd/library/platform/utils/Base/win32/Types.h index 0c64cb2cb..10905cc1a 100755 --- a/external/3rd/library/platform/utils/Base/win32/Types.h +++ b/external/3rd/library/platform/utils/Base/win32/Types.h @@ -25,13 +25,13 @@ namespace Base typedef signed char int8; typedef unsigned char uint8; -typedef short int16; -typedef unsigned short uint16; +typedef int16_t int16; +typedef uint16_t uint16; -typedef int int32; -typedef unsigned uint32; -typedef __int64 int64; -typedef unsigned __int64 uint64; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; }; #ifdef EXTERNAL_DISTRO diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/Archive.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/Archive.h index 212872204..8141f1d66 100755 --- a/external/3rd/library/soePlatform/CSAssist/utils/Base/Archive.h +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/Archive.h @@ -667,8 +667,9 @@ const unsigned MAX_ARRAY_SIZE = 1024; Base::get(source, arraySize); ValueType v; - if (arraySize > MAX_ARRAY_SIZE) + if (arraySize > MAX_ARRAY_SIZE) { arraySize = 0; + } for(unsigned int i = 0; i < arraySize; ++i) { diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/BlockAllocator.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/BlockAllocator.h index bbfbf2738..f9f9f8632 100755 --- a/external/3rd/library/soePlatform/CSAssist/utils/Base/BlockAllocator.h +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/BlockAllocator.h @@ -17,7 +17,7 @@ namespace Base BlockAllocator(); ~BlockAllocator(); void *getBlock(unsigned accum); - void returnBlock(unsigned *handle); + void returnBlock(uintptr_t *handle); private: uintptr_t *m_blocks[31]; diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/linux/BlockAllocator.cpp b/external/3rd/library/soePlatform/CSAssist/utils/Base/linux/BlockAllocator.cpp index 29d910749..f4042d1f6 100755 --- a/external/3rd/library/soePlatform/CSAssist/utils/Base/linux/BlockAllocator.cpp +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/linux/BlockAllocator.cpp @@ -23,8 +23,8 @@ namespace Base { while(m_blocks[i] != nullptr) { - unsigned *tmp = m_blocks[i]; - m_blocks[i] = (unsigned *)*m_blocks[i]; + uintptr_t *tmp = m_blocks[i]; + m_blocks[i] = (uintptr_t *)*m_blocks[i]; free(tmp); } } @@ -36,7 +36,7 @@ namespace Base void *BlockAllocator::getBlock(unsigned bytes) { unsigned accum = 16, bits = 16; - unsigned *handle = nullptr; + uintptr_t *handle = nullptr; // Perform a binary search looking for the highest bit. @@ -79,7 +79,7 @@ namespace Base if(m_blocks[accum] == 0) { // remove the pre allocated block from the linked list - handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned)); + handle = (uintptr_t *)calloc(((1 << accum) / 4) + 2, sizeof(uintptr_t)); handle[1] = accum; handle[0] = 0; } @@ -87,20 +87,20 @@ namespace Base { // Allocate a new block handle = m_blocks[accum]; - m_blocks[accum] = (unsigned *)handle[0]; + m_blocks[accum] = (uintptr_t *)handle[0]; handle[0] = 0; } // return a pointer that skips over the header used for the allocator's purposes return(handle + 2); } - void BlockAllocator::returnBlock(unsigned *handle) + void BlockAllocator::returnBlock(uintptr_t *handle) { // C++ allows for safe deletion of a nullptr pointer if(handle) { // Update the allocator linked list, insert this entry at the head - *(handle - 2) = (unsigned)m_blocks[*(handle - 1)]; + *(handle - 2) = (uintptr_t)m_blocks[*(handle - 1)]; // Add this entry to the proper linked list node m_blocks[*(handle - 1)] = (handle - 2); } diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/linux/Types.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/linux/Types.h index 69419a0fc..ea2b96257 100755 --- a/external/3rd/library/soePlatform/CSAssist/utils/Base/linux/Types.h +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/linux/Types.h @@ -11,7 +11,8 @@ #ifndef BASE_LINUX_TYPES_H #define BASE_LINUX_TYPES_H -#include +//#include +#include #ifdef EXTERNAL_DISTRO namespace NAMESPACE @@ -30,13 +31,13 @@ namespace Base typedef signed char int8; typedef unsigned char uint8; -typedef signed short int16; -typedef unsigned short uint16; +typedef int16_t int16; +typedef uint16_t uint16; typedef int32_t int32; -typedef u_int32_t uint32; +typedef uint32_t uint32; typedef int64_t int64; -typedef u_int64_t uint64; +typedef uint64_t uint64; } #ifdef EXTERNAL_DISTRO }; diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Types.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Types.h index 0c64cb2cb..10905cc1a 100755 --- a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Types.h +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Types.h @@ -25,13 +25,13 @@ namespace Base typedef signed char int8; typedef unsigned char uint8; -typedef short int16; -typedef unsigned short uint16; +typedef int16_t int16; +typedef uint16_t uint16; -typedef int int32; -typedef unsigned uint32; -typedef __int64 int64; -typedef unsigned __int64 uint64; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; }; #ifdef EXTERNAL_DISTRO diff --git a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/Archive.h b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/Archive.h index 856dcd95e..1cfc696f7 100755 --- a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/Archive.h +++ b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/Archive.h @@ -653,8 +653,9 @@ const unsigned MAX_ARRAY_SIZE = 1024; Base::get(source, arraySize); ValueType v; - if (arraySize > MAX_ARRAY_SIZE) + if (arraySize > MAX_ARRAY_SIZE) { arraySize = 0; + } for(unsigned int i = 0; i < arraySize; ++i) { diff --git a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/linux/Types.h b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/linux/Types.h index 69419a0fc..ea2b96257 100755 --- a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/linux/Types.h +++ b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/linux/Types.h @@ -11,7 +11,8 @@ #ifndef BASE_LINUX_TYPES_H #define BASE_LINUX_TYPES_H -#include +//#include +#include #ifdef EXTERNAL_DISTRO namespace NAMESPACE @@ -30,13 +31,13 @@ namespace Base typedef signed char int8; typedef unsigned char uint8; -typedef signed short int16; -typedef unsigned short uint16; +typedef int16_t int16; +typedef uint16_t uint16; typedef int32_t int32; -typedef u_int32_t uint32; +typedef uint32_t uint32; typedef int64_t int64; -typedef u_int64_t uint64; +typedef uint64_t uint64; } #ifdef EXTERNAL_DISTRO }; diff --git a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Types.h b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Types.h index 0c64cb2cb..10905cc1a 100755 --- a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Types.h +++ b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Types.h @@ -25,13 +25,13 @@ namespace Base typedef signed char int8; typedef unsigned char uint8; -typedef short int16; -typedef unsigned short uint16; +typedef int16_t int16; +typedef uint16_t uint16; -typedef int int32; -typedef unsigned uint32; -typedef __int64 int64; -typedef unsigned __int64 uint64; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; }; #ifdef EXTERNAL_DISTRO diff --git a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatar.cpp b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatar.cpp index 8ec60bc8b..ab25b4b81 100755 --- a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatar.cpp +++ b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatar.cpp @@ -148,7 +148,7 @@ const ChatUnicodeString& ChatAvatar::getStatusMessage() const return m_cStatusMessage; } -void ChatAvatar::setAttributes(unsigned long attributes) +void ChatAvatar::setAttributes(uint32_t attributes) { m_core->setAttributes(attributes); } @@ -158,7 +158,7 @@ void ChatAvatar::setLoginPriority(int loginPriority) m_core->setLoginPriority(loginPriority); } -void ChatAvatar::setInboxLimit(unsigned inboxLimit) +void ChatAvatar::setInboxLimit(uint32_t inboxLimit) { m_core->setInboxLimit(inboxLimit); } diff --git a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatar.h b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatar.h index 998738da5..43fbd1e3e 100755 --- a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatar.h +++ b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatar.h @@ -61,9 +61,9 @@ namespace ChatSystem const ChatUnicodeString &getForwardingEmail() const; const ChatUnicodeString& getStatusMessage() const; - void setAttributes(unsigned long attributes); + void setAttributes(uint32_t attributes); void setLoginPriority(int loginPriority); - void setInboxLimit(unsigned inboxLimit); + void setInboxLimit(uint32_t inboxLimit); void setForwardingEmail(const ChatUnicodeString &forwardingEmail); void setStatusMessage(const ChatUnicodeString& statusMessage); diff --git a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatarCore.cpp b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatarCore.cpp index 871f63d7a..838aaa752 100755 --- a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatarCore.cpp +++ b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatarCore.cpp @@ -17,7 +17,7 @@ namespace ChatSystem { } - ChatAvatarCore::ChatAvatarCore(unsigned avatarID, unsigned userID, const unsigned short *name, const unsigned short *address, const unsigned short *gateway, const unsigned short *server, unsigned gatewayID, unsigned serverID, const unsigned short *loginLocation, unsigned attributes) + ChatAvatarCore::ChatAvatarCore(unsigned avatarID, unsigned userID, const unsigned short *name, const unsigned short *address, const unsigned short *gateway, const unsigned short *server, unsigned gatewayID, unsigned serverID, const unsigned short *loginLocation, uint32_t attributes) : m_name(name), m_address(address), m_server(server), @@ -33,7 +33,7 @@ namespace ChatSystem { } - ChatAvatarCore::ChatAvatarCore(unsigned avatarID, unsigned userID, const ChatUnicodeString &name, const ChatUnicodeString &address, const ChatUnicodeString &gateway, const ChatUnicodeString &server, unsigned gatewayID, unsigned serverID, const ChatUnicodeString &loginLocation, unsigned attributes) + ChatAvatarCore::ChatAvatarCore(unsigned avatarID, unsigned userID, const ChatUnicodeString &name, const ChatUnicodeString &address, const ChatUnicodeString &gateway, const ChatUnicodeString &server, unsigned gatewayID, unsigned serverID, const ChatUnicodeString &loginLocation, uint32_t attributes) : m_name(name.string_data, name.string_length), m_address(address.string_data, address.string_length), m_server(server.string_data, server.string_length), @@ -49,7 +49,7 @@ namespace ChatSystem { } - ChatAvatarCore::ChatAvatarCore(unsigned avatarID, unsigned userID, const String &name, const String &address, const String &gateway, const String &server, unsigned gatewayID, unsigned serverID, const Plat_Unicode::String &loginLocation, unsigned attributes) + ChatAvatarCore::ChatAvatarCore(unsigned avatarID, unsigned userID, const String &name, const String &address, const String &gateway, const String &server, unsigned gatewayID, unsigned serverID, const Plat_Unicode::String &loginLocation, uint32_t attributes) : m_name(name), m_address(address), m_server(server), @@ -71,7 +71,7 @@ namespace ChatSystem get(iter, m_userID); ASSERT_VALID_STRING_LENGTH(get(iter, m_name)); ASSERT_VALID_STRING_LENGTH(get(iter, m_address)); - get(iter, (uint32 &)m_attributes); + get(iter, m_attributes); ASSERT_VALID_STRING_LENGTH(get(iter, m_loginLocation)); ASSERT_VALID_STRING_LENGTH(get(iter, m_server)); ASSERT_VALID_STRING_LENGTH(get(iter, m_gateway)); @@ -153,11 +153,11 @@ namespace ChatSystem put(msg, m_userID); put(msg, m_name); put(msg, m_address); - put(msg, (uint32)m_attributes); + put(msg, m_attributes); put(msg, m_loginLocation); } - void ChatAvatarCore::setAttributes(unsigned long attributes) + void ChatAvatarCore::setAttributes(uint32_t attributes) { m_attributes = attributes; } @@ -172,7 +172,7 @@ namespace ChatSystem m_email = email; } - void ChatAvatarCore::setInboxLimit(unsigned inboxLimit) + void ChatAvatarCore::setInboxLimit(uint32_t inboxLimit) { m_inboxLimit = inboxLimit; } diff --git a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatarCore.h b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatarCore.h index ebd3fc81e..e01d6b450 100755 --- a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatarCore.h +++ b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/ChatAvatarCore.h @@ -20,9 +20,9 @@ namespace ChatSystem public: ChatAvatarCore(); ChatAvatarCore(Base::ByteStream::ReadIterator &iter); - ChatAvatarCore(unsigned avatarID, unsigned userID, const unsigned short *name, const unsigned short *address, const unsigned short *gateway, const unsigned short *server, unsigned gatewayID, unsigned serverID, const unsigned short *loginLocation, unsigned attributes); - ChatAvatarCore(unsigned avatarID, unsigned userID, const ChatUnicodeString &name, const ChatUnicodeString &address, const ChatUnicodeString &gateway, const ChatUnicodeString &server, unsigned gatewayID, unsigned serverID, const ChatUnicodeString &loginLocation, unsigned attributes); - ChatAvatarCore(unsigned avatarID, unsigned userID, const Plat_Unicode::String &name, const Plat_Unicode::String &address, const Plat_Unicode::String &gateway, const Plat_Unicode::String &server, unsigned gatewayID, unsigned serverID, const Plat_Unicode::String &loginLocation, unsigned attributes); + ChatAvatarCore(unsigned avatarID, unsigned userID, const unsigned short *name, const unsigned short *address, const unsigned short *gateway, const unsigned short *server, unsigned gatewayID, unsigned serverID, const unsigned short *loginLocation, uint32_t attributes); + ChatAvatarCore(unsigned avatarID, unsigned userID, const ChatUnicodeString &name, const ChatUnicodeString &address, const ChatUnicodeString &gateway, const ChatUnicodeString &server, unsigned gatewayID, unsigned serverID, const ChatUnicodeString &loginLocation, uint32_t attributes); + ChatAvatarCore(unsigned avatarID, unsigned userID, const Plat_Unicode::String &name, const Plat_Unicode::String &address, const Plat_Unicode::String &gateway, const Plat_Unicode::String &server, unsigned gatewayID, unsigned serverID, const Plat_Unicode::String &loginLocation, uint32_t attributes); ChatAvatarCore(const ChatAvatarCore &rhs); @@ -34,9 +34,9 @@ namespace ChatSystem unsigned getAvatarID() const { return m_avatarID; } const Plat_Unicode::String &getLoginLocation() const { return m_loginLocation; } int getLoginPriority() const { return m_loginPriority; } - unsigned getAttributes() const { return m_attributes; } + uint32_t getAttributes() const { return m_attributes; } const Plat_Unicode::String &getEmail() const { return m_email; } - unsigned getInboxLimit() const { return m_inboxLimit; } + uint32_t getInboxLimit() const { return m_inboxLimit; } const Plat_Unicode::String &getServer() const { return m_server; } const Plat_Unicode::String &getGateway() const { return m_gateway; } unsigned getServerID() const { return m_serverID; } @@ -45,7 +45,7 @@ namespace ChatSystem ChatAvatar *getNewChatAvatar() const; - void setAttributes(unsigned long attributes); + void setAttributes(uint32_t attributes); void setLoginPriority(int loginPriority); void setEmail(const Plat_Unicode::String email); void setInboxLimit(unsigned inboxLimit); @@ -63,8 +63,8 @@ namespace ChatSystem Plat_Unicode::String m_email; Plat_Unicode::String m_statusMessage; - unsigned long m_attributes; - unsigned long m_inboxLimit; + uint32_t m_attributes; + uint32_t m_inboxLimit; int m_loginPriority; unsigned m_userID; diff --git a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/Response.cpp b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/Response.cpp index ad0894994..ba8e8efb5 100755 --- a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/Response.cpp +++ b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/Response.cpp @@ -1471,7 +1471,7 @@ namespace ChatSystem get(iter, m_type); get(iter, m_track); get(iter, m_result); - get(iter, (uint32 &)m_serverVersion); + get(iter, m_serverVersion); } ResAddSnoopAvatar::ResAddSnoopAvatar(void *user, unsigned srcAvatarID, const ChatUnicodeString &destName, const ChatUnicodeString &destAddress) diff --git a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/Response.h b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/Response.h index b12077468..edd3edba1 100755 --- a/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/Response.h +++ b/external/3rd/library/soePlatform/ChatAPI/projects/ChatAPI/Response.h @@ -1186,9 +1186,9 @@ namespace ChatSystem virtual void unpack(Base::ByteStream::ReadIterator &iter); - unsigned long getServerVersion() const { return m_serverVersion; } + uint32_t getServerVersion() const { return m_serverVersion; } private: - unsigned long m_serverVersion; + uint32_t m_serverVersion; }; class ResAddSnoopAvatar : public GenericAPI::GenericResponse diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/Archive.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/Archive.h index 8e13f2c01..95c0c6f4c 100755 --- a/external/3rd/library/soePlatform/ChatAPI/utils/Base/Archive.h +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/Archive.h @@ -664,8 +664,9 @@ const unsigned MAX_ARRAY_SIZE = 1024; Base::get(source, arraySize); ValueType v; - if (arraySize > MAX_ARRAY_SIZE) + if (arraySize > MAX_ARRAY_SIZE) { arraySize = 0; + } for(unsigned int i = 0; i < arraySize; ++i) { diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/BlockAllocator.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/BlockAllocator.h index bbfbf2738..f9f9f8632 100755 --- a/external/3rd/library/soePlatform/ChatAPI/utils/Base/BlockAllocator.h +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/BlockAllocator.h @@ -17,7 +17,7 @@ namespace Base BlockAllocator(); ~BlockAllocator(); void *getBlock(unsigned accum); - void returnBlock(unsigned *handle); + void returnBlock(uintptr_t *handle); private: uintptr_t *m_blocks[31]; diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/linux/BlockAllocator.cpp b/external/3rd/library/soePlatform/ChatAPI/utils/Base/linux/BlockAllocator.cpp index 29d910749..f4042d1f6 100755 --- a/external/3rd/library/soePlatform/ChatAPI/utils/Base/linux/BlockAllocator.cpp +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/linux/BlockAllocator.cpp @@ -23,8 +23,8 @@ namespace Base { while(m_blocks[i] != nullptr) { - unsigned *tmp = m_blocks[i]; - m_blocks[i] = (unsigned *)*m_blocks[i]; + uintptr_t *tmp = m_blocks[i]; + m_blocks[i] = (uintptr_t *)*m_blocks[i]; free(tmp); } } @@ -36,7 +36,7 @@ namespace Base void *BlockAllocator::getBlock(unsigned bytes) { unsigned accum = 16, bits = 16; - unsigned *handle = nullptr; + uintptr_t *handle = nullptr; // Perform a binary search looking for the highest bit. @@ -79,7 +79,7 @@ namespace Base if(m_blocks[accum] == 0) { // remove the pre allocated block from the linked list - handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned)); + handle = (uintptr_t *)calloc(((1 << accum) / 4) + 2, sizeof(uintptr_t)); handle[1] = accum; handle[0] = 0; } @@ -87,20 +87,20 @@ namespace Base { // Allocate a new block handle = m_blocks[accum]; - m_blocks[accum] = (unsigned *)handle[0]; + m_blocks[accum] = (uintptr_t *)handle[0]; handle[0] = 0; } // return a pointer that skips over the header used for the allocator's purposes return(handle + 2); } - void BlockAllocator::returnBlock(unsigned *handle) + void BlockAllocator::returnBlock(uintptr_t *handle) { // C++ allows for safe deletion of a nullptr pointer if(handle) { // Update the allocator linked list, insert this entry at the head - *(handle - 2) = (unsigned)m_blocks[*(handle - 1)]; + *(handle - 2) = (uintptr_t)m_blocks[*(handle - 1)]; // Add this entry to the proper linked list node m_blocks[*(handle - 1)] = (handle - 2); } diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/linux/Types.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/linux/Types.h index 6ee504505..574ee5caa 100755 --- a/external/3rd/library/soePlatform/ChatAPI/utils/Base/linux/Types.h +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/linux/Types.h @@ -11,7 +11,8 @@ #ifndef BASE_LINUX_TYPES_H #define BASE_LINUX_TYPES_H -#include +//#include +#include #ifdef EXTERNAL_DISTRO namespace NAMESPACE @@ -27,13 +28,13 @@ namespace Base typedef signed char int8; typedef unsigned char uint8; -typedef signed short int16; -typedef unsigned short uint16; +typedef int16_t int16; +typedef uint16_t uint16; typedef int32_t int32; -typedef u_int32_t uint32; +typedef uint32_t uint32; typedef int64_t int64; -typedef u_int64_t uint64; +typedef uint64_t uint64; } #ifdef EXTERNAL_DISTRO }; diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Types.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Types.h index 0c64cb2cb..10905cc1a 100755 --- a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Types.h +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Types.h @@ -25,13 +25,13 @@ namespace Base typedef signed char int8; typedef unsigned char uint8; -typedef short int16; -typedef unsigned short uint16; +typedef int16_t int16; +typedef uint16_t uint16; -typedef int int32; -typedef unsigned uint32; -typedef __int64 int64; -typedef unsigned __int64 uint64; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; }; #ifdef EXTERNAL_DISTRO diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/UdpLibrary/UdpDriverLinux.cpp b/external/3rd/library/soePlatform/ChatAPI/utils/UdpLibrary/UdpDriverLinux.cpp index aa11f5cdc..9ca240140 100755 --- a/external/3rd/library/soePlatform/ChatAPI/utils/UdpLibrary/UdpDriverLinux.cpp +++ b/external/3rd/library/soePlatform/ChatAPI/utils/UdpLibrary/UdpDriverLinux.cpp @@ -1,6 +1,12 @@ // Copyright 2004 Sony Online Entertainment, all rights reserved. // Author: Jeff Petersen +#ifdef NDEBUG +#define SWG_ASSERT(exp) ((void) (exp)) +#else +#define SWG_ASSERT assert +#endif + #include "UdpDriver.h" #include "UdpHelper.h" @@ -17,7 +23,6 @@ #include // needed by gcc 3.1 for linux #include - namespace UdpLibrary { @@ -80,19 +85,19 @@ bool UdpPlatformDriver::SocketOpen(int port, int incomingBufferSize, int outgoin // open socket stuff unsigned long nb = 1; int err = ioctl(mData->socket, FIONBIO, &nb); - assert(err != -1); + SWG_ASSERT(err != -1); nb = outgoingBufferSize; err = setsockopt(mData->socket, SOL_SOCKET, SO_SNDBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = incomingBufferSize; err = setsockopt(mData->socket, SOL_SOCKET, SO_RCVBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = 0; err = setsockopt(mData->socket, SOL_SOCKET, SO_BSDCOMPAT, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = 1; err = setsockopt(mData->socket, SOL_IP, IP_RECVERR, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); int optLen = sizeof(mData->startTtl); getsockopt(mData->socket, IPPROTO_IP, IP_TTL, &mData->startTtl, (socklen_t *)&optLen); diff --git a/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/Base/serializeClasses.h b/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/Base/serializeClasses.h index 8e6e37401..7db29d5dd 100755 --- a/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/Base/serializeClasses.h +++ b/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/Base/serializeClasses.h @@ -389,57 +389,45 @@ namespace soe { if (size < sizeof(int64)) return 0; -#if (defined(WIN32) || defined(linux)) - uint32 low = *(uint32_t *) &data; - uint32 high = *((uint32_t *)&data+1); -#elif defined(sparc) - uint32 low = *((uint32 *)&data+1); - uint32 high = *(uint32 *)(&data); -#endif - stream[BYTE1] = (unsigned char)low&0xff; - stream[BYTE2] = (unsigned char)(low>>8)&0xff; - stream[BYTE3] = (unsigned char)(low>>16)&0xff; - stream[BYTE4] = (unsigned char)(low>>24)&0xff; - stream[BYTE5] = (unsigned char)high&0xff; - stream[BYTE6] = (unsigned char)(high>>8)&0xff; - stream[BYTE7] = (unsigned char)(high>>16)&0xff; - stream[BYTE8] = (unsigned char)(high>>24)&0xff; + stream[BYTE1] = data&0xff; + stream[BYTE2] = (data>>8)&0xff; + stream[BYTE3] = (data>>16)&0xff; + stream[BYTE4] = (data>>24)&0xff; + stream[BYTE5] = (data>>32)&0xff; + stream[BYTE6] = (data>>40)&0xff; + stream[BYTE7] = (data>>48)&0xff; + stream[BYTE8] = (data>>56)&0xff; return sizeof(int64); } // 370 ns inline unsigned Write(unsigned char * stream, unsigned size, uint64 data, unsigned version = 0) { - if (size < sizeof(uint64)) + if (size < sizeof(int64)) return 0; -#if (defined(WIN32) || defined(linux)) - uint32 low = *(uint32_t *) &data; - uint32 high = *((uint32_t *)&data+1); -#elif defined(sparc) - uint32 low = *((uint32 *)&data+1); - uint32 high = *(uint32 *)(&data); -#endif - stream[BYTE1] = (unsigned char)low&0xff; - stream[BYTE2] = (unsigned char)(low>>8)&0xff; - stream[BYTE3] = (unsigned char)(low>>16)&0xff; - stream[BYTE4] = (unsigned char)(low>>24)&0xff; - stream[BYTE5] = (unsigned char)high&0xff; - stream[BYTE6] = (unsigned char)(high>>8)&0xff; - stream[BYTE7] = (unsigned char)(high>>16)&0xff; - stream[BYTE8] = (unsigned char)(high>>24)&0xff; - return sizeof(uint64); + stream[BYTE1] = data&0xff; + stream[BYTE2] = (data>>8)&0xff; + stream[BYTE3] = (data>>16)&0xff; + stream[BYTE4] = (data>>24)&0xff; + stream[BYTE5] = (data>>32)&0xff; + stream[BYTE6] = (data>>40)&0xff; + stream[BYTE7] = (data>>48)&0xff; + stream[BYTE8] = (data>>56)&0xff; + return sizeof(int64); } // 360 ns inline unsigned Write(unsigned char * stream, unsigned size, float data, unsigned version = 0) { - uint32 & dataRef = *(uint32_t *)(&data); if (size < sizeof(float)) return 0; - stream[BYTE1] = dataRef&0xff; - stream[BYTE2] = (dataRef>>8)&0xff; - stream[BYTE3] = (dataRef>>16)&0xff; - stream[BYTE4] = (dataRef>>24)&0xff; + unsigned char dataArr[sizeof(float)]; + memcpy(&dataArr, &data, sizeof(float)); + + stream[BYTE1] = dataArr[0]&0xff; + stream[BYTE2] = dataArr[1]&0xff; + stream[BYTE3] = dataArr[2]&0xff; + stream[BYTE4] = dataArr[3]&0xff; return sizeof(float); } @@ -448,21 +436,17 @@ namespace soe { if (size < sizeof(double)) return 0; -#if (defined(WIN32) || defined(linux)) - uint32 low = *(uint32_t *)(&data); - uint32 high = *((uint32_t *)&data+1); -#elif defined(sparc) - uint32 low = *((uint32 *)&data+1); - uint32 high = *(uint32 *)(&data); -#endif - stream[BYTE1] = (unsigned char)low&0xff; - stream[BYTE2] = (unsigned char)(low>>8)&0xff; - stream[BYTE3] = (unsigned char)(low>>16)&0xff; - stream[BYTE4] = (unsigned char)(low>>24)&0xff; - stream[BYTE5] = (unsigned char)high&0xff; - stream[BYTE6] = (unsigned char)(high>>8)&0xff; - stream[BYTE7] = (unsigned char)(high>>16)&0xff; - stream[BYTE8] = (unsigned char)(high>>24)&0xff; + unsigned char dataArr[sizeof(double)]; + memcpy(&dataArr, &data, sizeof(double)); + + stream[BYTE1] = dataArr[0]&0xff; + stream[BYTE2] = dataArr[1]&0xff; + stream[BYTE3] = dataArr[2]&0xff; + stream[BYTE4] = dataArr[3]&0xff; + stream[BYTE5] = dataArr[4]&0xff; + stream[BYTE6] = dataArr[5]&0xff; + stream[BYTE7] = dataArr[6]&0xff; + stream[BYTE8] = dataArr[7]&0xff; return sizeof(double); } diff --git a/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/Base/types.h b/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/Base/types.h index ba396c51e..19d20d139 100755 --- a/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/Base/types.h +++ b/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/Base/types.h @@ -6,7 +6,8 @@ #define STRINGIFY(S) #S #ifdef linux -#include +//#include +#include #endif #define DECLSPEC @@ -34,21 +35,21 @@ namespace soe { typedef char int8; typedef unsigned char uint8; - typedef short int16; - typedef unsigned short uint16; + typedef int16_t int16; + typedef uint16_t uint16; #ifdef WIN32 - typedef int int32; - typedef unsigned uint32; - typedef __int64 int64; - typedef unsigned __int64 uint64; + typedef int32_t int32; + typedef uint32_t uint32; + typedef int64_t int64; + typedef uint64_t uint64; #elif linux - typedef int32_t int32; - typedef u_int32_t uint32; - typedef int64_t int64; - typedef u_int64_t uint64; + typedef int32_t int32; + typedef uint32_t uint32; + typedef int64_t int64; + typedef uint64_t uint64; //! the previous seem erroneous // typedef signed int int32; // typedef unsigned int uint32; diff --git a/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/UdpLibrary/UdpLibrary.cpp b/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/UdpLibrary/UdpLibrary.cpp index f86f5d7bb..c7ca918d5 100755 --- a/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/UdpLibrary/UdpLibrary.cpp +++ b/external/3rd/library/soePlatform/VChatAPI/utils2.0/utils/UdpLibrary/UdpLibrary.cpp @@ -1,3 +1,9 @@ +#ifdef NDEBUG +#define SWG_ASSERT(exp) ((void) (exp)) +#else +#define SWG_ASSERT assert +#endif + #include #include #include @@ -443,36 +449,36 @@ void UdpManager::CreateAndBindSocket(int usePort) #elif defined(sparc) ulong nb = 1; int err = ioctl(mUdpSocket, FIONBIO, &nb); - assert(err != -1); + SWG_ASSERT(err != -1); nb = udpMin(256 * 1024, mParams.outgoingBufferSize); err = setsockopt(mUdpSocket, SOL_SOCKET, SO_SNDBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = udpMin(256 * 1024, mParams.incomingBufferSize); err = setsockopt(mUdpSocket, SOL_SOCKET, SO_RCVBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); int optLen = sizeof(mStartTtl); getsockopt(mUdpSocket, IPPROTO_IP, IP_TTL, &mStartTtl, (socklen_t *)&optLen); nb = 1; err = setsockopt(mUdpSocket, SOL_SOCKET, SO_DGRAM_ERRIND, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); #else // linux is to remain the default compile mode unsigned long nb = 1; int err = ioctl(mUdpSocket, FIONBIO, &nb); - assert(err != -1); + SWG_ASSERT(err != -1); nb = mParams.outgoingBufferSize; err = setsockopt(mUdpSocket, SOL_SOCKET, SO_SNDBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = mParams.incomingBufferSize; err = setsockopt(mUdpSocket, SOL_SOCKET, SO_RCVBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = 0; err = setsockopt(mUdpSocket, SOL_SOCKET, SO_BSDCOMPAT, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = 1; err = setsockopt(mUdpSocket, SOL_IP, IP_RECVERR, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); int optLen = sizeof(mStartTtl); getsockopt(mUdpSocket, IPPROTO_IP, IP_TTL, &mStartTtl, (socklen_t *)&optLen); diff --git a/external/3rd/library/udplibrary/UdpLibrary.cpp b/external/3rd/library/udplibrary/UdpLibrary.cpp index 4105355fe..7d91ea6c2 100755 --- a/external/3rd/library/udplibrary/UdpLibrary.cpp +++ b/external/3rd/library/udplibrary/UdpLibrary.cpp @@ -1,3 +1,9 @@ +#ifdef NDEBUG +#define SWG_ASSERT(exp) ((void) (exp)) +#else +#define SWG_ASSERT assert +#endif + #include #include #include @@ -438,36 +444,36 @@ void UdpManager::CreateAndBindSocket(int usePort) #elif defined(sparc) ulong nb = 1; int err = ioctl(mUdpSocket, FIONBIO, &nb); - assert(err != -1); + SWG_ASSERT(err != -1); nb = udpMin(256 * 1024, mParams.outgoingBufferSize); err = setsockopt(mUdpSocket, SOL_SOCKET, SO_SNDBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = udpMin(256 * 1024, mParams.incomingBufferSize); err = setsockopt(mUdpSocket, SOL_SOCKET, SO_RCVBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); int optLen = sizeof(mStartTtl); getsockopt(mUdpSocket, IPPROTO_IP, IP_TTL, &mStartTtl, (socklen_t *)&optLen); nb = 1; err = setsockopt(mUdpSocket, SOL_SOCKET, SO_DGRAM_ERRIND, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); #else // linux is to remain the default compile mode unsigned long nb = 1; int err = ioctl(mUdpSocket, FIONBIO, &nb); - assert(err != -1); + SWG_ASSERT(err != -1); nb = mParams.outgoingBufferSize; err = setsockopt(mUdpSocket, SOL_SOCKET, SO_SNDBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = mParams.incomingBufferSize; err = setsockopt(mUdpSocket, SOL_SOCKET, SO_RCVBUF, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = 0; err = setsockopt(mUdpSocket, SOL_SOCKET, SO_BSDCOMPAT, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); nb = 1; err = setsockopt(mUdpSocket, SOL_IP, IP_RECVERR, &nb, sizeof(nb)); - assert(err == 0); + SWG_ASSERT(err == 0); int optLen = sizeof(mStartTtl); getsockopt(mUdpSocket, IPPROTO_IP, IP_TTL, &mStartTtl, (socklen_t *)&optLen); @@ -560,7 +566,8 @@ void UdpManager::RemoveConnection(UdpConnection *con) mAddressHashTable->Remove(con, AddressHashValue(con->mIp, con->mPort)); - unsigned int addy = con->mIp.GetAddress(); + // addy is unused + // unsigned int addy = con->mIp.GetAddress(); mConnectCodeHashTable->Remove(con, con->mConnectCode); } @@ -2896,21 +2903,21 @@ const char *UdpConnection::DisconnectReasonText(DisconnectReason reason) { sInitialized = true; memset(sDisconnectReason, 0, sizeof(sDisconnectReason)); - sDisconnectReason[cDisconnectReasonNone] = "DisconnectReasonNone"; - sDisconnectReason[cDisconnectReasonIcmpError] = "DisconnectReasonIcmpError"; - sDisconnectReason[cDisconnectReasonTimeout] = "DisconnectReasonTimeout"; - sDisconnectReason[cDisconnectReasonOtherSideTerminated] = "DisconnectReasonOtherSideTerminated"; - sDisconnectReason[cDisconnectReasonManagerDeleted] = "DisconnectReasonManagerDeleted"; - sDisconnectReason[cDisconnectReasonConnectFail] = "DisconnectReasonConnectFail"; - sDisconnectReason[cDisconnectReasonApplication] = "DisconnectReasonApplication"; - sDisconnectReason[cDisconnectReasonUnreachableConnection] = "DisconnectReasonUnreachableConnection"; - sDisconnectReason[cDisconnectReasonUnacknowledgedTimeout] = "DisconnectReasonUnacknowledgedTimeout"; - sDisconnectReason[cDisconnectReasonNewConnectionAttempt] = "DisconnectReasonNewConnectionAttempt"; - sDisconnectReason[cDisconnectReasonConnectionRefused] = "DisconnectReasonConnectionRefused"; - sDisconnectReason[cDisconnectReasonMutualConnectError] = "DisconnectReasonConnectError"; - sDisconnectReason[cDisconnectReasonConnectingToSelf] = "DisconnectReasonConnectingToSelf"; - sDisconnectReason[cDisconnectReasonReliableOverflow] = "DisconnectReasonReliableOverflow"; - sDisconnectReason[cDisconnectReasonDosAttack] = "DisconnectReasonDoSAttack"; + sDisconnectReason[cDisconnectReasonNone] = (char *) "DisconnectReasonNone"; + sDisconnectReason[cDisconnectReasonIcmpError] = (char *) "DisconnectReasonIcmpError"; + sDisconnectReason[cDisconnectReasonTimeout] = (char *) "DisconnectReasonTimeout"; + sDisconnectReason[cDisconnectReasonOtherSideTerminated] = (char *) "DisconnectReasonOtherSideTerminated"; + sDisconnectReason[cDisconnectReasonManagerDeleted] = (char *) "DisconnectReasonManagerDeleted"; + sDisconnectReason[cDisconnectReasonConnectFail] = (char *) "DisconnectReasonConnectFail"; + sDisconnectReason[cDisconnectReasonApplication] = (char *) "DisconnectReasonApplication"; + sDisconnectReason[cDisconnectReasonUnreachableConnection] = (char *) "DisconnectReasonUnreachableConnection"; + sDisconnectReason[cDisconnectReasonUnacknowledgedTimeout] = (char *) "DisconnectReasonUnacknowledgedTimeout"; + sDisconnectReason[cDisconnectReasonNewConnectionAttempt] = (char *) "DisconnectReasonNewConnectionAttempt"; + sDisconnectReason[cDisconnectReasonConnectionRefused] = (char *) "DisconnectReasonConnectionRefused"; + sDisconnectReason[cDisconnectReasonMutualConnectError] = (char *) "DisconnectReasonConnectError"; + sDisconnectReason[cDisconnectReasonConnectingToSelf] = (char *) "DisconnectReasonConnectingToSelf"; + sDisconnectReason[cDisconnectReasonReliableOverflow] = (char *) "DisconnectReasonReliableOverflow"; + sDisconnectReason[cDisconnectReasonDosAttack] = (char *) "DisconnectReasonDoSAttack"; } return(sDisconnectReason[reason]); diff --git a/external/ours/library/archive/src/shared/Archive.h b/external/ours/library/archive/src/shared/Archive.h index 2921d66f7..b47190c19 100755 --- a/external/ours/library/archive/src/shared/Archive.h +++ b/external/ours/library/archive/src/shared/Archive.h @@ -30,42 +30,28 @@ inline void get(ReadIterator & source, float & target) //--------------------------------------------------------------------- -inline void get(ReadIterator & source, unsigned long int & target) +inline void get(ReadIterator & source, uint32_t & target) { source.get(&target, 4); } //--------------------------------------------------------------------- -inline void get(ReadIterator & source, signed long int & target) +inline void get(ReadIterator & source, int32_t & target) { source.get(&target, 4); } //--------------------------------------------------------------------- -inline void get(ReadIterator & source, unsigned int & target) -{ - source.get(&target, 4); -} - -//--------------------------------------------------------------------- - -inline void get(ReadIterator & source, signed int & target) -{ - source.get(&target, 4); -} - -//--------------------------------------------------------------------- - -inline void get(ReadIterator & source, unsigned short int & target) +inline void get(ReadIterator & source, uint16_t & target) { source.get(&target, 2); } //--------------------------------------------------------------------- -inline void get(ReadIterator & source, signed short int & target) +inline void get(ReadIterator & source, int16_t & target) { source.get(&target, 2); } @@ -190,9 +176,9 @@ template inline void get_ptr(ReadIterator & source, std::vector inline void get(ReadIterator & source, std::map & target) { - size_t numKeys; + int32_t numKeys; get(source, numKeys); - size_t i; + int32_t i; for(i = 0; i < numKeys; ++i) { Key k; @@ -229,42 +215,28 @@ inline void put(ByteStream & target, const float & source) //--------------------------------------------------------------------- -inline void put(ByteStream & target, const unsigned long int & source) -{ - target.put(&source, 4); -} - -//--------------------------------------------------------------------- - -inline void put(ByteStream & target, const signed long int & source) -{ - target.put(&source, 4); -} - -//--------------------------------------------------------------------- - -inline void put(ByteStream & target, const unsigned int & source) +inline void put(ByteStream & target, const uint32_t & source) { target.put(&source, 4); } //--------------------------------------------------------------------- -inline void put(ByteStream & target, const signed int & source) +inline void put(ByteStream & target, const int32_t & source) { target.put(&source, 4); } //--------------------------------------------------------------------- -inline void put(ByteStream & target, const unsigned short int & source) +inline void put(ByteStream & target, const uint16_t & source) { target.put(&source, 2); } //--------------------------------------------------------------------- -inline void put(ByteStream & target, const signed short int & source) +inline void put(ByteStream & target, const int16_t & source) { target.put(&source, 2); } @@ -296,12 +268,12 @@ inline void put(ByteStream & target, const std::string & source) { if (source.size() < 65535) { - unsigned short len = static_cast(source.size()); + unsigned short len = static_cast(source.size()); put(target, len); } else { - unsigned short len = static_cast(65535); + unsigned short len = static_cast(65535); put(target, len); unsigned int size = source.size(); put(target, size); @@ -345,7 +317,7 @@ template inline void put(ByteStream & target, const std: template inline void put(ByteStream & target, const std::vector & source) { - signed int length = source.size(); + int32_t length = source.size(); target.put(&length, 4); for(int i = 0; i < length; ++i) { @@ -357,7 +329,7 @@ template inline void put(ByteStream & target, const std::vector & template inline void put(ByteStream & target, const std::set & source) { - signed int length = source.size(); + int32_t length = source.size(); target.put(&length, 4); for (typename std::set::const_iterator i = source.begin(); i != source.end(); ++i) put(target, *i); @@ -367,7 +339,7 @@ template inline void put(ByteStream & target, const std::set & so template inline void put(ByteStream & target, const std::deque & source) { - signed int length = source.size(); + int32_t length = source.size(); target.put(&length, 4); for(int i = 0; i < length; ++i) { @@ -379,7 +351,7 @@ template inline void put(ByteStream & target, const std::deque & template inline void put(ByteStream & target, const std::map & source) { - size_t numKeys = source.size(); + int32_t numKeys = source.size(); put(target, numKeys); for (typename std::map::const_iterator i = source.begin(); i != source.end(); ++i) { diff --git a/external/ours/library/archive/src/shared/AutoDeltaByteStream.h b/external/ours/library/archive/src/shared/AutoDeltaByteStream.h index 53b4d07d0..ab6f9ed5d 100755 --- a/external/ours/library/archive/src/shared/AutoDeltaByteStream.h +++ b/external/ours/library/archive/src/shared/AutoDeltaByteStream.h @@ -726,7 +726,7 @@ class AutoDeltaContainer : public AutoDeltaVariableBase /** pure virtual */ virtual ~AutoDeltaContainer() = 0; /** pure virtual */ - virtual const size_t size() const = 0; + virtual const uint32_t size() const = 0; }; //----------------------------------------------------------------------- diff --git a/external/ours/library/archive/src/shared/AutoDeltaMap.h b/external/ours/library/archive/src/shared/AutoDeltaMap.h index 9256495cf..d1fc90187 100755 --- a/external/ours/library/archive/src/shared/AutoDeltaMap.h +++ b/external/ours/library/archive/src/shared/AutoDeltaMap.h @@ -65,7 +65,7 @@ class AutoDeltaMap : public AutoDeltaContainer void pack(ByteStream & target) const; void packDelta(ByteStream & target) const; void set(const KeyType & key, const ValueType & value); - const size_t size() const; + const uint32_t size() const; void unpack(ReadIterator & source); void unpackDelta(ReadIterator & source); static void pack(ByteStream & target, const std::vector & data); @@ -88,7 +88,7 @@ class AutoDeltaMap : public AutoDeltaContainer void onSet(const KeyType &, const ValueType &, const ValueType &); MapType container; - size_t baselineCommandCount; + int32_t baselineCommandCount; mutable std::vector changes; std::pair *onEraseCallback; std::pair *onInsertCallback; @@ -349,7 +349,7 @@ template inline void AutoDeltaMap::pack(ByteStream & target) const { typename std::map::const_iterator i; - Archive::put(target, container.size()); + Archive::put(target, static_cast(container.size())); Archive::put(target, baselineCommandCount); unsigned char cmd; for(i = container.begin(); i != container.end(); ++i) @@ -374,8 +374,8 @@ inline void AutoDeltaMap::pack(ByteStream & targ template inline void AutoDeltaMap::pack(ByteStream & target, const std::vector &data) { - Archive::put(target, data.size()); - Archive::put(target, static_cast(0)); // baselineCommandCount + Archive::put(target, static_cast(data.size())); + Archive::put(target, static_cast(0)); // baselineCommandCount for(typename std::vector::const_iterator c(data.begin()); c != data.end(); ++c) { assert(c->cmd == Command::ADD); // only add is valid in packing the whole container @@ -403,7 +403,7 @@ inline void AutoDeltaMap::pack(ByteStream & targ template inline void AutoDeltaMap::packDelta(ByteStream & target) const { - Archive::put(target, changes.size()); + Archive::put(target, static_cast(changes.size())); Archive::put(target, baselineCommandCount); for (typename std::vector::iterator i = changes.begin(); i != changes.end(); ++i) { @@ -435,7 +435,7 @@ inline void AutoDeltaMap::packDelta(ByteStream & @return the number of elements in the map */ template -inline const size_t AutoDeltaMap::size() const +inline const uint32_t AutoDeltaMap::size() const { return container.size(); } @@ -514,12 +514,12 @@ inline void AutoDeltaMap::unpack(ReadIterator & clearDelta(); Command c; - size_t commandCount; + int32_t commandCount; Archive::get(source, commandCount); Archive::get(source, baselineCommandCount); - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { Archive::get(source, c.cmd); assert(c.cmd == Command::ADD); // only add is valid in unpack @@ -548,13 +548,13 @@ inline void AutoDeltaMap::unpack(ReadIterator & // unpacking baseline data Command c; - size_t commandCount; - size_t baselineCommandCount; + int32_t commandCount; + int32_t baselineCommandCount; Archive::get(source, commandCount); Archive::get(source, baselineCommandCount); - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { Archive::get(source, c.cmd); assert(c.cmd == Command::ADD); // only add is valid in unpack @@ -572,7 +572,7 @@ template inline void AutoDeltaMap::unpackDelta(ReadIterator & source) { Command c; - size_t skipCount, commandCount, targetBaselineCommandCount; + int32_t skipCount, commandCount, targetBaselineCommandCount; Archive::get(source, commandCount); Archive::get(source, targetBaselineCommandCount); @@ -593,7 +593,7 @@ inline void AutoDeltaMap::unpackDelta(ReadIterat if (skipCount > commandCount) skipCount = commandCount; - size_t i; + int32_t i; for (i = 0; i < skipCount; ++i) { Archive::get(source, c.cmd); @@ -647,12 +647,12 @@ template inline void AutoDeltaMap::unpackDelta(ReadIterator & source, std::vector & data) { Command c; - size_t commandCount, targetBaselineCommandCount; + int32_t commandCount, targetBaselineCommandCount; Archive::get(source, commandCount); Archive::get(source, targetBaselineCommandCount); - for (size_t i=0 ; i < commandCount; ++i) + for (int32_t i=0 ; i < commandCount; ++i) { Archive::get(source, c.cmd); switch(c.cmd) diff --git a/external/ours/library/archive/src/shared/AutoDeltaPackedMap.h b/external/ours/library/archive/src/shared/AutoDeltaPackedMap.h index e73b56b30..f6b0539f6 100755 --- a/external/ours/library/archive/src/shared/AutoDeltaPackedMap.h +++ b/external/ours/library/archive/src/shared/AutoDeltaPackedMap.h @@ -23,8 +23,8 @@ namespace Archive void get(ReadIterator & source, unsigned __int64 & target); void put(ByteStream & target, const unsigned __int64 & source); #else - void get(ReadIterator & source, unsigned long long int & target); - void put(ByteStream & target, const unsigned long long int & source); + void get(ReadIterator & source, uint64_t & target); + void put(ByteStream & target, const uint64_t & source); #endif /** * An AutoDeltaPackedMap is an AutoDeltaMap that will be packed into @@ -100,7 +100,7 @@ namespace Archive typename AutoDeltaMap::Command c; Archive::put(target, countCharacter(buffer,':')); - Archive::put(target, static_cast(0)); // baselineCommandCount + Archive::put(target, static_cast(0)); // baselineCommandCount int tempPos = 0; for (std::string::const_iterator i=buffer.begin(); i!=buffer.end(); ++i) @@ -127,8 +127,8 @@ namespace Archive char temp[200]; typename AutoDeltaMap::Command c; - size_t commandCount; - size_t baselineCommandCount; + int32_t commandCount; + int32_t baselineCommandCount; Archive::get(source, commandCount); Archive::get(source, baselineCommandCount); @@ -139,7 +139,7 @@ namespace Archive } else { - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { Archive::get(source, c.cmd); Archive::get(source, c.key); @@ -193,30 +193,41 @@ namespace Archive } template<> - inline void AutoDeltaPackedMap::pack(ByteStream & target, const std::string & buffer) + inline void AutoDeltaPackedMap::pack(ByteStream & target, const std::string & buffer) { internal_pack(target, buffer, "%i %i"); } template<> - inline void AutoDeltaPackedMap::unpack(ReadIterator & source, std::string & buffer) + inline void AutoDeltaPackedMap::unpack(ReadIterator & source, std::string & buffer) { internal_unpack(source, buffer, "%i %i:"); } template<> - inline void AutoDeltaPackedMap::pack(ByteStream & target, const std::string & buffer) + inline void AutoDeltaPackedMap::pack(ByteStream & target, const std::string & buffer) { internal_pack(target, buffer, "%i %u"); } template<> - inline void AutoDeltaPackedMap::unpack(ReadIterator & source, std::string & buffer) + inline void AutoDeltaPackedMap::unpack(ReadIterator & source, std::string & buffer) { internal_unpack(source, buffer, "%i %u:"); } #ifdef WIN32 + template<> + inline void AutoDeltaPackedMap::pack(ByteStream & target, const std::string & buffer) + { + internal_pack(target, buffer, "%lu %I64u"); + } + + template<> + inline void AutoDeltaPackedMap::unpack(ReadIterator & source, std::string & buffer) + { + internal_unpack(source, buffer, "%lu %I64u:"); + } template<> inline void AutoDeltaPackedMap::pack(ByteStream & target, const std::string & buffer) { @@ -231,13 +242,13 @@ namespace Archive #else template<> - inline void AutoDeltaPackedMap::pack(ByteStream & target, const std::string & buffer) + inline void AutoDeltaPackedMap::pack(ByteStream & target, const std::string & buffer) { internal_pack(target, buffer, "%lu %llu"); } template<> - inline void AutoDeltaPackedMap::unpack(ReadIterator & source, std::string & buffer) + inline void AutoDeltaPackedMap::unpack(ReadIterator & source, std::string & buffer) { internal_unpack(source, buffer, "%lu %llu:"); } diff --git a/external/ours/library/archive/src/shared/AutoDeltaQueue.h b/external/ours/library/archive/src/shared/AutoDeltaQueue.h index 5b29aacf3..ad17937ef 100755 --- a/external/ours/library/archive/src/shared/AutoDeltaQueue.h +++ b/external/ours/library/archive/src/shared/AutoDeltaQueue.h @@ -46,7 +46,7 @@ class AutoDeltaQueue: public AutoDeltaContainer const bool isDirty() const; void pack(ByteStream &target) const; void packDelta(ByteStream &target) const; - const size_t size() const; + const uint32_t size() const; void unpack(ReadIterator &source); void unpackDelta(ReadIterator &source); @@ -72,7 +72,7 @@ class AutoDeltaQueue: public AutoDeltaContainer }; QueueType container; - size_t baselineCommandCount; + uint32_t baselineCommandCount; mutable std::vector changes; AutoDeltaQueue &operator=(AutoDeltaQueue const &); @@ -251,7 +251,7 @@ template inline void AutoDeltaQueue::pack(ByteStream &target) const { const_iterator i; - Archive::put(target, container.size()); + Archive::put(target, static_cast (container.size())); Archive::put(target, baselineCommandCount); unsigned char cmd; for (i = container.begin(); i != container.end(); ++i) @@ -267,7 +267,7 @@ inline void AutoDeltaQueue::pack(ByteStream &target) const template inline void AutoDeltaQueue::packDelta(ByteStream &target) const { - Archive::put(target, changes.size()); + Archive::put(target, static_cast (changes.size())); Archive::put(target, baselineCommandCount); for (typename std::vector::iterator i = changes.begin(); i != changes.end(); ++i) { @@ -293,7 +293,7 @@ inline void AutoDeltaQueue::packDelta(ByteStream &target) const //----------------------------------------------------------------------- template -inline const size_t AutoDeltaQueue::size() const +inline const uint32_t AutoDeltaQueue::size() const { return container.size(); } @@ -324,12 +324,12 @@ inline void AutoDeltaQueue::unpack(ReadIterator &source) clearDelta(); ModifyCommand c; - size_t commandCount; + int32_t commandCount; Archive::get(source, commandCount); Archive::get(source, baselineCommandCount); - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { Archive::get(source, c.cmd); assert(c.cmd == ModifyCommand::PUSH); // only push valid for pack/unpack @@ -345,7 +345,7 @@ inline void AutoDeltaQueue::unpackDelta(ReadIterator &source) { using Archive::get; ModifyCommand c; - size_t skipCount, commandCount, targetBaselineCommandCount; + int32_t skipCount, commandCount, targetBaselineCommandCount; Archive::get(source, commandCount); Archive::get(source, targetBaselineCommandCount); @@ -359,7 +359,7 @@ inline void AutoDeltaQueue::unpackDelta(ReadIterator &source) if (skipCount > commandCount) skipCount = commandCount; - size_t i; + int32_t i; for (i = 0; i < skipCount; ++i) { Archive::get(source, c.cmd); diff --git a/external/ours/library/archive/src/shared/AutoDeltaSet.h b/external/ours/library/archive/src/shared/AutoDeltaSet.h index e413c21e7..67382f163 100644 --- a/external/ours/library/archive/src/shared/AutoDeltaSet.h +++ b/external/ours/library/archive/src/shared/AutoDeltaSet.h @@ -57,7 +57,7 @@ class AutoDeltaSet: public AutoDeltaContainer void packDelta(ByteStream &target) const; SetType const & get() const; - const size_t size() const; + const uint32_t size() const; bool empty() const; bool contains(ValueType const &t) const; const_iterator find(ValueType const &t) const; @@ -84,7 +84,7 @@ class AutoDeltaSet: public AutoDeltaContainer private: SetType m_set; - size_t m_baselineCommandCount; + uint32_t m_baselineCommandCount; mutable std::vector m_commands; std::pair *m_onChangedCallback; std::pair *m_onEraseCallback; @@ -301,7 +301,7 @@ inline void AutoDeltaSet::onInsert(ValueType const &value template inline void AutoDeltaSet::pack(ByteStream &target) const { - Archive::put(target, m_set.size()); + Archive::put(target, static_cast (m_set.size())); Archive::put(target, m_baselineCommandCount); for (typename SetType::const_iterator i = m_set.begin(); i != m_set.end(); ++i) put(target, *i); @@ -312,8 +312,8 @@ inline void AutoDeltaSet::pack(ByteStream &target) const template inline void AutoDeltaSet::pack(ByteStream &target, std::set const &data) { - Archive::put(target, data.size()); - Archive::put(target, static_cast(0)); // baselineCommandCount + Archive::put(target, static_cast (data.size())); + Archive::put(target, static_cast (0)); // baselineCommandCount for (typename std::set::const_iterator i = data.begin(); i != data.end(); ++i) put(target, *i); } @@ -323,7 +323,7 @@ inline void AutoDeltaSet::pack(ByteStream &target, std::s template inline void AutoDeltaSet::packDelta(ByteStream &target) const { - Archive::put(target, m_commands.size()); + Archive::put(target, static_cast (m_commands.size())); Archive::put(target, m_baselineCommandCount); for (typename std::vector::iterator i = m_commands.begin(); i != m_commands.end(); ++i) { @@ -402,7 +402,7 @@ inline bool AutoDeltaSet::empty() const //----------------------------------------------------------------------- template -inline const size_t AutoDeltaSet::size() const +inline const uint32_t AutoDeltaSet::size() const { return m_set.size(); } @@ -415,13 +415,13 @@ inline void AutoDeltaSet::unpack(ReadIterator &source) m_set.clear(); clearDelta(); - size_t commandCount; + int32_t commandCount; ValueType value; Archive::get(source, commandCount); Archive::get(source, m_baselineCommandCount); using Archive::get; - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { get(source, value); m_set.insert(value); @@ -436,13 +436,13 @@ template inline void AutoDeltaSet::unpack(ReadIterator &source, std::vector &data) { Command c; - size_t commandCount, targetBaselineCommandCount; + int32_t commandCount, targetBaselineCommandCount; Archive::get(source, commandCount); Archive::get(source, targetBaselineCommandCount); c.cmd = Command::INSERT; - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { Archive::get(source,c.value); data.push_back(c); @@ -455,12 +455,12 @@ template inline void AutoDeltaSet::unpackDelta(ReadIterator &source, std::vector &data) { Command c; - size_t commandCount, targetBaselineCommandCount; + int32_t commandCount, targetBaselineCommandCount; Archive::get(source, commandCount); Archive::get(source, targetBaselineCommandCount); - for (size_t i = 0 ; i < commandCount; ++i) + for (int32_t i = 0 ; i < commandCount; ++i) { Archive::get(source, c.cmd); switch (c.cmd) @@ -486,7 +486,7 @@ inline void AutoDeltaSet::unpackDelta(ReadIterator &sourc { using Archive::get; Command c; - size_t skipCount, commandCount, targetBaselineCommandCount; + uint32_t skipCount, commandCount, targetBaselineCommandCount; Archive::get(source, commandCount); Archive::get(source, targetBaselineCommandCount); @@ -503,7 +503,7 @@ inline void AutoDeltaSet::unpackDelta(ReadIterator &sourc if (skipCount > commandCount) skipCount = commandCount; - size_t i = 0; + uint32_t i = 0; for ( ; i < skipCount; ++i) { Archive::get(source, c.cmd); diff --git a/external/ours/library/archive/src/shared/AutoDeltaVector.h b/external/ours/library/archive/src/shared/AutoDeltaVector.h index 5d2d37bf8..d0115f30d 100755 --- a/external/ours/library/archive/src/shared/AutoDeltaVector.h +++ b/external/ours/library/archive/src/shared/AutoDeltaVector.h @@ -39,7 +39,7 @@ class AutoDeltaVector : public AutoDeltaContainer public: AutoDeltaVector(); - explicit AutoDeltaVector(size_t initialSize); + explicit AutoDeltaVector(uint32_t initialSize); ~AutoDeltaVector(); const ValueType & back () const; @@ -74,7 +74,7 @@ class AutoDeltaVector : public AutoDeltaContainer void setOnInsert (ObjectType * owner, void (ObjectType::*onInsert)(const unsigned int, const ValueType &)); void setOnSet (ObjectType * owner, void (ObjectType::*onSet)(const unsigned int, const ValueType &, const ValueType &)); - const size_t size () const; + const uint32_t size () const; bool empty () const; const ValueType & operator[] (const unsigned int element) const; @@ -91,7 +91,7 @@ class AutoDeltaVector : public AutoDeltaContainer private: std::vector v; - size_t baselineCommandCount; + uint32_t baselineCommandCount; mutable std::vector commands; std::pair * onChangedCallback; std::pair * onEraseCallback; @@ -120,7 +120,7 @@ onSetCallback(0) //----------------------------------------------------------------------- template -inline AutoDeltaVector::AutoDeltaVector(size_t initialSize) : +inline AutoDeltaVector::AutoDeltaVector(uint32_t initialSize) : AutoDeltaContainer(), v(initialSize), baselineCommandCount(0), @@ -366,7 +366,7 @@ inline void AutoDeltaVector::onSet(const unsigned int ele template inline void AutoDeltaVector::pack(ByteStream & target) const { - Archive::put(target, v.size()); + Archive::put(target, static_cast (v.size())); Archive::put(target, baselineCommandCount); typename std::vector::const_iterator i; for (i = v.begin(); i != v.end(); ++i) @@ -380,8 +380,8 @@ inline void AutoDeltaVector::pack(ByteStream & target) co template inline void AutoDeltaVector::pack(ByteStream & target, const std::vector & data) { - Archive::put(target, data.size()); - Archive::put(target, static_cast(0)); // baselineCommandCount + Archive::put(target, static_cast(data.size())); + Archive::put(target, static_cast(0)); // baselineCommandCount typename std::vector::const_iterator i; for (i = data.begin(); i != data.end(); ++i) { @@ -394,7 +394,7 @@ inline void AutoDeltaVector::pack(ByteStream & target, co template inline void AutoDeltaVector::packDelta(ByteStream & target) const { - Archive::put(target, commands.size()); + Archive::put(target, static_cast(commands.size())); Archive::put(target, baselineCommandCount); typename std::vector::iterator i; @@ -483,13 +483,13 @@ inline void AutoDeltaVector::resize(size_type n, ValueTyp { // expand the vector v.resize(n); - for (size_t i = size; i < n; ++i) + for (uint32_t i = size; i < n; ++i) set(i, x); } else if (size > n) { // contract the vector - for (size_t i = size - 1; i >= n; --i) + for (uint32_t i = size - 1; i >= n; --i) { erase(i); @@ -607,7 +607,7 @@ inline bool AutoDeltaVector::empty() const //----------------------------------------------------------------------- template -inline const size_t AutoDeltaVector::size() const +inline const uint32_t AutoDeltaVector::size() const { return v.size(); } @@ -622,13 +622,13 @@ inline void AutoDeltaVector::unpack(ReadIterator & source v.clear(); clearDelta(); - size_t commandCount; + uint32_t commandCount; ValueType value; Archive::get(source, commandCount); Archive::get(source, baselineCommandCount); - for (size_t i = 0; i < commandCount; ++i) + for (uint32_t i = 0; i < commandCount; ++i) { get(source, value); v.push_back(value); @@ -644,14 +644,14 @@ inline void AutoDeltaVector::unpack(ReadIterator & source { using Archive::get; // unpacking the whole kazaba - size_t commandCount; - size_t bcc; + uint32_t commandCount; + uint32_t bcc; Command c; Archive::get(source, commandCount); Archive::get(source, bcc); - for (size_t i = 0; i < commandCount; ++i) + for (uint32_t i = 0; i < commandCount; ++i) { get(source,c.value); c.index = static_cast(i); @@ -668,12 +668,12 @@ inline void AutoDeltaVector::unpackDelta(ReadIterator & s { using Archive::get; Command c; - size_t commandCount, targetBaselineCommandCount; + uint32_t commandCount, targetBaselineCommandCount; Archive::get(source, commandCount); Archive::get(source, targetBaselineCommandCount); - for (size_t i=0 ; i < commandCount; ++i) + for (uint32_t i=0 ; i < commandCount; ++i) { Archive::get(source, c.cmd); switch (c.cmd) @@ -708,7 +708,7 @@ inline void AutoDeltaVector::unpackDelta(ReadIterator & s { using Archive::get; Command c; - size_t skipCount, commandCount, targetBaselineCommandCount; + uint32_t skipCount, commandCount, targetBaselineCommandCount; Archive::get(source, commandCount); Archive::get(source, targetBaselineCommandCount); @@ -719,7 +719,7 @@ inline void AutoDeltaVector::unpackDelta(ReadIterator & s if (skipCount > commandCount) skipCount = commandCount; - size_t i; + uint32_t i; for (i = 0; i < skipCount; ++i) { Archive::get(source, c.cmd); @@ -727,7 +727,7 @@ inline void AutoDeltaVector::unpackDelta(ReadIterator & s Archive::get(source, c.index); if (c.cmd == Command::SETALL) { - for (unsigned int j = 0; j < c.index; ++j) + for (uint32_t j = 0; j < c.index; ++j) { ++i; get(source, c.value); diff --git a/external/ours/library/archive/src/shared/ByteStream.cpp b/external/ours/library/archive/src/shared/ByteStream.cpp index 4965bc8cf..6b16bf293 100755 --- a/external/ours/library/archive/src/shared/ByteStream.cpp +++ b/external/ours/library/archive/src/shared/ByteStream.cpp @@ -224,7 +224,7 @@ ByteStream &ByteStream::operator=(ByteStream const &rhs) @author Justin Randall */ -void ByteStream::get(void *target, ReadIterator &readIterator, const unsigned long int targetSize) const +void ByteStream::get(void *target, ReadIterator &readIterator, const uint32_t targetSize) const { if (data && readIterator.getReadPosition() + targetSize <= allocatedSize) { @@ -345,7 +345,7 @@ ByteStream::Data *ByteStream::Data::getNewData() void ByteStream::Data::releaseOldData(ByteStream::Data *oldData) { - assert((unsigned) reinterpret_cast(oldData) != 0xefefefefu); + assert(reinterpret_cast(oldData) != 0xefefefefefefefefu); if (oldData->size > 4096) delete oldData; diff --git a/external/ours/library/archive/src/shared/ByteStream.h b/external/ours/library/archive/src/shared/ByteStream.h index a94aeb36a..d40bb0902 100755 --- a/external/ours/library/archive/src/shared/ByteStream.h +++ b/external/ours/library/archive/src/shared/ByteStream.h @@ -9,6 +9,7 @@ #include #include +#include //--------------------------------------------------------------------- @@ -82,7 +83,7 @@ class ReadIterator bool operator == (const ReadIterator & other) const; bool operator != (const ReadIterator & other) const; void advance (const unsigned int distance); - void get (void * target, const unsigned long int readSize); + void get (void * target, const uint32_t readSize); const unsigned int getSize () const; const unsigned char * const getBuffer () const; const unsigned int getReadPosition () const; @@ -136,7 +137,7 @@ class ByteStream void setAllocatedSizeLimit(unsigned int limit); private: - void get(void * target, ReadIterator & readIterator, const unsigned long int readSize) const; + void get(void * target, ReadIterator & readIterator, const uint32_t readSize) const; void growToAtLeast(const unsigned int targetSize); void reAllocate(const unsigned int newSize); @@ -155,7 +156,7 @@ class ByteStream friend class ByteStream; friend class Archive::ReadIterator; unsigned char * buffer; - unsigned long size; + uint32_t size; private: struct DataFreeList { @@ -252,7 +253,7 @@ inline ReadIterator & ReadIterator::operator = (const ReadIterator & rhs) //--------------------------------------------------------------------- -inline void ReadIterator::get(void * target, const unsigned long int readSize) +inline void ReadIterator::get(void * target, const uint32_t readSize) { if(stream) { diff --git a/external/ours/library/crypto/CMakeLists.txt b/external/ours/library/crypto/CMakeLists.txt index 26724306d..13ad4e447 100644 --- a/external/ours/library/crypto/CMakeLists.txt +++ b/external/ours/library/crypto/CMakeLists.txt @@ -6,6 +6,9 @@ if(WIN32) add_definitions(/D_CRT_SECURE_NO_WARNINGS) endif() +add_definitions(-DCRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) +add_definitions(-DCRYPTOPP_DISABLE_SHANI) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) add_subdirectory(src) diff --git a/external/ours/library/crypto/src/CMakeLists.txt b/external/ours/library/crypto/src/CMakeLists.txt index 215b59675..b8a4bde24 100644 --- a/external/ours/library/crypto/src/CMakeLists.txt +++ b/external/ours/library/crypto/src/CMakeLists.txt @@ -3,11 +3,27 @@ set(SHARED_SOURCES shared/core/FirstCrypto.h + shared/original/algebra.cpp + shared/original/algebra.h + shared/original/algparam.cpp + shared/original/algparam.h + shared/original/allocate.cpp + shared/original/allocate.h + shared/original/asn.cpp + shared/original/asn.h shared/original/config.h + shared/original/cpu.cpp + shared/original/cpu.h shared/original/cryptlib.cpp shared/original/cryptlib.h shared/original/filters.cpp shared/original/filters.h + shared/original/fips140.cpp + shared/original/fips140.h + shared/original/hmac.cpp + shared/original/hmac.h + shared/original/integer.cpp + shared/original/integer.h shared/original/iterhash.cpp shared/original/iterhash.h shared/original/md5.cpp @@ -16,9 +32,34 @@ set(SHARED_SOURCES shared/original/misc.h shared/original/mqueue.cpp shared/original/mqueue.h + shared/original/nbtheory.cpp + shared/original/nbtheory.h + shared/original/osrng.cpp + shared/original/osrng.h + shared/original/pch.cpp + shared/original/pch.h + shared/original/pubkey.cpp + shared/original/pubkey.h shared/original/queue.cpp shared/original/queue.h + shared/original/rc2.cpp + shared/original/rc2.h + shared/original/rdtables.cpp + shared/original/rijndael.cpp + shared/original/rijndael.h + shared/original/rijndael_simd.cpp + shared/original/rng.cpp + shared/original/rng.h + shared/original/seckey.h + shared/original/sha.cpp + shared/original/sha.h + shared/original/sha3.cpp + shared/original/sha3.h + shared/original/shacal2.cpp + shared/original/shacal2.h + shared/original/sha_simd.cpp shared/original/smartptr.h + shared/original/sse_simd.cpp shared/original/tftables.cpp shared/original/twofish.cpp shared/original/twofish.h @@ -29,7 +70,6 @@ set(SHARED_SOURCES shared/wrapper/Hash.h shared/wrapper/MD5Hash.cpp shared/wrapper/MD5Hash.h - shared/wrapper/TwofishCrypt.cpp shared/wrapper/TwofishCrypt.h shared/wrapper/TwofishDecryptor.cpp shared/wrapper/TwofishDecryptor.h diff --git a/external/ours/library/crypto/src/shared/original/3way.cpp b/external/ours/library/crypto/src/shared/original/3way.cpp new file mode 100755 index 000000000..aecbaf011 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/3way.cpp @@ -0,0 +1,143 @@ +// 3way.cpp - modified by Wei Dai from Joan Daemen's 3way.c +// The original code and all modifications are in the public domain. + +#include "pch.h" +#include "3way.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void ThreeWay_TestInstantiations() +{ + ThreeWay::Encryption x1; + ThreeWay::Decryption x2; +} +#endif + +namespace +{ + const word32 START_E = 0x0b0b; // round constant of first encryption round + const word32 START_D = 0xb1b1; // round constant of first decryption round +} + +static inline word32 reverseBits(word32 a) +{ + a = ((a & 0xAAAAAAAA) >> 1) | ((a & 0x55555555) << 1); + a = ((a & 0xCCCCCCCC) >> 2) | ((a & 0x33333333) << 2); + return ((a & 0xF0F0F0F0) >> 4) | ((a & 0x0F0F0F0F) << 4); +} + +#define mu(a0, a1, a2) \ +{ \ + a1 = reverseBits(a1); \ + word32 t = reverseBits(a0); \ + a0 = reverseBits(a2); \ + a2 = t; \ +} + +#define pi_gamma_pi(a0, a1, a2) \ +{ \ + word32 b0, b2; \ + b2 = rotlConstant<1>(a2); \ + b0 = rotlConstant<22>(a0); \ + a0 = rotlConstant<1>(b0 ^ (a1|(~b2))); \ + a2 = rotlConstant<22>(b2 ^ (b0|(~a1))); \ + a1 ^= (b2|(~b0)); \ +} + +// thanks to Paulo Barreto for this optimized theta() +#define theta(a0, a1, a2) \ +{ \ + word32 b0, b1, c; \ + c = a0 ^ a1 ^ a2; \ + c = rotlConstant<16>(c) ^ rotlConstant<8>(c); \ + b0 = (a0 << 24) ^ (a2 >> 8) ^ (a1 << 8) ^ (a0 >> 24); \ + b1 = (a1 << 24) ^ (a0 >> 8) ^ (a2 << 8) ^ (a1 >> 24); \ + a0 ^= c ^ b0; \ + a1 ^= c ^ b1; \ + a2 ^= c ^ (b0 >> 16) ^ (b1 << 16); \ +} + +#define rho(a0, a1, a2) \ +{ \ + theta(a0, a1, a2); \ + pi_gamma_pi(a0, a1, a2); \ +} + +void ThreeWay::Base::UncheckedSetKey(const byte *uk, unsigned int length, const NameValuePairs ¶ms) +{ + AssertValidKeyLength(length); + + m_rounds = GetRoundsAndThrowIfInvalid(params, this); + + for (unsigned int i=0; i<3; i++) + m_k[i] = (word32)uk[4*i+3] | ((word32)uk[4*i+2]<<8) | ((word32)uk[4*i+1]<<16) | ((word32)uk[4*i]<<24); + + if (!IsForwardTransformation()) + { + theta(m_k[0], m_k[1], m_k[2]); + mu(m_k[0], m_k[1], m_k[2]); + m_k[0] = ByteReverse(m_k[0]); + m_k[1] = ByteReverse(m_k[1]); + m_k[2] = ByteReverse(m_k[2]); + } +} + +void ThreeWay::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + typedef BlockGetAndPut Block; + + word32 a0, a1, a2; + Block::Get(inBlock)(a0)(a1)(a2); + + word32 rc = START_E; + + for(unsigned i=0; i Block; + + word32 a0, a1, a2; + Block::Get(inBlock)(a0)(a1)(a2); + + word32 rc = START_D; + + mu(a0, a1, a2); + for(unsigned i=0; i, 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/external/ours/library/crypto/src/shared/original/GNUmakefile b/external/ours/library/crypto/src/shared/original/GNUmakefile new file mode 100755 index 000000000..6f6307106 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/GNUmakefile @@ -0,0 +1,1795 @@ + +########################################################### +##### System Attributes and Programs ##### +########################################################### + +# https://www.gnu.org/software/make/manual/make.html#Makefile-Conventions +# and https://www.gnu.org/prep/standards/standards.html + +SHELL = /bin/sh + +# If needed +TMPDIR ?= /tmp +# Used for feature tests +TOUT ?= a.out +TOUT := $(strip $(TOUT)) + +# Allow override for the cryptest.exe recipe. Change to +# ./libcryptopp.so or ./libcryptopp.dylib to suit your +# taste. https://github.com/weidai11/cryptopp/issues/866 +LINK_LIBRARY ?= libcryptopp.a +LINK_LIBRARY_PATH ?= ./ + +# Command and arguments +AR ?= ar +ARFLAGS ?= -cr # ar needs the dash on OpenBSD +RANLIB ?= ranlib + +CP ?= cp +MV ?= mv +RM ?= rm -f +GREP ?= grep +SED ?= sed +CHMOD ?= chmod +MKDIR ?= mkdir -p + +LN ?= ln -sf +LDCONF ?= /sbin/ldconfig -n + +# Solaris provides a non-Posix sed and grep at /usr/bin +# Solaris 10 is missing AR in /usr/bin +ifneq ($(wildcard /usr/xpg4/bin/grep),) + GREP := /usr/xpg4/bin/grep +endif +ifneq ($(wildcard /usr/xpg4/bin/sed),) + SED := /usr/xpg4/bin/sed +endif +ifneq ($(wildcard /usr/xpg4/bin/ar),) + AR := /usr/xpg4/bin/ar +endif + +# Clang is reporting armv8l-unknown-linux-gnueabihf +# for ARMv7 images on Aarch64 hardware. +MACHINEX := $(shell $(CXX) $(CXXFLAGS) -dumpmachine 2>/dev/null) +HOSTX := $(shell echo $(MACHINEX) | cut -f 1 -d '-') +ifeq ($(HOSTX),) + HOSTX := $(shell uname -m 2>/dev/null) +endif + +IS_X86 := $(shell echo "$(HOSTX)" | $(GREP) -v "64" | $(GREP) -i -c -E 'i.86|x86|i86') +IS_X64 := $(shell echo "$(HOSTX)" | $(GREP) -i -c -E '_64|d64') +IS_PPC32 := $(shell echo "$(HOSTX)" | $(GREP) -v "64" | $(GREP) -i -c -E 'ppc|power') +IS_PPC64 := $(shell echo "$(HOSTX)" | $(GREP) -i -c -E 'ppc64|powerpc64|power64') +IS_SPARC32 := $(shell echo "$(HOSTX)" | $(GREP) -v "64" | $(GREP) -i -c -E 'sun|sparc') +IS_SPARC64 := $(shell echo "$(HOSTX)" | $(GREP) -i -c -E 'sun|sparc64') +IS_ARM32 := $(shell echo "$(HOSTX)" | $(GREP) -v "64" | $(GREP) -i -c -E 'arm|armhf|armv7|eabihf|armv8') +IS_ARMV8 := $(shell echo "$(HOSTX)" | $(GREP) -i -c -E 'aarch32|aarch64|arm64') + +# Attempt to determine platform +SYSTEMX := $(shell $(CXX) $(CXXFLAGS) -dumpmachine 2>/dev/null) +ifeq ($(SYSTEMX),) + SYSTEMX := $(shell uname -s 2>/dev/null) +endif + +IS_LINUX := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "Linux") +IS_HURD := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c -E "GNU|Hurd") +IS_MINGW := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "MinGW") +IS_CYGWIN := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "Cygwin") +IS_DARWIN := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "Darwin") +IS_NETBSD := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "NetBSD") +IS_AIX := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "aix") +IS_SUN := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c -E "SunOS|Solaris") + +SUN_COMPILER := $(shell $(CXX) -V 2>&1 | $(GREP) -i -c -E 'CC: (Sun|Studio)') +GCC_COMPILER := $(shell $(CXX) --version 2>/dev/null | $(GREP) -v -E '(llvm|clang)' | $(GREP) -i -c -E '(gcc|g\+\+)') +XLC_COMPILER := $(shell $(CXX) -qversion 2>/dev/null |$(GREP) -i -c "IBM XL") +CLANG_COMPILER := $(shell $(CXX) --version 2>/dev/null | $(GREP) -i -c -E '(llvm|clang)') +INTEL_COMPILER := $(shell $(CXX) --version 2>/dev/null | $(GREP) -i -c '\(icc\)') + +# Enable shared object versioning for Linux and Solaris +HAS_SOLIB_VERSION ?= 0 +ifneq ($(IS_LINUX)$(IS_HURD)$(IS_SUN),000) + HAS_SOLIB_VERSION := 1 +endif + +# Formerly adhoc.cpp was created from adhoc.cpp.proto when needed. +ifeq ($(wildcard adhoc.cpp),) +$(shell cp adhoc.cpp.proto adhoc.cpp) +endif + +# Hack to skip CPU feature tests for some recipes +DETECT_FEATURES ?= 1 +ifeq ($(findstring -DCRYPTOPP_DISABLE_ASM,$(CXXFLAGS)),-DCRYPTOPP_DISABLE_ASM) + DETECT_FEATURES := 0 +else ifeq ($(findstring clean,$(MAKECMDGOALS)),clean) + DETECT_FEATURES := 0 +else ifeq ($(findstring distclean,$(MAKECMDGOALS)),distclean) + DETECT_FEATURES := 0 +else ifeq ($(findstring trim,$(MAKECMDGOALS)),trim) + DETECT_FEATURES := 0 +else ifeq ($(findstring zip,$(MAKECMDGOALS)),zip) + DETECT_FEATURES := 0 +endif + +# Strip out -Wall, -Wextra and friends for feature testing. FORTIFY_SOURCE is removed +# because it requires -O1 or higher, but we use -O0 to tame the optimizer. +# Always print testing flags since some tests always happen, like 64-bit. +TCXXFLAGS := $(filter-out -D_FORTIFY_SOURCE=% -M -MM -Wall -Wextra -Werror% -Wunused -Wconversion -Wp%, $(CPPFLAGS) $(CXXFLAGS)) +ifneq ($(strip $(TCXXFLAGS)),) + $(info Using testing flags: $(TCXXFLAGS)) +endif + +# TCOMMAND is used for just about all tests. Make will lazy-evaluate +# the variables when executed by $(shell $(TCOMMAND) ...). +TCOMMAND = $(CXX) $(TCXXFLAGS) $(TEXTRA) $(ZOPT) $(TOPT) $(TPROG) -o $(TOUT) + +# Fixup AIX +ifeq ($(IS_AIX),1) + TPROG = TestPrograms/test_64bit.cpp + TOPT = + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + IS_PPC64=1 + else + IS_PPC32=1 + endif +endif + +# Uncomment for debugging +# $(info Here's what we found... IS_X86: $(IS_X86), IS_X64: $(IS_X64), IS_ARM32: $(IS_ARM32), IS_ARMV8: $(IS_ARMV8)) + +########################################################### +##### General Variables ##### +########################################################### + +# Base CXXFLAGS used if the user did not specify them +ifeq ($(CXXFLAGS),) + ifeq ($(SUN_COMPILER),1) + CRYPTOPP_CXXFLAGS += -DNDEBUG -g -xO3 + ZOPT = -xO0 + else + CRYPTOPP_CXXFLAGS += -DNDEBUG -g2 -O3 + ZOPT = -O0 + endif +endif + +# Fix CXX on Cygwin 1.1.4 +ifeq ($(CXX),gcc) +CXX := g++ +endif + +# On ARM we may compile aes_armv4.S though the CC compiler +ifeq ($(GCC_COMPILER),1) + CC=gcc +else ifeq ($(CLANG_COMPILER),1) + CC=clang +endif + +# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html +ifeq ($(PREFIX),) + PREFIX = /usr/local + PC_PREFIX = /usr/local +else + PC_PREFIX = $(PREFIX) +endif +ifeq ($(LIBDIR),) + LIBDIR := $(PREFIX)/lib + PC_LIBDIR = $${prefix}/lib +else + PC_LIBDIR = $(LIBDIR) +endif +ifeq ($(DATADIR),) + DATADIR := $(PREFIX)/share + PC_DATADIR = $${prefix}/share +else + PC_DATADIR = $(DATADIR) +endif +ifeq ($(INCLUDEDIR),) + INCLUDEDIR := $(PREFIX)/include + PC_INCLUDEDIR = $${prefix}/include +else + PC_INCLUDEDIR = $(INCLUDEDIR) +endif +ifeq ($(BINDIR),) + BINDIR := $(PREFIX)/bin +endif + +# We honor ARFLAGS, but the "v" option used by default causes a noisy make +ifeq ($(ARFLAGS),rv) +ARFLAGS = r +endif + +# Original MinGW targets Win2k by default, but lacks proper Win2k support +# if target Windows version is not specified, use Windows XP instead +ifeq ($(IS_MINGW),1) +ifeq ($(findstring -D_WIN32_WINNT,$(CXXFLAGS)),) +ifeq ($(findstring -D_WIN32_WINDOWS,$(CXXFLAGS)),) +ifeq ($(findstring -DWINVER,$(CXXFLAGS)),) +ifeq ($(findstring -DNTDDI_VERSION,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -D_WIN32_WINNT=0x0501 +endif # NTDDI_VERSION +endif # WINVER +endif # _WIN32_WINDOWS +endif # _WIN32_WINNT +endif # IS_MINGW + +# Newlib needs _XOPEN_SOURCE=600 for signals +TPROG = TestPrograms/test_newlib.cpp +TOPT = +HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) +ifeq ($(strip $(HAVE_OPT)),0) + ifeq ($(findstring -D_XOPEN_SOURCE,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -D_XOPEN_SOURCE=600 + endif +endif + +########################################################### +##### X86/X32/X64 Options ##### +########################################################### + +ifneq ($(IS_X86)$(IS_X64)$(IS_MINGW),000) +ifeq ($(DETECT_FEATURES),1) + + ifeq ($(SUN_COMPILER),1) + SSE2_FLAG = -xarch=sse2 + SSE3_FLAG = -xarch=sse3 + SSSE3_FLAG = -xarch=ssse3 + SSE41_FLAG = -xarch=sse4_1 + SSE42_FLAG = -xarch=sse4_2 + CLMUL_FLAG = -xarch=aes + AESNI_FLAG = -xarch=aes + AVX_FLAG = -xarch=avx + AVX2_FLAG = -xarch=avx2 + SHANI_FLAG = -xarch=sha + else + SSE2_FLAG = -msse2 + SSE3_FLAG = -msse3 + SSSE3_FLAG = -mssse3 + SSE41_FLAG = -msse4.1 + SSE42_FLAG = -msse4.2 + CLMUL_FLAG = -mpclmul + AESNI_FLAG = -maes + AVX_FLAG = -mavx + AVX2_FLAG = -mavx2 + SHANI_FLAG = -msha + endif + + # Tell MacPorts and Homebrew GCC to use Clang integrated assembler + # Intel-based Macs. http://github.com/weidai11/cryptopp/issues/190 + ifneq ($(IS_DARWIN),0) + ifeq ($(findstring -Wa,-q,$(CXXFLAGS)),) + TPROG = TestPrograms/test_cxx.cpp + TOPT = -Wa,-q + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + TEXTRA += -Wa,-q + CRYPTOPP_CXXFLAGS += -Wa,-q + endif + endif + endif + + TPROG = TestPrograms/test_x86_sse2.cpp + TOPT = $(SSE2_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CHACHA_FLAG = $(SSE2_FLAG) + SUN_LDFLAGS += $(SSE2_FLAG) + else + # Make does not have useful debugging facilities. Show the user + # what happened by compiling again without the pipe. + $(info Running make again to see what failed) + $(info $(shell $(TCOMMAND))) + SSE2_FLAG = + endif + + ifeq ($(SSE2_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ASM + endif + + # Need SSE2 or higher for these tests + ifneq ($(SSE2_FLAG),) + + TPROG = TestPrograms/test_x86_ssse3.cpp + TOPT = $(SSSE3_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + ARIA_FLAG = $(SSSE3_FLAG) + CHAM_FLAG = $(SSSE3_FLAG) + KECCAK_FLAG = $(SSSE3_FLAG) + LEA_FLAG = $(SSSE3_FLAG) + LSH256_FLAG = $(SSSE3_FLAG) + LSH512_FLAG = $(SSSE3_FLAG) + SIMON128_FLAG = $(SSSE3_FLAG) + SPECK128_FLAG = $(SSSE3_FLAG) + SUN_LDFLAGS += $(SSSE3_FLAG) + else + SSSE3_FLAG = + endif + + # The first Apple MacBooks were Core2's with SSE4.1 + ifneq ($(IS_DARWIN),0) + # Add SSE2 algo's here as required + # They get a free upgrade + endif + + TPROG = TestPrograms/test_x86_sse41.cpp + TOPT = $(SSE41_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + BLAKE2B_FLAG = $(SSE41_FLAG) + BLAKE2S_FLAG = $(SSE41_FLAG) + SUN_LDFLAGS += $(SSE41_FLAG) + else + SSE41_FLAG = + endif + + TPROG = TestPrograms/test_x86_sse42.cpp + TOPT = $(SSE42_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CRC_FLAG = $(SSE42_FLAG) + SUN_LDFLAGS += $(SSE42_FLAG) + else + SSE42_FLAG = + endif + + TPROG = TestPrograms/test_x86_clmul.cpp + TOPT = $(CLMUL_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + GCM_FLAG = $(SSSE3_FLAG) $(CLMUL_FLAG) + GF2N_FLAG = $(CLMUL_FLAG) + SUN_LDFLAGS += $(CLMUL_FLAG) + else + CLMUL_FLAG = + endif + + TPROG = TestPrograms/test_x86_aes.cpp + TOPT = $(AESNI_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + AES_FLAG = $(SSE41_FLAG) $(AESNI_FLAG) + SM4_FLAG = $(SSSE3_FLAG) $(AESNI_FLAG) + SUN_LDFLAGS += $(AESNI_FLAG) + else + AESNI_FLAG = + endif + + TPROG = TestPrograms/test_x86_avx.cpp + TOPT = $(AVX_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + # XXX_FLAG = $(AVX_FLAG) + SUN_LDFLAGS += $(AVX_FLAG) + else + AVX_FLAG = + endif + + TPROG = TestPrograms/test_x86_avx2.cpp + TOPT = $(AVX2_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CHACHA_AVX2_FLAG = $(AVX2_FLAG) + LSH256_AVX2_FLAG = $(AVX2_FLAG) + LSH512_AVX2_FLAG = $(AVX2_FLAG) + SUN_LDFLAGS += $(AVX2_FLAG) + else + AVX2_FLAG = + endif + + TPROG = TestPrograms/test_x86_sha.cpp + TOPT = $(SHANI_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SHA_FLAG = $(SSE42_FLAG) $(SHANI_FLAG) + SUN_LDFLAGS += $(SHANI_FLAG) + else + SHANI_FLAG = + endif + + ifeq ($(SUN_COMPILER),1) + CRYPTOPP_LDFLAGS += $(SUN_LDFLAGS) + endif + + ifeq ($(SSE3_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_SSE3 + else ifeq ($(SSSE3_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_SSSE3 + else ifeq ($(SSE41_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_SSE4 + else ifeq ($(SSE42_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_SSE4 + endif + + ifneq ($(SSE42_FLAG),) + # Unusual GCC/Clang on Macports. It assembles AES, but not CLMUL. + # test_x86_clmul.s:15: no such instruction: 'pclmulqdq $0, %xmm1,%xmm0' + ifeq ($(CLMUL_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_CLMUL + endif + ifeq ($(AESNI_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_AESNI + endif + + ifeq ($(AVX_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_AVX + else ifeq ($(AVX2_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_AVX2 + endif + # SHANI independent of AVX per GH #1045 + ifeq ($(SHANI_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_SHANI + endif + endif + + # Drop to SSE2 if available + ifeq ($(GCM_FLAG),) + GCM_FLAG = $(SSE2_FLAG) + endif + + # Most Clang cannot handle mixed asm with positional arguments, where the + # body is Intel style with no prefix and the templates are AT&T style. + # Also see https://bugs.llvm.org/show_bug.cgi?id=39895 . + + # CRYPTOPP_DISABLE_MIXED_ASM is now being added in config_asm.h for all + # Clang compilers. This test will need to be re-enabled if Clang fixes it. + #TPROG = TestPrograms/test_asm_mixed.cpp + #TOPT = + #HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + #ifneq ($(strip $(HAVE_OPT)),0) + # CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_MIXED_ASM + #endif + + # SSE2_FLAGS + endif +# DETECT_FEATURES +endif + +ifneq ($(INTEL_COMPILER),0) + CRYPTOPP_CXXFLAGS += -wd68 -wd186 -wd279 -wd327 -wd161 -wd3180 + + ICC111_OR_LATER := $(shell $(CXX) --version 2>&1 | $(GREP) -c -E "\(ICC\) ([2-9][0-9]|1[2-9]|11\.[1-9])") + ifeq ($(ICC111_OR_LATER),0) + # "internal error: backend signals" occurs on some x86 inline assembly with ICC 9 and + # some x64 inline assembly with ICC 11.0. If you want to use Crypto++'s assembly code + # with ICC, try enabling it on individual files + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ASM + endif +endif + +# Allow use of "/" operator for GNU Assembler. +# http://sourceware.org/bugzilla/show_bug.cgi?id=4572 +ifeq ($(findstring -DCRYPTOPP_DISABLE_ASM,$(CXXFLAGS)),) + ifeq ($(IS_SUN)$(GCC_COMPILER),11) + CRYPTOPP_CXXFLAGS += -Wa,--divide + endif +endif + +# IS_X86, IS_X32 and IS_X64 +endif + +########################################################### +##### ARM A-32 and NEON ##### +########################################################### + +ifneq ($(IS_ARM32),0) +ifeq ($(DETECT_FEATURES),1) + + # Clang needs an option to include + TPROG = TestPrograms/test_arm_neon_header.cpp + TOPT = -DCRYPTOPP_ARM_NEON_HEADER=1 -march=armv7-a -mfpu=neon + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + TEXTRA += -DCRYPTOPP_ARM_NEON_HEADER=1 + endif + + TPROG = TestPrograms/test_arm_neon.cpp + TOPT = -march=armv7-a -mfpu=neon + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + NEON_FLAG = -march=armv7-a -mfpu=neon + ARIA_FLAG = -march=armv7-a -mfpu=neon + GCM_FLAG = -march=armv7-a -mfpu=neon + BLAKE2B_FLAG = -march=armv7-a -mfpu=neon + BLAKE2S_FLAG = -march=armv7-a -mfpu=neon + CHACHA_FLAG = -march=armv7-a -mfpu=neon + CHAM_FLAG = -march=armv7-a -mfpu=neon + LEA_FLAG = -march=armv7-a -mfpu=neon + SIMON128_FLAG = -march=armv7-a -mfpu=neon + SPECK128_FLAG = -march=armv7-a -mfpu=neon + SM4_FLAG = -march=armv7-a -mfpu=neon + else + # Make does not have useful debugging facilities. Show the user + # what happened by compiling again without the pipe. + $(info Running make again to see what failed) + $(info $(shell $(TCOMMAND))) + NEON_FLAG = + endif + + ifeq ($(NEON_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ASM + endif + +# DETECT_FEATURES +endif +# IS_ARM32 +endif + +########################################################### +##### Aach32 and Aarch64 ##### +########################################################### + +ifneq ($(IS_ARMV8),0) +ifeq ($(DETECT_FEATURES),1) + + TPROG = TestPrograms/test_arm_neon_header.cpp + TOPT = -DCRYPTOPP_ARM_NEON_HEADER=1 + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + TEXTRA += -DCRYPTOPP_ARM_NEON_HEADER=1 + endif + + TPROG = TestPrograms/test_arm_acle_header.cpp + TOPT = -DCRYPTOPP_ARM_ACLE_HEADER=1 -march=armv8-a + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + TEXTRA += -DCRYPTOPP_ARM_ACLE_HEADER=1 + endif + + TPROG = TestPrograms/test_arm_asimd.cpp + TOPT = -march=armv8-a + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + ASIMD_FLAG = -march=armv8-a + ARIA_FLAG = -march=armv8-a + BLAKE2B_FLAG = -march=armv8-a + BLAKE2S_FLAG = -march=armv8-a + CHACHA_FLAG = -march=armv8-a + CHAM_FLAG = -march=armv8-a + LEA_FLAG = -march=armv8-a + NEON_FLAG = -march=armv8-a + SIMON128_FLAG = -march=armv8-a + SPECK128_FLAG = -march=armv8-a + SM4_FLAG = -march=armv8-a + else + # Make does not have useful debugging facilities. Show the user + # what happened by compiling again without the pipe. + $(info Running make again to see what failed) + $(info $(shell $(TCOMMAND))) + ASIMD_FLAG = + endif + + ifeq ($(ASIMD_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ASM + endif + + ifneq ($(ASIMD_FLAG),) + TPROG = TestPrograms/test_arm_crc.cpp + TOPT = -march=armv8-a+crc + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CRC_FLAG = -march=armv8-a+crc + else + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_CRC32 + endif + + TPROG = TestPrograms/test_arm_aes.cpp + TOPT = -march=armv8-a+crypto + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + AES_FLAG = -march=armv8-a+crypto + else + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_AES + endif + + TPROG = TestPrograms/test_arm_pmull.cpp + TOPT = -march=armv8-a+crypto + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + GCM_FLAG = -march=armv8-a+crypto + GF2N_FLAG = -march=armv8-a+crypto + else + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_PMULL + endif + + TPROG = TestPrograms/test_arm_sha1.cpp + TOPT = -march=armv8-a+crypto + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SHA_FLAG = -march=armv8-a+crypto + else + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SHA1 + endif + + TPROG = TestPrograms/test_arm_sha256.cpp + TOPT = -march=armv8-a+crypto + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SHA_FLAG = -march=armv8-a+crypto + else + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SHA2 + endif + + TPROG = TestPrograms/test_arm_sm3.cpp + TOPT = -march=armv8.4-a+sm3 + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SM3_FLAG = -march=armv8.4-a+sm3 + SM4_FLAG = -march=armv8.4-a+sm3 + else + #CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SM3 + #CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SM4 + endif + + TPROG = TestPrograms/test_arm_sha3.cpp + TOPT = -march=armv8.4-a+sha3 + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SHA3_FLAG = -march=armv8.4-a+sha3 + else + #CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SHA3 + endif + + TPROG = TestPrograms/test_arm_sha512.cpp + TOPT = -march=armv8.4-a+sha512 + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SHA512_FLAG = -march=armv8.4-a+sha512 + else + #CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SHA512 + endif + + # ASIMD_FLAG + endif + +# DETECT_FEATURES +endif +# IS_ARMV8 +endif + +########################################################### +##### PowerPC ##### +########################################################### + +# PowerPC and PowerPC64. Altivec is available with POWER4 with GCC and +# POWER6 with XLC. The tests below are crafted for IBM XLC and the LLVM +# front-end. XLC/LLVM only supplies POWER8 so we have to set the flags for +# XLC/LLVM to POWER8. I've got a feeling LLVM is going to cause trouble. + +ifneq ($(IS_PPC32)$(IS_PPC64),00) +ifeq ($(DETECT_FEATURES),1) + + # IBM XL C/C++ has the -qaltivec flag really screwed up. We can't seem + # to get it enabled without an -qarch= option. And -qarch= produces an + # error on later versions of the compiler. The only thing that seems + # to work consistently is -qarch=auto. -qarch=auto is equivalent to + # GCC's -march=native, which we don't really want. + + # XLC requires -qaltivec in addition to Arch or CPU option + ifeq ($(XLC_COMPILER),1) + # POWER9_FLAG = -qarch=pwr9 -qaltivec + POWER8_FLAG = -qarch=pwr8 -qaltivec + POWER7_VSX_FLAG = -qarch=pwr7 -qvsx -qaltivec + POWER7_PWR_FLAG = -qarch=pwr7 -qaltivec + ALTIVEC_FLAG = -qarch=auto -qaltivec + else + # POWER9_FLAG = -mcpu=power9 + POWER8_FLAG = -mcpu=power8 + POWER7_VSX_FLAG = -mcpu=power7 -mvsx + POWER7_PWR_FLAG = -mcpu=power7 + ALTIVEC_FLAG = -maltivec + endif + + # GCC 10 is giving us trouble in CPU_ProbePower9() and + # CPU_ProbeDARN(). GCC is generating POWER9 instructions + # on POWER8 for ppc_power9.cpp. The compiler folks did + # not think through the consequences of requiring us to + # use -mcpu=power9 to unlock the ISA. Epic fail. + # https:#github.com/weidai11/cryptopp/issues/986 + POWER9_FLAG = + + # XLC with LLVM front-ends failed to define XLC defines. + #ifeq ($(findstring -qxlcompatmacros,$(CXXFLAGS)),) + # TPROG = TestPrograms/test_ppc_altivec.cpp + # TOPT = -qxlcompatmacros + # HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + # ifeq ($(strip $(HAVE_OPT)),0) + # CRYPTOPP_CXXFLAGS += -qxlcompatmacros + # endif + #endif + + ##################################################################### + # Looking for a POWER9 option + + #TPROG = TestPrograms/test_ppc_power9.cpp + #TOPT = $(POWER9_FLAG) + #HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + #ifeq ($(strip $(HAVE_OPT)),0) + # DARN_FLAG = $(POWER9_FLAG) + #else + # POWER9_FLAG = + #endif + + ##################################################################### + # Looking for a POWER8 option + + TPROG = TestPrograms/test_ppc_power8.cpp + TOPT = $(POWER8_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + AES_FLAG = $(POWER8_FLAG) + BLAKE2B_FLAG = $(POWER8_FLAG) + CRC_FLAG = $(POWER8_FLAG) + GCM_FLAG = $(POWER8_FLAG) + GF2N_FLAG = $(POWER8_FLAG) + LEA_FLAG = $(POWER8_FLAG) + SHA_FLAG = $(POWER8_FLAG) + SHACAL2_FLAG = $(POWER8_FLAG) + else + POWER8_FLAG = + endif + + ##################################################################### + # Looking for a POWER7 option + + # GCC needs -mvsx for Power7 to enable 64-bit vector elements. + # XLC provides 64-bit vector elements without an option. + + TPROG = TestPrograms/test_ppc_power7.cpp + TOPT = $(POWER7_VSX_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + POWER7_FLAG = $(POWER7_VSX_FLAG) + else + TPROG = TestPrograms/test_ppc_power7.cpp + TOPT = $(POWER7_PWR_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + POWER7_FLAG = $(POWER7_PWR_FLAG) + else + POWER7_FLAG = + endif + endif + + ##################################################################### + # Looking for an Altivec option + + TPROG = TestPrograms/test_ppc_altivec.cpp + TOPT = $(ALTIVEC_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + ALTIVEC_FLAG := $(ALTIVEC_FLAG) + else + # Make does not have useful debugging facilities. Show the user + # what happened by compiling again without the pipe. + $(info Running make again to see what failed) + $(info $(shell $(TCOMMAND))) + ALTIVEC_FLAG = + endif + + ifneq ($(ALTIVEC_FLAG),) + BLAKE2S_FLAG = $(ALTIVEC_FLAG) + CHACHA_FLAG = $(ALTIVEC_FLAG) + SPECK128_FLAG = $(ALTIVEC_FLAG) + SIMON128_FLAG = $(ALTIVEC_FLAG) + endif + + ##################################################################### + # Fixups for algorithms that can drop to a lower ISA, if needed + + # Drop to Altivec if higher Power is not available + ifneq ($(ALTIVEC_FLAG),) + ifeq ($(GCM_FLAG),) + GCM_FLAG = $(ALTIVEC_FLAG) + endif + endif + + ##################################################################### + # Fixups for missing ISAs + + ifeq ($(ALTIVEC_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ALTIVEC + else ifeq ($(POWER7_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_POWER7 + else ifeq ($(POWER8_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_POWER8 + #else ifeq ($(POWER9_FLAG),) + # CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_POWER9 + endif + +# DETECT_FEATURES +endif + +# IBM XL C++ compiler +ifeq ($(XLC_COMPILER),1) + ifeq ($(findstring -qmaxmem,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -qmaxmem=-1 + endif + # http://www-01.ibm.com/support/docview.wss?uid=swg21007500 + ifeq ($(findstring -qrtti,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -qrtti + endif +endif + +# IS_PPC32, IS_PPC64 +endif + +########################################################### +##### Common ##### +########################################################### + +# Add -fPIC for targets *except* X86, X32, Cygwin or MinGW +ifeq ($(IS_X86)$(IS_CYGWIN)$(IS_MINGW),000) + ifeq ($(findstring -fpic,$(CXXFLAGS))$(findstring -fPIC,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -fPIC + endif +endif + +# Use -pthread whenever it is available. See http://www.hpl.hp.com/techreports/2004/HPL-2004-209.pdf +# http://stackoverflow.com/questions/2127797/gcc-significance-of-pthread-flag-when-compiling +ifeq ($(DETECT_FEATURES),1) + ifeq ($(XLC_COMPILER),1) + ifeq ($(findstring -qthreaded,$(CXXFLAGS)),) + TPROG = TestPrograms/test_pthreads.cpp + TOPT = -qthreaded + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CRYPTOPP_CXXFLAGS += -qthreaded + endif # CRYPTOPP_CXXFLAGS + endif # qthreaded + else + ifeq ($(findstring -pthread,$(CXXFLAGS)),) + TPROG = TestPrograms/test_pthreads.cpp + TOPT = -pthread + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CRYPTOPP_CXXFLAGS += -pthread + endif # CRYPTOPP_CXXFLAGS + endif # pthread + endif # XLC/GCC and friends +endif # DETECT_FEATURES + +# Remove -fPIC if present. SunCC use -KPIC, and needs the larger GOT table +# https://docs.oracle.com/cd/E19205-01/819-5267/bkbaq/index.html +ifeq ($(SUN_COMPILER),1) + CRYPTOPP_CXXFLAGS := $(subst -fPIC,-KPIC,$(CRYPTOPP_CXXFLAGS)) + CRYPTOPP_CXXFLAGS := $(subst -fpic,-KPIC,$(CRYPTOPP_CXXFLAGS)) +endif + +# Remove -fPIC if present. IBM XL C++ uses -qpic +ifeq ($(XLC_COMPILER),1) + CRYPTOPP_CXXFLAGS := $(subst -fPIC,-qpic,$(CRYPTOPP_CXXFLAGS)) + CRYPTOPP_CXXFLAGS := $(subst -fpic,-qpic,$(CRYPTOPP_CXXFLAGS)) +endif + +# Disable IBM XL C++ "1500-036: (I) The NOSTRICT option (default at OPT(3)) +# has the potential to alter the semantics of a program." +ifeq ($(XLC_COMPILER),1) + TPROG = TestPrograms/test_cxx.cpp + TOPT = -qsuppress=1500-036 + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CRYPTOPP_CXXFLAGS += -qsuppress=1500-036 + endif # -qsuppress +endif # IBM XL C++ compiler + +# libc++ is LLVM's standard C++ library. If we add libc++ +# here then all user programs must use it too. The open +# question is, which choice is easier on users? +ifneq ($(IS_DARWIN),0) + CXX ?= c++ + # CRYPTOPP_CXXFLAGS += -stdlib=libc++ + ifeq ($(findstring -fno-common,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -fno-common + endif + IS_APPLE_LIBTOOL=$(shell libtool -V 2>&1 | $(GREP) -i -c 'Apple') + ifeq ($(IS_APPLE_LIBTOOL),1) + AR = libtool + else + AR = /usr/bin/libtool + endif + ARFLAGS = -static -o +endif + +# Add -xregs=no%appl SPARC. SunCC should not use certain registers in library code. +# https://docs.oracle.com/cd/E18659_01/html/821-1383/bkamt.html +ifneq ($(IS_SPARC32)$(IS_SPARC64),00) + ifeq ($(SUN_COMPILER),1) + ifeq ($(findstring -xregs=no%appl,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -xregs=no%appl + endif # -xregs + endif # SunCC + ifeq ($(GCC_COMPILER),1) + ifeq ($(findstring -mno-app-regs,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -mno-app-regs + endif # no-app-regs + endif # GCC +endif # Sparc + +# Add -pipe for everything except IBM XL C++, SunCC and ARM. +# Allow ARM-64 because they seems to have >1 GB of memory +ifeq ($(XLC_COMPILER)$(SUN_COMPILER)$(IS_ARM32),000) + ifeq ($(findstring -save-temps,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -pipe + endif +endif + +# For SunOS, create a Mapfile that allows our object files +# to contain additional bits (like SSE4 and AES on old Xeon) +# http://www.oracle.com/technetwork/server-storage/solaris/hwcap-modification-139536.html +ifeq ($(IS_SUN)$(SUN_COMPILER),11) + ifneq ($(IS_X86)$(IS_X64),00) + ifeq ($(findstring -DCRYPTOPP_DISABLE_ASM,$(CRYPTOPP_CXXFLAGS) $(CXXFLAGS)),) + CRYPTOPP_LDFLAGS += -M cryptopp.mapfile + endif # No CRYPTOPP_DISABLE_ASM + endif # X86/X32/X64 +endif # SunOS + +ifneq ($(IS_LINUX)$(IS_HURD),00) + ifeq ($(findstring -fopenmp,$(CXXFLAGS)),-fopenmp) + ifeq ($(findstring -lgomp,$(LDLIBS)),) + LDLIBS += -lgomp + endif # LDLIBS + endif # OpenMP +endif # IS_LINUX or IS_HURD + +# Add -errtags=yes to get the name for a warning suppression +ifneq ($(SUN_COMPILER),0) # override flags for CC Sun C++ compiler +# Add to all Solaris +CRYPTOPP_CXXFLAGS += -template=no%extdef +SUN_CC10_BUGGY := $(shell $(CXX) -V 2>&1 | $(GREP) -c -E "CC: Sun .* 5\.10 .* (2009|2010/0[1-4])") +ifneq ($(SUN_CC10_BUGGY),0) +# -DCRYPTOPP_INCLUDE_VECTOR_CC is needed for Sun Studio 12u1 Sun C++ 5.10 SunOS_i386 128229-02 2009/09/21 +# and was fixed in May 2010. Remove it if you get "already had a body defined" errors in vector.cc +CRYPTOPP_CXXFLAGS += -DCRYPTOPP_INCLUDE_VECTOR_CC +endif +AR = $(CXX) +ARFLAGS = -xar -o +RANLIB = true +endif + +# No ASM for Travis testing +ifeq ($(findstring no-asm,$(MAKECMDGOALS)),no-asm) + ifeq ($(findstring -DCRYPTOPP_DISABLE_ASM,$(CRYPTOPP_CXXFLAGS) $(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_ASM + endif # CRYPTOPP_CXXFLAGS +endif # No ASM + +# Native build testing. Issue 'make native'. +ifeq ($(findstring native,$(MAKECMDGOALS)),native) + NATIVE_OPT = + + # Try GCC and compatibles first + TPROG = TestPrograms/test_cxx.cpp + TOPT = -march=native + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + NATIVE_OPT = -march=native + endif # NATIVE_OPT + + # And tune + ifeq ($(NATIVE_OPT),) + TOPT = -mtune=native + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + NATIVE_OPT = -mtune=native + endif # NATIVE_OPT + endif + + # Try SunCC next + ifeq ($(NATIVE_OPT),) + TOPT = -native + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + NATIVE_OPT = -native + endif # NATIVE_OPT + endif + + ifneq ($(NATIVE_OPT),) + CRYPTOPP_CXXFLAGS += $(NATIVE_OPT) + endif + +endif # Native + +# Undefined Behavior Sanitizer (UBsan) testing. Issue 'make ubsan'. +ifeq ($(findstring ubsan,$(MAKECMDGOALS)),ubsan) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-g%=-g3) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-O%=-O1) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-xO%=-xO1) + ifeq ($(findstring -fsanitize=undefined,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -fsanitize=undefined + endif # CRYPTOPP_CXXFLAGS + ifeq ($(findstring -DCRYPTOPP_COVERAGE,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_COVERAGE + endif # CRYPTOPP_CXXFLAGS +endif # UBsan + +# Address Sanitizer (Asan) testing. Issue 'make asan'. +ifeq ($(findstring asan,$(MAKECMDGOALS)),asan) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-g%=-g3) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-O%=-O1) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-xO%=-xO1) + ifeq ($(findstring -fsanitize=address,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -fsanitize=address + endif # CRYPTOPP_CXXFLAGS + ifeq ($(findstring -DCRYPTOPP_COVERAGE,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_COVERAGE + endif # CRYPTOPP_CXXFLAGS + ifeq ($(findstring -fno-omit-frame-pointer,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -fno-omit-frame-pointer + endif # CRYPTOPP_CXXFLAGS +endif # Asan + +# LD gold linker testing. Triggered by 'LD=ld.gold'. +ifeq ($(findstring ld.gold,$(LD)),ld.gold) + ifeq ($(findstring -fuse-ld=gold,$(CXXFLAGS)),) + LD_GOLD = $(shell command -v ld.gold) + ELF_FORMAT := $(shell file $(LD_GOLD) 2>&1 | cut -d":" -f 2 | $(GREP) -i -c "elf") + ifneq ($(ELF_FORMAT),0) + CRYPTOPP_LDFLAGS += -fuse-ld=gold + endif # ELF/ELF64 + endif # CXXFLAGS +endif # Gold + +# lcov code coverage. Issue 'make coverage'. +ifneq ($(filter lcov coverage,$(MAKECMDGOALS)),) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-g%=-g3) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-O%=-O1) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-xO%=-xO1) + ifeq ($(findstring -DCRYPTOPP_COVERAGE,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_COVERAGE + endif # CRYPTOPP_COVERAGE + ifeq ($(findstring -coverage,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -coverage + endif # -coverage +endif # GCC code coverage + +# gcov code coverage for Travis. Issue 'make codecov'. +ifneq ($(filter gcov codecov,$(MAKECMDGOALS)),) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-g%=-g3) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-O%=-O1) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-xO%=-xO1) + ifeq ($(findstring -DCRYPTOPP_COVERAGE,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_COVERAGE + endif # CRYPTOPP_COVERAGE + ifeq ($(findstring -coverage,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -coverage + endif # -coverage +endif # GCC code coverage + +# Valgrind testing. Issue 'make valgrind'. +ifneq ($(filter valgrind,$(MAKECMDGOALS)),) + # Tune flags; see http://valgrind.org/docs/manual/quick-start.html + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-g%=-g3) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-O%=-O1) + CRYPTOPP_CXXFLAGS := $(CRYPTOPP_CXXFLAGS:-xO%=-xO1) + ifeq ($(findstring -DCRYPTOPP_COVERAGE,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_COVERAGE + endif # -DCRYPTOPP_COVERAGE +endif # Valgrind + +# Debug testing on GNU systems. Triggered by -DDEBUG. +# Newlib test due to http://sourceware.org/bugzilla/show_bug.cgi?id=20268 +ifneq ($(filter -DDEBUG -DDEBUG=1,$(CXXFLAGS)),) + TPROG = TestPrograms/test_cxx.cpp + TOPT = + USING_GLIBCXX := $(shell $(CXX)$(CXXFLAGS) -E $(TPROG) -c 2>&1 | $(GREP) -i -c "__GLIBCXX__") + ifneq ($(USING_GLIBCXX),0) + ifeq ($(HAS_NEWLIB),0) + ifeq ($(findstring -D_GLIBCXX_DEBUG,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -D_GLIBCXX_DEBUG + endif # CRYPTOPP_CXXFLAGS + endif # HAS_NEWLIB + endif # USING_GLIBCXX + + ifeq ($(XLC_COMPILER),1) + TPROG = TestPrograms/test_cxx.cpp + TOPT = -qheapdebug -qro + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CRYPTOPP_CXXFLAGS += -qheapdebug -qro + endif # CRYPTOPP_CXXFLAGS + endif # XLC_COMPILER +endif # Debug build + +# Dead code stripping. Issue 'make lean'. +ifeq ($(findstring lean,$(MAKECMDGOALS)),lean) + ifeq ($(findstring -ffunction-sections,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -ffunction-sections + endif # CRYPTOPP_CXXFLAGS + ifeq ($(findstring -fdata-sections,$(CXXFLAGS)),) + CRYPTOPP_CXXFLAGS += -fdata-sections + endif # CRYPTOPP_CXXFLAGS + ifneq ($(IS_DARWIN),0) + ifeq ($(findstring -Wl,-dead_strip,$(LDFLAGS)),) + CRYPTOPP_LDFLAGS += -Wl,-dead_strip + endif # CRYPTOPP_CXXFLAGS + else # BSD, Linux and Unix + ifeq ($(findstring -Wl,--gc-sections,$(LDFLAGS)),) + CRYPTOPP_LDFLAGS += -Wl,--gc-sections + endif # LDFLAGS + endif # MAKECMDGOALS +endif # Dead code stripping + +# For Shared Objects, Diff, Dist/Zip rules +LIB_VER := $(shell $(GREP) "define CRYPTOPP_VERSION" config_ver.h | cut -d" " -f 3) +LIB_MAJOR := $(shell echo $(LIB_VER) | cut -c 1) +LIB_MINOR := $(shell echo $(LIB_VER) | cut -c 2) +LIB_PATCH := $(shell echo $(LIB_VER) | cut -c 3) + +ifeq ($(strip $(LIB_PATCH)),) + LIB_PATCH := 0 +endif + +ifeq ($(HAS_SOLIB_VERSION),1) +# Different patchlevels and minors are compatible since 6.1 +SOLIB_COMPAT_SUFFIX=.$(LIB_MAJOR) +# Linux uses -Wl,-soname +ifneq ($(IS_LINUX)$(IS_HURD),00) +# Linux uses full version suffix for shared library +SOLIB_VERSION_SUFFIX=.$(LIB_MAJOR).$(LIB_MINOR).$(LIB_PATCH) +SOLIB_FLAGS=-Wl,-soname,libcryptopp.so$(SOLIB_COMPAT_SUFFIX) +endif +# Solaris uses -Wl,-h +ifeq ($(IS_SUN),1) +# Solaris uses major version suffix for shared library, but we use major.minor +# The minor version allows previous version to remain and not overwritten. +# https://blogs.oracle.com/solaris/how-to-name-a-solaris-shared-object-v2 +SOLIB_VERSION_SUFFIX=.$(LIB_MAJOR).$(LIB_MINOR) +SOLIB_FLAGS=-Wl,-h,libcryptopp.so$(SOLIB_COMPAT_SUFFIX) +endif +endif # HAS_SOLIB_VERSION + +########################################################### +##### Temp file cleanup ##### +########################################################### + +# After this point no more test programs should be run. +# https://github.com/weidai11/cryptopp/issues/738 +ifeq ($(findstring /dev/null,$(TOUT)),) + # $(info TOUT is not /dev/null, cleaning $(TOUT)) + ifeq ($(wildcard $(TOUT)),$(TOUT)) + UNUSED := $(shell $(RM) $(TOUT) 2>/dev/null) + endif + ifeq ($(wildcard $(TOUT).dSYM/),$(TOUT).dSYM/) + UNUSED := $(shell $(RM) -r $(TOUT).dSYM/ 2>/dev/null) + endif +endif + +########################################################### +##### Source and object files ##### +########################################################### + +# List cryptlib.cpp first, then cpu.cpp, then integer.cpp to tame C++ static initialization problems. +SRCS := cryptlib.cpp cpu.cpp integer.cpp $(filter-out cryptlib.cpp cpu.cpp integer.cpp pch.cpp simple.cpp,$(sort $(wildcard *.cpp))) +# For Makefile.am; resource.h is Windows +INCL := $(filter-out resource.h,$(sort $(wildcard *.h))) + +ifneq ($(IS_MINGW),0) +INCL += resource.h +endif + +# Cryptogams source files. We couple to ARMv7. +# Limit to Linux. The source files target the GNU assembler. +# Also see https://www.cryptopp.com/wiki/Cryptogams. +ifeq ($(IS_ARM32)$(IS_LINUX),11) + ifeq ($(CLANG_COMPILER),1) + CRYPTOGAMS_ARMV4_FLAG = -march=armv7-a -Wa,--noexecstack + CRYPTOGAMS_ARMV4_THUMB_FLAG = -march=armv7-a -mthumb -Wa,--noexecstack + else + CRYPTOGAMS_ARMV4_FLAG = -march=armv7-a -Wa,--noexecstack + CRYPTOGAMS_ARMV4_THUMB_FLAG = -march=armv7-a -Wa,--noexecstack + endif + SRCS += aes_armv4.S sha1_armv4.S sha256_armv4.S sha512_armv4.S +endif + +# Remove unneeded arch specific files to speed build time. +ifeq ($(IS_PPC32)$(IS_PPC64),00) + SRCS := $(filter-out ppc_%,$(SRCS)) +endif +ifeq ($(IS_ARM32)$(IS_ARMV8),00) + SRCS := $(filter-out arm_%,$(SRCS)) + SRCS := $(filter-out neon_%,$(SRCS)) +endif +ifeq ($(IS_X86)$(IS_X32)$(IS_X64),000) + SRCS := $(filter-out sse_%,$(SRCS)) +endif + +# List cryptlib.cpp first, then cpu.cpp, then integer.cpp to tame C++ static initialization problems. +OBJS := $(SRCS:.cpp=.o) +OBJS := $(OBJS:.S=.o) + +# List test.cpp first to tame C++ static initialization problems. +TESTSRCS := adhoc.cpp test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp dlltest.cpp fipsalgt.cpp validat0.cpp validat1.cpp validat2.cpp validat3.cpp validat4.cpp validat5.cpp validat6.cpp validat7.cpp validat8.cpp validat9.cpp validat10.cpp regtest1.cpp regtest2.cpp regtest3.cpp regtest4.cpp +TESTINCL := bench.h factory.h validate.h + +# Test objects +TESTOBJS := $(TESTSRCS:.cpp=.o) +LIBOBJS := $(filter-out $(TESTOBJS),$(OBJS)) + +# In Crypto++ 5.6.2 these were the source and object files for the FIPS DLL. +# Since the library is on the Historical Validation List we add all files. +# The 5.6.2 list is at https://github.com/weidai11/cryptopp/blob/789f81f048c9. +DLLSRCS := $(SRCS) +DLLOBJS := $(DLLSRCS:.cpp=.export.o) +DLLOBJS := $(DLLOBJS:.S=.export.o) + +# Import lib testing +LIBIMPORTOBJS := $(LIBOBJS:.o=.import.o) +TESTIMPORTOBJS := $(TESTOBJS:.o=.import.o) +DLLTESTOBJS := dlltest.dllonly.o + +# Clean recipe, Issue 998. Don't filter-out some artifacts from the list of objects +# The *.S is a hack. It makes the ASM appear like C++ so the object files make the CLEAN_OBJS list +CLEAN_SRCS := $(wildcard *.cpp) $(patsubst %.S,%.cpp,$(wildcard *.S)) +CLEAN_OBJS := $(CLEAN_SRCS:.cpp=.o) $(CLEAN_SRCS:.cpp=.import.o) $(CLEAN_SRCS:.cpp=.export.o) + +########################################################### +##### Add our flags to user flags ##### +########################################################### + +# This ensures we don't add flags when the user forbids +# use of customary library flags, like -fPIC. Make will +# ignore this assignment when CXXFLAGS is passed as an +# argument to the make program: make CXXFLAGS="..." +CPPFLAGS := $(strip $(CRYPTOPP_CPPFLAGS) $(CPPFLAGS)) +CXXFLAGS := $(strip $(CRYPTOPP_CXXFLAGS) $(CXXFLAGS)) +LDFLAGS := $(strip $(CRYPTOPP_LDFLAGS) $(LDFLAGS)) + +########################################################### +##### Targets and Recipes ##### +########################################################### + +# Default builds program with static library only +.PHONY: default +default: cryptest.exe + +.PHONY: all static dynamic +all: static dynamic cryptest.exe + +ifneq ($(IS_DARWIN),0) +static: libcryptopp.a +shared dynamic dylib: libcryptopp.dylib +else +static: libcryptopp.a +shared dynamic: libcryptopp.so$(SOLIB_VERSION_SUFFIX) +endif + +# CXXFLAGS are tuned earlier. +.PHONY: native no-asm asan ubsan +native no-asm asan ubsan: cryptest.exe + +# CXXFLAGS are tuned earlier. Applications must use linker flags +# -Wl,--gc-sections (Linux and Unix) or -Wl,-dead_strip (OS X) +.PHONY: lean +lean: static dynamic cryptest.exe + +# May want to export CXXFLAGS="-g3 -O1" +.PHONY: lcov coverage +lcov coverage: cryptest.exe + @-$(RM) -r ./TestCoverage/ + lcov --base-directory . --directory . --zerocounters -q + ./cryptest.exe v + ./cryptest.exe tv all + ./cryptest.exe b 0.25 + lcov --base-directory . --directory . -c -o cryptest.info + lcov --remove cryptest.info "adhoc.*" -o cryptest.info + lcov --remove cryptest.info "fips140.*" -o cryptest.info + lcov --remove cryptest.info "*test.*" -o cryptest.info + lcov --remove cryptest.info "/usr/*" -o cryptest.info + genhtml -o ./TestCoverage/ -t "Crypto++ test coverage" --num-spaces 4 cryptest.info + +# Travis CI and CodeCov rule +.PHONY: gcov codecov +gcov codecov: cryptest.exe + @-$(RM) -r ./TestCoverage/ + ./cryptest.exe v + ./cryptest.exe tv all + gcov -r $(SRCS) + +# Should use CXXFLAGS="-g3 -O1" +.PHONY: valgrind +valgrind: cryptest.exe + valgrind --track-origins=yes --suppressions=cryptopp.supp ./cryptest.exe v + +.PHONY: test check +test check: cryptest.exe + ./cryptest.exe v + +# Used to generate list of source files for Autotools, CMakeList, Android.mk, etc +.PHONY: sources +sources: adhoc.cpp + $(info ***** Library sources *****) + $(info $(filter-out $(TESTSRCS),$(SRCS))) + $(info ) + $(info ***** Library headers *****) + $(info $(filter-out $(TESTINCL),$(INCL))) + $(info ) + $(info ***** Test sources *****) + $(info $(TESTSRCS)) + $(info ) + $(info ***** Test headers *****) + $(info $(TESTINCL)) + +# Directory we want (can't specify on Doygen command line) +DOCUMENT_DIRECTORY := ref$(LIB_VER) +# Directory Doxygen uses (specified in Doygen config file) +ifeq ($(wildcard Doxyfile),Doxyfile) +DOXYGEN_DIRECTORY := $(strip $(shell $(GREP) "OUTPUT_DIRECTORY" Doxyfile | $(GREP) -v "\#" | cut -d "=" -f 2)) +endif +# Default directory (in case its missing in the config file) +ifeq ($(strip $(DOXYGEN_DIRECTORY)),) +DOXYGEN_DIRECTORY := html-docs +endif + +# Builds the documentation. Directory name is ref563, ref570, etc. +.PHONY: docs html +docs html: + @-$(RM) -r $(DOXYGEN_DIRECTORY)/ $(DOCUMENT_DIRECTORY)/ html-docs/ + @-$(RM) CryptoPPRef.zip + doxygen Doxyfile -d CRYPTOPP_DOXYGEN_PROCESSING + $(MV) $(DOXYGEN_DIRECTORY)/ $(DOCUMENT_DIRECTORY)/ + zip -9 CryptoPPRef.zip -x ".*" -x "*/.*" -r $(DOCUMENT_DIRECTORY)/ + +.PHONY: clean +clean: + -$(RM) adhoc.cpp.o adhoc.cpp.proto.o $(CLEAN_OBJS) rdrand-*.o + @-$(RM) libcryptopp.a libcryptopp.dylib cryptopp.dll libcryptopp.dll.a libcryptopp.import.a + @-$(RM) libcryptopp.so libcryptopp.so$(SOLIB_COMPAT_SUFFIX) libcryptopp.so$(SOLIB_VERSION_SUFFIX) + @-$(RM) cryptest.exe dlltest.exe cryptest.import.exe cryptest.dat ct et + @-$(RM) *.la *.lo *.gcov *.gcno *.gcda *.stackdump core core-* + @-$(RM) /tmp/adhoc.exe + @-$(RM) -r /tmp/cryptopp_test/ + @-$(RM) -r *.exe.dSYM/ *.dylib.dSYM/ + @-$(RM) -r cov-int/ + +.PHONY: autotools-clean +autotools-clean: + @-$(RM) -f configure.ac configure configure.in Makefile.am Makefile.in Makefile + @-$(RM) -f config.guess config.status config.sub config.h.in compile depcomp + @-$(RM) -f install-sh stamp-h1 ar-lib *.lo *.la *.m4 local.* lt*.sh missing + @-$(RM) -f cryptest cryptestcwd libtool* libcryptopp.la libcryptopp.pc* + @-$(RM) -rf build-aux/ m4/ auto*.cache/ .deps/ .libs/ + +.PHONY: cmake-clean +cmake-clean: + @-$(RM) -f cryptopp-config.cmake CMakeLists.txt + @-$(RM) -rf cmake_build/ + +.PHONY: android-clean +android-clean: + @-$(RM) -f $(patsubst %_simd.cpp,%_simd.cpp.neon,$(wildcard *_simd.cpp)) + @-$(RM) -rf obj/ + +.PHONY: distclean +distclean: clean autotools-clean cmake-clean android-clean + -$(RM) adhoc.cpp adhoc.cpp.copied GNUmakefile.deps benchmarks.html cryptest.txt + -$(RM) cryptest_all.info cryptest_debug.info cryptest_noasm.info cryptest_base.info cryptest.info cryptest_release.info + @-$(RM) cryptest-*.txt cryptopp.tgz libcryptopp.pc *.o *.bc *.ii *~ + @-$(RM) -r cryptlib.lib cryptest.exe *.suo *.sdf *.pdb Win32/ x64/ ipch/ + @-$(RM) -r $(LIBOBJS:.o=.obj) $(TESTOBJS:.o=.obj) + @-$(RM) -r $(LIBOBJS:.o=.lst) $(TESTOBJS:.o=.lst) + @-$(RM) -r TestCoverage/ ref*/ + @-$(RM) cryptopp$(LIB_VER)\.* CryptoPPRef.zip + +# Install cryptest.exe, libcryptopp.a, libcryptopp.so and libcryptopp.pc. +# The library install was broken-out into its own recipe at GH #653. +.PHONY: install +install: cryptest.exe install-lib + @-$(MKDIR) $(DESTDIR)$(BINDIR) + $(CP) cryptest.exe $(DESTDIR)$(BINDIR) + $(CHMOD) u=rwx,go=rx $(DESTDIR)$(BINDIR)/cryptest.exe + @-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestData + @-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestVectors + $(CP) TestData/*.dat $(DESTDIR)$(DATADIR)/cryptopp/TestData + $(CHMOD) u=rw,go=r $(DESTDIR)$(DATADIR)/cryptopp/TestData/*.dat + $(CP) TestVectors/*.txt $(DESTDIR)$(DATADIR)/cryptopp/TestVectors + $(CHMOD) u=rw,go=r $(DESTDIR)$(DATADIR)/cryptopp/TestVectors/*.txt + +# A recipe to install only the library, and not cryptest.exe. Also +# see https://github.com/weidai11/cryptopp/issues/653. Some users +# already have a libcryptopp.pc. Install the *.pc file if the file +# is present. If you want one, then issue 'make libcryptopp.pc'. +.PHONY: install-lib +install-lib: + @-$(MKDIR) $(DESTDIR)$(INCLUDEDIR)/cryptopp + $(CP) *.h $(DESTDIR)$(INCLUDEDIR)/cryptopp + $(CHMOD) u=rw,go=r $(DESTDIR)$(INCLUDEDIR)/cryptopp/*.h +ifneq ($(wildcard libcryptopp.a),) + @-$(MKDIR) $(DESTDIR)$(LIBDIR) + $(CP) libcryptopp.a $(DESTDIR)$(LIBDIR) + $(CHMOD) u=rw,go=r $(DESTDIR)$(LIBDIR)/libcryptopp.a +endif +ifneq ($(wildcard libcryptopp.dylib),) + @-$(MKDIR) $(DESTDIR)$(LIBDIR) + $(CP) libcryptopp.dylib $(DESTDIR)$(LIBDIR) + $(CHMOD) u=rwx,go=rx $(DESTDIR)$(LIBDIR)/libcryptopp.dylib + -install_name_tool -id $(DESTDIR)$(LIBDIR)/libcryptopp.dylib $(DESTDIR)$(LIBDIR)/libcryptopp.dylib +endif +ifneq ($(wildcard libcryptopp.so$(SOLIB_VERSION_SUFFIX)),) + @-$(MKDIR) $(DESTDIR)$(LIBDIR) + $(CP) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR) + $(CHMOD) u=rwx,go=rx $(DESTDIR)$(LIBDIR)/libcryptopp.so$(SOLIB_VERSION_SUFFIX) +ifeq ($(HAS_SOLIB_VERSION),1) + -$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)/libcryptopp.so + $(LDCONF) $(DESTDIR)$(LIBDIR) +endif +endif +ifneq ($(wildcard libcryptopp.pc),) + @-$(MKDIR) $(DESTDIR)$(LIBDIR)/pkgconfig + $(CP) libcryptopp.pc $(DESTDIR)$(LIBDIR)/pkgconfig + $(CHMOD) u=rw,go=r $(DESTDIR)$(LIBDIR)/pkgconfig/libcryptopp.pc +endif + +.PHONY: remove uninstall +remove uninstall: + -$(RM) -r $(DESTDIR)$(INCLUDEDIR)/cryptopp + -$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.a + -$(RM) $(DESTDIR)$(BINDIR)/cryptest.exe +ifneq ($(wildcard $(DESTDIR)$(LIBDIR)/libcryptopp.dylib),) + -$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.dylib +endif +ifneq ($(wildcard $(DESTDIR)$(LIBDIR)/libcryptopp.so),) + -$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.so +endif + @-$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.so$(SOLIB_VERSION_SUFFIX) + @-$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.so$(SOLIB_COMPAT_SUFFIX) + @-$(RM) $(DESTDIR)$(LIBDIR)/pkgconfig/libcryptopp.pc + @-$(RM) -r $(DESTDIR)$(DATADIR)/cryptopp + +libcryptopp.a: $(LIBOBJS) | osx_warning + $(AR) $(ARFLAGS) $@ $(LIBOBJS) +ifeq ($(IS_SUN),0) + $(RANLIB) $@ +endif + +ifeq ($(HAS_SOLIB_VERSION),1) +.PHONY: libcryptopp.so +libcryptopp.so: libcryptopp.so$(SOLIB_VERSION_SUFFIX) | so_warning +endif + +libcryptopp.so$(SOLIB_VERSION_SUFFIX): $(LIBOBJS) +ifeq ($(XLC_COMPILER),1) + $(CXX) -qmkshrobj $(SOLIB_FLAGS) -o $@ $(CXXFLAGS) $(LDFLAGS) $(LIBOBJS) $(LDLIBS) +else + $(CXX) -shared $(SOLIB_FLAGS) -o $@ $(CXXFLAGS) $(LDFLAGS) $(LIBOBJS) $(LDLIBS) +endif +ifeq ($(HAS_SOLIB_VERSION),1) + -$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) libcryptopp.so + -$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) libcryptopp.so$(SOLIB_COMPAT_SUFFIX) +endif + +libcryptopp.dylib: $(LIBOBJS) | osx_warning + $(CXX) -dynamiclib -o $@ $(CXXFLAGS) -install_name "$@" -current_version "$(LIB_MAJOR).$(LIB_MINOR).$(LIB_PATCH)" -compatibility_version "$(LIB_MAJOR).$(LIB_MINOR)" -headerpad_max_install_names $(LDFLAGS) $(LIBOBJS) + +cryptest.exe: $(LINK_LIBRARY) $(TESTOBJS) | osx_warning + $(CXX) -o $@ $(CXXFLAGS) $(TESTOBJS) $(LINK_LIBRARY_PATH)$(LINK_LIBRARY) $(LDFLAGS) $(LDLIBS) + +# Makes it faster to test changes +nolib: $(OBJS) + $(CXX) -o ct $(CXXFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS) + +dll: cryptest.import.exe dlltest.exe + +cryptopp.dll: $(DLLOBJS) + $(CXX) -shared -o $@ $(CXXFLAGS) $(DLLOBJS) $(LDFLAGS) $(LDLIBS) -Wl,--out-implib=libcryptopp.dll.a + +libcryptopp.import.a: $(LIBIMPORTOBJS) + $(AR) $(ARFLAGS) $@ $(LIBIMPORTOBJS) +ifeq ($(IS_SUN),0) + $(RANLIB) $@ +endif + +cryptest.import.exe: cryptopp.dll libcryptopp.import.a $(TESTIMPORTOBJS) + $(CXX) -o $@ $(CXXFLAGS) $(TESTIMPORTOBJS) -L. -lcryptopp.dll -lcryptopp.import $(LDFLAGS) $(LDLIBS) + +dlltest.exe: cryptopp.dll $(DLLTESTOBJS) + $(CXX) -o $@ $(CXXFLAGS) $(DLLTESTOBJS) -L. -lcryptopp.dll $(LDFLAGS) $(LDLIBS) + +# Some users already have a libcryptopp.pc. We install it if the file +# is present. If you want one, then issue 'make libcryptopp.pc'. Be sure +# to use/verify PREFIX and LIBDIR below after writing the file. +cryptopp.pc libcryptopp.pc: + @echo '# Crypto++ package configuration file' > libcryptopp.pc + @echo '' >> libcryptopp.pc + @echo 'prefix=$(PC_PREFIX)' >> libcryptopp.pc + @echo 'libdir=$(PC_LIBDIR)' >> libcryptopp.pc + @echo 'includedir=$(PC_INCLUDEDIR)' >> libcryptopp.pc + @echo 'datadir=$(PC_DATADIR)' >> libcryptopp.pc + @echo '' >> libcryptopp.pc + @echo 'Name: Crypto++' >> libcryptopp.pc + @echo 'Description: Crypto++ cryptographic library' >> libcryptopp.pc + @echo 'Version: 8.6' >> libcryptopp.pc + @echo 'URL: https://cryptopp.com/' >> libcryptopp.pc + @echo '' >> libcryptopp.pc + @echo 'Cflags: -I$${includedir}' >> libcryptopp.pc + @echo 'Libs: -L$${libdir} -lcryptopp' >> libcryptopp.pc + +# This recipe prepares the distro files +TEXT_FILES := *.h *.cpp *.S GNUmakefile GNUmakefile-cross License.txt Readme.txt Install.txt Filelist.txt Doxyfile cryptest* cryptlib* dlltest* cryptdll* *.sln *.vcxproj *.filters cryptopp.rc TestVectors/*.txt TestData/*.dat TestPrograms/*.cpp +EXEC_FILES := TestScripts/*.sh TestScripts/*.cmd +EXEC_DIRS := TestData/ TestVectors/ TestScripts/ TestPrograms/ + +ifeq ($(wildcard Filelist.txt),Filelist.txt) +DIST_FILES := $(shell cat Filelist.txt) +endif + +.PHONY: trim +trim: +ifneq ($(IS_DARWIN),0) + $(SED) -i '' -e's/[[:space:]]*$$//' *.supp *.txt .*.yml *.h *.cpp *.asm *.S + $(SED) -i '' -e's/[[:space:]]*$$//' *.sln *.vcxproj *.filters GNUmakefile GNUmakefile-cross + $(SED) -i '' -e's/[[:space:]]*$$//' TestData/*.dat TestVectors/*.txt TestPrograms/*.cpp TestScripts/*.* + make convert +else + $(SED) -i -e's/[[:space:]]*$$//' *.supp *.txt .*.yml *.h *.cpp *.asm *.S + $(SED) -i -e's/[[:space:]]*$$//' *.sln *.vcxproj *.filters GNUmakefile GNUmakefile-cross + $(SED) -i -e's/[[:space:]]*$$//' TestData/*.dat TestVectors/*.txt TestPrograms/*.cpp TestScripts/*.* + make convert +endif + +.PHONY: convert +convert: + @-$(CHMOD) u=rwx,go=rx $(EXEC_DIRS) + @-$(CHMOD) u=rw,go=r $(TEXT_FILES) *.supp .*.yml *.asm *.zip TestVectors/*.txt TestData/*.dat TestPrograms/*.cpp + @-$(CHMOD) u=rwx,go=rx $(EXEC_FILES) *.sh + -unix2dos --keepdate --quiet $(TEXT_FILES) .*.yml *.asm TestScripts/*.cmd TestScripts/*.txt TestScripts/*.cpp + -dos2unix --keepdate --quiet GNUmakefile GNUmakefile-cross *.sh *.S *.supp *.mapfile TestScripts/*.sh +ifneq ($(IS_DARWIN),0) + @-xattr -c * +endif + +# Build the ZIP file with source files. No documentation. +.PHONY: zip dist +zip dist: | distclean convert + zip -q -9 cryptopp$(LIB_VER).zip $(DIST_FILES) + +# Build the ISO to transfer the ZIP to old distros via CDROM +.PHONY: iso +iso: | zip +ifneq ($(IS_DARWIN),0) + $(MKDIR) $(PWD)/cryptopp$(LIB_VER) + $(CP) cryptopp$(LIB_VER).zip $(PWD)/cryptopp$(LIB_VER) + hdiutil makehybrid -iso -joliet -o cryptopp$(LIB_VER).iso $(PWD)/cryptopp$(LIB_VER) + @-$(RM) -r $(PWD)/cryptopp$(LIB_VER) +else ifneq ($(IS_LINUX)$(IS_HURD),00) + $(MKDIR) $(PWD)/cryptopp$(LIB_VER) + $(CP) cryptopp$(LIB_VER).zip $(PWD)/cryptopp$(LIB_VER) + genisoimage -q -o cryptopp$(LIB_VER).iso $(PWD)/cryptopp$(LIB_VER) + @-$(RM) -r $(PWD)/cryptopp$(LIB_VER) +endif + +# CRYPTOPP_CPU_FREQ in GHz +CRYPTOPP_CPU_FREQ ?= 0.0 +.PHONY: bench benchmark benchmarks +bench benchmark benchmarks: cryptest.exe + @-$(RM) -f benchmarks.html + ./cryptest.exe b 2 $(CRYPTOPP_CPU_FREQ) + +adhoc.cpp: adhoc.cpp.proto +ifeq ($(wildcard adhoc.cpp),) + cp adhoc.cpp.proto adhoc.cpp +else + touch adhoc.cpp +endif + +# Include dependencies, if present. You must issue `make deps` to create them. +ifeq ($(wildcard GNUmakefile.deps),GNUmakefile.deps) +-include GNUmakefile.deps +endif # Dependencies + +# A few recipes trigger warnings for -std=c++11 and -stdlib=c++ +NOSTD_CXXFLAGS=$(filter-out -stdlib=%,$(filter-out -std=%,$(CXXFLAGS))) + +# Cryptogams ARM asm implementation. AES needs -mthumb for Clang +aes_armv4.o : aes_armv4.S + $(CXX) $(strip $(CPPFLAGS) $(NOSTD_CXXFLAGS) $(CRYPTOGAMS_ARMV4_THUMB_FLAG) -c) $< + +# SSSE3 or NEON available +aria_simd.o : aria_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(ARIA_FLAG) -c) $< + +# SSE, NEON or POWER7 available +blake2s_simd.o : blake2s_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(BLAKE2S_FLAG) -c) $< + +# SSE, NEON or POWER8 available +blake2b_simd.o : blake2b_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(BLAKE2B_FLAG) -c) $< + +# SSE2 or NEON available +chacha_simd.o : chacha_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(CHACHA_FLAG) -c) $< + +# AVX2 available +chacha_avx.o : chacha_avx.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(CHACHA_AVX2_FLAG) -c) $< + +# SSSE3 available +cham_simd.o : cham_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(CHAM_FLAG) -c) $< + +# SSE4.2 or ARMv8a available +crc_simd.o : crc_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(CRC_FLAG) -c) $< + +# Power9 available +darn.o : darn.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(DARN_FLAG) -c) $< + +# SSE2 on i686 +donna_sse.o : donna_sse.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SSE2_FLAG) -c) $< + +# Carryless multiply +gcm_simd.o : gcm_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(GCM_FLAG) -c) $< + +# Carryless multiply +gf2n_simd.o : gf2n_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(GF2N_FLAG) -c) $< + +# SSSE3 available +keccak_simd.o : keccak_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(KECCAK_FLAG) -c) $< + +# SSSE3 available +lea_simd.o : lea_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LEA_FLAG) -c) $< + +# SSSE3 available +lsh256_sse.o : lsh256_sse.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LSH256_FLAG) -c) $< + +# AVX2 available +lsh256_avx.o : lsh256_avx.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LSH256_AVX2_FLAG) -c) $< + +# SSSE3 available +lsh512_sse.o : lsh512_sse.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LSH512_FLAG) -c) $< + +# AVX2 available +lsh512_avx.o : lsh512_avx.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LSH512_AVX2_FLAG) -c) $< + +# NEON available +neon_simd.o : neon_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(NEON_FLAG) -c) $< + +# AltiVec available +ppc_simd.o : ppc_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(ALTIVEC_FLAG) -c) $< + +# Power7 available +ppc_power7.o : ppc_power7.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(POWER7_FLAG) -c) $< + +# Power8 available +ppc_power8.o : ppc_power8.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(POWER8_FLAG) -c) $< + +# Power9 available +ppc_power9.o : ppc_power9.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(POWER9_FLAG) -c) $< + +# AESNI or ARMv7a/ARMv8a available +rijndael_simd.o : rijndael_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(AES_FLAG) -c) $< + +# SSE4.2/SHA-NI or ARMv8a available +sha_simd.o : sha_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SHA_FLAG) -c) $< + +# Cryptogams SHA1 asm implementation. +sha1_armv4.o : sha1_armv4.S + $(CXX) $(strip $(CPPFLAGS) $(NOSTD_CXXFLAGS) $(CRYPTOGAMS_ARMV4_FLAG) -c) $< + +# Cryptogams SHA256 asm implementation. +sha256_armv4.o : sha256_armv4.S + $(CXX) $(strip $(CPPFLAGS) $(NOSTD_CXXFLAGS) $(CRYPTOGAMS_ARMV4_FLAG) -c) $< + +# Cryptogams SHA512 asm implementation. +sha512_armv4.o : sha512_armv4.S + $(CXX) $(strip $(CPPFLAGS) $(NOSTD_CXXFLAGS) $(CRYPTOGAMS_ARMV4_FLAG) -c) $< + +sha3_simd.o : sha3_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SHA3_FLAG) -c) $< + +# SSE4.2/SHA-NI or ARMv8a available +shacal2_simd.o : shacal2_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SHA_FLAG) -c) $< + +# SSSE3, NEON or POWER8 available +simon128_simd.o : simon128_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SIMON128_FLAG) -c) $< + +# SSSE3, NEON or POWER8 available +speck128_simd.o : speck128_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SPECK128_FLAG) -c) $< + +# ARMv8.4 available +sm3_simd.o : sm3_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SM3_FLAG) -c) $< + +# AESNI available +sm4_simd.o : sm4_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SM4_FLAG) -c) $< + +# IBM XLC -O3 optimization bug +ifeq ($(XLC_COMPILER),1) +sm3.o : sm3.cpp + $(CXX) $(strip $(CPPFLAGS) $(subst -O3,-O2,$(CXXFLAGS)) -c) $< +donna_32.o : donna_32.cpp + $(CXX) $(strip $(CPPFLAGS) $(subst -O3,-O2,$(CXXFLAGS)) -c) $< +donna_64.o : donna_64.cpp + $(CXX) $(strip $(CPPFLAGS) $(subst -O3,-O2,$(CXXFLAGS)) -c) $< +endif + +# SSE2 on i686 +sse_simd.o : sse_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SSE2_FLAG) -c) $< + +# Don't build Rijndael with UBsan. Too much noise due to unaligned data accesses. +ifneq ($(findstring -fsanitize=undefined,$(CXXFLAGS)),) +rijndael.o : rijndael.cpp + $(CXX) $(strip $(subst -fsanitize=undefined,,$(CXXFLAGS)) -c) $< +endif + +# Only use CRYPTOPP_DATA_DIR if its not set in CXXFLAGS +ifeq ($(findstring -DCRYPTOPP_DATA_DIR, $(CXXFLAGS)),) +ifneq ($(strip $(CRYPTOPP_DATA_DIR)),) +validat%.o : validat%.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -DCRYPTOPP_DATA_DIR=\"$(CRYPTOPP_DATA_DIR)\" -c) $< +bench%.o : bench%.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -DCRYPTOPP_DATA_DIR=\"$(CRYPTOPP_DATA_DIR)\" -c) $< +datatest.o : datatest.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -DCRYPTOPP_DATA_DIR=\"$(CRYPTOPP_DATA_DIR)\" -c) $< +test.o : test.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -DCRYPTOPP_DATA_DIR=\"$(CRYPTOPP_DATA_DIR)\" -c) $< +endif +endif + +validat1.o : validat1.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(ALTIVEC_FLAG) -c) $< + +%.dllonly.o : %.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -DCRYPTOPP_DLL_ONLY -c) $< -o $@ + +%.import.o : %.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -DCRYPTOPP_IMPORTS -c) $< -o $@ + +%.export.o : %.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -DCRYPTOPP_EXPORTS -c) $< -o $@ + +%.bc : %.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -c) $< + +%.o : %.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -c) $< + +.PHONY: so_warning +so_warning: +ifeq ($(HAS_SOLIB_VERSION),1) + $(info ) + $(info WARNING: Only the symlinks to the shared-object library have been updated.) + $(info WARNING: If the library is installed in a system directory you will need) + $(info WARNING: to run 'ldconfig' to update the shared-object library cache.) + $(info ) +endif + +.PHONY: osx_warning +osx_warning: +ifeq ($(IS_DARWIN)$(CLANG_COMPILER),11) + ifeq ($(findstring -stdlib=libc++,$(CRYPTOPP_CXXFLAGS)$(CXXFLAGS)),) + $(info ) + $(info INFO: Crypto++ was built without LLVM's libc++. If you are using the library) + $(info INFO: with modern Xcode, then you should add -stdlib=libc++ to CXXFLAGS. It is) + $(info INFO: already present in the makefile, and you only need to uncomment it.) + $(info ) + endif +endif + +.PHONY: dep deps depend +dep deps depend GNUmakefile.deps: + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS)) -MM *.cpp > GNUmakefile.deps diff --git a/external/ours/library/crypto/src/shared/original/GNUmakefile-cross b/external/ours/library/crypto/src/shared/original/GNUmakefile-cross new file mode 100755 index 000000000..9847f04bf --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/GNUmakefile-cross @@ -0,0 +1,1060 @@ +# https://www.gnu.org/software/make/manual/make.html#Makefile-Conventions +# and https://www.gnu.org/prep/standards/standards.html + +SHELL = /bin/sh + +# If needed +TMPDIR ?= /tmp +# Used for feature tests +TOUT ?= a.out +TOUT := $(strip $(TOUT)) + +# Allow override for the cryptest.exe recipe. Change to +# ./libcryptopp.so or ./libcryptopp.dylib to suit your +# taste. https://github.com/weidai11/cryptopp/issues/866 +LINK_LIBRARY ?= libcryptopp.a +LINK_LIBRARY_PATH ?= ./ + +# Default FLAGS if none were provided +CPPFLAGS ?= -DNDEBUG +CXXFLAGS ?= -g2 -O3 -fPIC -pipe + +AR ?= ar +ARFLAGS ?= cr +RANLIB ?= ranlib +CP ?= cp +MV ?= mv +CHMOD ?= chmod +MKDIR ?= mkdir -p +GREP ?= grep +SED ?= sed + +LN ?= ln -sf +LDCONF ?= /sbin/ldconfig -n + +IS_IOS ?= 0 +IS_ANDROID ?= 0 +IS_ARM_EMBEDDED ?= 0 + +# Clang is reporting armv8l-unknown-linux-gnueabihf +# for ARMv7 images on Aarch64 hardware. +MACHINEX := $(shell $(CXX) $(CXXFLAGS) -dumpmachine 2>/dev/null) +HOSTX := $(shell echo $(MACHINEX) | cut -f 1 -d '-') +ifeq ($(HOSTX),) + HOSTX := $(shell uname -m 2>/dev/null) +endif + +IS_LINUX := $(shell echo $(MACHINEX) | $(GREP) -i -c "Linux") + +# Can be used by Android and Embedded cross-compiles. Disable by default because +# Android and embedded users typically don't run this configuration. +HAS_SOLIB_VERSION ?= 0 + +# Formerly adhoc.cpp was created from adhoc.cpp.proto when needed. +# This is now needed because ISA tests are performed using adhoc.cpp. +ifeq ($(wildcard adhoc.cpp),) +$(shell cp adhoc.cpp.proto adhoc.cpp) +endif + +########################################################### +##### General Variables ##### +########################################################### + +# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html +ifeq ($(PREFIX),) + PREFIX = /usr/local +endif +ifeq ($(LIBDIR),) + LIBDIR := $(PREFIX)/lib +endif +ifeq ($(DATADIR),) + DATADIR := $(PREFIX)/share +endif +ifeq ($(INCLUDEDIR),) + INCLUDEDIR := $(PREFIX)/include +endif +ifeq ($(BINDIR),) + BINDIR := $(PREFIX)/bin +endif + +# We honor ARFLAGS, but the "v" option used by default causes a noisy make +ifeq ($(ARFLAGS),rv) + ARFLAGS = r +endif + +########################################################### +##### MacOS ##### +########################################################### + +# MacOS cross-compile configuration. +# See http://www.cryptopp.com/wiki/MacOS_(Command_Line). +ifeq ($(IS_MACOS),1) + # setenv-macos.sh sets CPPFLAGS, CXXFLAGS and LDFLAGS + IS_APPLE_LIBTOOL=$(shell libtool -V 2>&1 | $(GREP) -i -c 'Apple') + ifeq ($(IS_APPLE_LIBTOOL),1) + AR = libtool + else + AR = /usr/bin/libtool + endif + ARFLAGS = -static -o +endif + +########################################################### +##### iOS ##### +########################################################### + +# iOS cross-compile configuration. +# See http://www.cryptopp.com/wiki/iOS_(Command_Line). +ifeq ($(IS_IOS),1) + # setenv-ios.sh sets CPPFLAGS, CXXFLAGS and LDFLAGS + AR = libtool + ARFLAGS = -static -o +endif + +########################################################### +##### Android ##### +########################################################### + +# Android cross-compile configuration. +# See http://www.cryptopp.com/wiki/Android_(Command_Line). +ifeq ($(IS_ANDROID),1) + # setenv-android.sh sets CPPFLAGS, CXXFLAGS and LDFLAGS + + # Source files copied into PWD for Android cpu-features + # setenv-android.sh does the copying. Its a dirty compile. + ANDROID_CPU_OBJ = cpu-features.o +endif + +########################################################### +##### Embedded ##### +########################################################### + +# ARM embedded cross-compile configuration. +# See http://www.cryptopp.com/wiki/ARM_Embedded_(Command_Line) +# and http://www.cryptopp.com/wiki/ARM_Embedded_(Bare Metal). +ifeq ($(IS_ARM_EMBEDDED),1) + # setenv-android.sh sets CPPFLAGS, CXXFLAGS and LDFLAGS +endif + +########################################################### +##### Compiler and Platform ##### +########################################################### + +# Wait until CXXFLAGS have been set by setenv scripts. + +GCC_COMPILER := $(shell $(CXX) --version 2>/dev/null | $(GREP) -v -E 'llvm|clang' | $(GREP) -i -c -E '(gcc|g\+\+)') +CLANG_COMPILER := $(shell $(CXX) --version 2>/dev/null | $(GREP) -i -c -E 'llvm|clang') + +HOSTX := $(shell $(CXX) $(CXXFLAGS) -dumpmachine 2>/dev/null | cut -f 1 -d '-') +ifeq ($(HOSTX),) + HOSTX := $(shell uname -m 2>/dev/null) +endif + +# This dance is because Clang reports the host architecture instead +# of the target architecture for -dumpmachine. Running Clang on an +# x86_64 machine with -arch arm64 yields x86_64 instead of arm64. + +ifeq ($(CLANG_COMPILER),1) + # The compiler is either GCC or Clang + IS_X86 := $(shell echo $(CXXFLAGS) | $(GREP) -v 64 | $(GREP) -i -c -E 'i.86') + IS_X64 := $(shell echo $(CXXFLAGS) | $(GREP) -i -c -E 'x86_64|amd64') + IS_ARM32 := $(shell echo $(CXXFLAGS) | $(GREP) -v 64 | $(GREP) -i -c -E 'arm|armhf|arm7l|armeabihf') + IS_ARMV8 := $(shell echo $(CXXFLAGS) | $(GREP) -i -c -E 'aarch32|aarch64|arm64|armv8') +else + IS_X86 := $(shell echo $(HOSTX) | $(GREP) -v 64 | $(GREP) -i -c -E 'i.86') + IS_X64 := $(shell echo $(HOSTX) | $(GREP) -i -c -E 'x86_64|amd64') + IS_ARM32 := $(shell echo $(HOSTX) | $(GREP) -v 64 | $(GREP) -i -c -E 'arm|armhf|arm7l|eabihf') + IS_ARMV8 := $(shell echo $(HOSTX) | $(GREP) -i -c -E 'aarch32|aarch64|arm64|armv8') +endif + +ifeq ($(IS_ARMV8),1) + IS_ARM32 = 0 +endif + +IS_X32 := 0 +IS_PPC32 := 0 +IS_PPC64 := 0 + +# Uncomment for debugging +# $(info Here's what we found... IS_X86: $(IS_X86), IS_X64: $(IS_X64), IS_ARM32: $(IS_ARM32), IS_ARMV8: $(IS_ARMV8)) + +########################################################### +##### Test Program ##### +########################################################### + +# Hack to skip CPU feature tests for some recipes +DETECT_FEATURES ?= 1 +ifeq ($(findstring -DCRYPTOPP_DISABLE_ASM,$(CXXFLAGS)),-DCRYPTOPP_DISABLE_ASM) + DETECT_FEATURES := 0 +else ifeq ($(findstring clean,$(MAKECMDGOALS)),clean) + DETECT_FEATURES := 0 +else ifeq ($(findstring distclean,$(MAKECMDGOALS)),distclean) + DETECT_FEATURES := 0 +else ifeq ($(findstring trim,$(MAKECMDGOALS)),trim) + DETECT_FEATURES := 0 +else ifeq ($(findstring zip,$(MAKECMDGOALS)),zip) + DETECT_FEATURES := 0 +endif + +# Strip out -Wall, -Wextra and friends for feature testing. FORTIFY_SOURCE is removed +# because it requires -O1 or higher, but we use -O0 to tame the optimizer. +# Always print testing flags since some tests always happen, like 64-bit. +TCXXFLAGS := $(filter-out -D_FORTIFY_SOURCE=% -M -MM -Wall -Wextra -Werror% -Wunused -Wconversion -Wp%, $(CPPFLAGS) $(CXXFLAGS)) +ifneq ($(strip $(TCXXFLAGS)),) + $(info Using testing flags: $(TCXXFLAGS)) +endif + +# TCOMMAND is used for just about all tests. Make will lazy-evaluate +# the variables when executed by $(shell $(TCOMMAND) ...). +TCOMMAND = $(CXX) $(TCXXFLAGS) $(TEXTRA) $(ZOPT) $(TOPT) $(TPROG) -o $(TOUT) + +########################################################### +##### X86/X32/X64 Options ##### +########################################################### + +ifneq ($(IS_X86)$(IS_X64),00) +ifeq ($(DETECT_FEATURES),1) + + SSE2_FLAG = -msse2 + SSE3_FLAG = -msse3 + SSSE3_FLAG = -mssse3 + SSE41_FLAG = -msse4.1 + SSE42_FLAG = -msse4.2 + CLMUL_FLAG = -mpclmul + AESNI_FLAG = -maes + AVX_FLAG = -mavx + AVX2_FLAG = -mavx2 + SHANI_FLAG = -msha + + TPROG = TestPrograms/test_x86_sse2.cpp + TOPT = $(SSE2_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CHACHA_FLAG = $(SSE2_FLAG) + else + # Make does not have useful debugging facilities. Show the user + # what happened by compiling again without the pipe. + $(info Running make again to see what failed) + $(info $(shell $(TCOMMAND))) + SSE2_FLAG = + endif + + ifeq ($(SSE2_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_ASM + endif + + # Need SSE2 or higher for these tests + ifneq ($(SSE2_FLAG),) + TPROG = TestPrograms/test_x86_ssse3.cpp + TOPT = $(SSSE3_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + ARIA_FLAG = $(SSSE3_FLAG) + CHAM_FLAG = $(SSSE3_FLAG) + KECCAK_FLAG = $(SSSE3_FLAG) + LEA_FLAG = $(SSSE3_FLAG) + LSH256_FLAG = $(SSSE3_FLAG) + LSH512_FLAG = $(SSSE3_FLAG) + SIMON128_FLAG = $(SSSE3_FLAG) + SPECK128_FLAG = $(SSSE3_FLAG) + else + SSSE3_FLAG = + endif + + # The first Apple MacBooks were Core2's with SSE4.1 + ifneq ($(IS_DARWIN),0) + # Add SSE2 algo's here as required + # They get a free upgrade + endif + + TPROG = TestPrograms/test_x86_sse41.cpp + TOPT = $(SSE41_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + BLAKE2B_FLAG = $(SSE41_FLAG) + BLAKE2S_FLAG = $(SSE41_FLAG) + else + SSE41_FLAG = + endif + + TPROG = TestPrograms/test_x86_sse42.cpp + TOPT = $(SSE42_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CRC_FLAG = $(SSE42_FLAG) + else + SSE42_FLAG = + endif + + TPROG = TestPrograms/test_x86_clmul.cpp + TOPT = $(CLMUL_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + GCM_FLAG = $(SSSE3_FLAG) $(CLMUL_FLAG) + GF2N_FLAG = $(CLMUL_FLAG) + else + CLMUL_FLAG = + endif + + TPROG = TestPrograms/test_x86_aes.cpp + TOPT = $(AESNI_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + AES_FLAG = $(SSE41_FLAG) $(AESNI_FLAG) + SM4_FLAG = $(SSSE3_FLAG) $(AESNI_FLAG) + else + AESNI_FLAG = + endif + + TPROG = TestPrograms/test_x86_avx.cpp + TOPT = $(AVX_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + # XXX_FLAG = $(AVX_FLAG) + else + AVX_FLAG = + endif + + TPROG = TestPrograms/test_x86_avx2.cpp + TOPT = $(AVX2_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + CHACHA_AVX2_FLAG = $(AVX2_FLAG) + LSH256_AVX2_FLAG = $(AVX2_FLAG) + LSH512_AVX2_FLAG = $(AVX2_FLAG) + else + AVX2_FLAG = + endif + + TPROG = TestPrograms/test_x86_sha.cpp + TOPT = $(SHANI_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SHA_FLAG = $(SSE42_FLAG) $(SHANI_FLAG) + else + SHANI_FLAG = + endif + + ifeq ($(SSE3_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_SSE3 + else ifeq ($(SSSE3_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_SSSE3 + else ifeq ($(SSE41_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_SSE4 + else ifeq ($(SSE42_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_SSE4 + endif + + ifneq ($(SSE42_FLAG),) + # Unusual GCC/Clang on Macports. It assembles AES, but not CLMUL. + # test_x86_clmul.s:15: no such instruction: 'pclmulqdq $0, %xmm1,%xmm0' + ifeq ($(CLMUL_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_CLMUL + endif + ifeq ($(AESNI_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_AESNI + endif + + ifeq ($(AVX_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_AVX + else ifeq ($(AVX2_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_AVX2 + endif + # SHANI independent of AVX per GH #1045 + ifeq ($(SHANI_FLAG),) + CRYPTOPP_CXXFLAGS += -DCRYPTOPP_DISABLE_SHANI + endif + endif + + # Drop to SSE2 if available + ifeq ($(GCM_FLAG),) + GCM_FLAG = $(SSE2_FLAG) + endif + + # Most Clang cannot handle mixed asm with positional arguments, where the + # body is Intel style with no prefix and the templates are AT&T style. + # Also see https://bugs.llvm.org/show_bug.cgi?id=39895 . + + # CRYPTOPP_DISABLE_MIXED_ASM is now being added in config_asm.h for all + # Clang compilers. This test will need to be re-enabled if Clang fixes it. + #TPROG = TestPrograms/test_asm_mixed.cpp + #TOPT = + #HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + #ifneq ($(strip $(HAVE_OPT)),0) + # CXXFLAGS += -DCRYPTOPP_DISABLE_MIXED_ASM + #endif + + # SSE2_FLAGS + endif + +# DETECT_FEATURES +endif + +# IS_X86, IS_X32 and IS_X64 +endif + +########################################################### +##### ARM A-32 and NEON ##### +########################################################### + +ifneq ($(IS_ARM32),0) +ifeq ($(DETECT_FEATURES),1) + + # Android needs -c compile flag for NEON. Otherwise there's an odd linker message. + ifeq ($(IS_ANDROID),1) + NEON_FLAG = -march=armv7-a -mfpu=vfpv3-d16 -mfpu=neon + else + NEON_FLAG = -march=armv7-a -mfpu=neon + endif + + # Clang needs an option to include + TPROG = TestPrograms/test_arm_neon_header.cpp + TOPT = -DCRYPTOPP_ARM_NEON_HEADER=1 $(NEON_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + TEXTRA += -DCRYPTOPP_ARM_NEON_HEADER=1 + endif + + TPROG = TestPrograms/test_arm_neon.cpp + TOPT = $(NEON_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + ARIA_FLAG = $(NEON_FLAG) + AES_FLAG = $(NEON_FLAG) + CRC_FLAG = $(NEON_FLAG) + GCM_FLAG = $(NEON_FLAG) + BLAKE2B_FLAG = $(NEON_FLAG) + BLAKE2S_FLAG = $(NEON_FLAG) + CHACHA_FLAG = $(NEON_FLAG) + CHAM_FLAG = $(NEON_FLAG) + LEA_FLAG = $(NEON_FLAG) + SHA_FLAG = $(NEON_FLAG) + SIMON128_FLAG = $(NEON_FLAG) + SPECK128_FLAG = $(NEON_FLAG) + SM4_FLAG = $(NEON_FLAG) + else + # Make does not have useful debugging facilities. Show the user + # what happened by compiling again without the pipe. + $(info Running make again to see what failed) + $(info $(shell $(TCOMMAND))) + NEON_FLAG = + endif + + ifeq ($(NEON_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_ASM + endif + +# DETECT_FEATURES +endif +# IS_ARM32 +endif + +########################################################### +##### Aach32 and Aarch64 ##### +########################################################### + +ifneq ($(IS_ARMV8),0) +ifeq ($(DETECT_FEATURES),1) + + ifeq ($(IS_IOS),1) + ASIMD_FLAG = -arch arm64 + CRC_FLAG = -arch arm64 + AES_FLAG = -arch arm64 + PMUL_FLAG = -arch arm64 + SHA_FLAG = -arch arm64 + else + ASIMD_FLAG = -march=armv8-a + CRC_FLAG = -march=armv8-a+crc + AES_FLAG = -march=armv8-a+crypto + GCM_FLAG = -march=armv8-a+crypto + GF2N_FLAG = -march=armv8-a+crypto + SHA_FLAG = -march=armv8-a+crypto + endif + + TPROG = TestPrograms/test_arm_neon_header.cpp + TOPT = -DCRYPTOPP_ARM_NEON_HEADER=1 + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + TEXTRA += -DCRYPTOPP_ARM_NEON_HEADER=1 + endif + + TPROG = TestPrograms/test_arm_acle_header.cpp + TOPT = -DCRYPTOPP_ARM_ACLE_HEADER=1 $(ASIMD_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + TEXTRA += -DCRYPTOPP_ARM_ACLE_HEADER=1 + endif + + TPROG = TestPrograms/test_arm_asimd.cpp + TOPT = $(ASIMD_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + ARIA_FLAG = $(ASIMD_FLAG) + BLAKE2B_FLAG = $(ASIMD_FLAG) + BLAKE2S_FLAG = $(ASIMD_FLAG) + CHACHA_FLAG = $(ASIMD_FLAG) + CHAM_FLAG = $(ASIMD_FLAG) + LEA_FLAG = $(ASIMD_FLAG) + NEON_FLAG = $(ASIMD_FLAG) + SIMON128_FLAG = $(ASIMD_FLAG) + SPECK128_FLAG = $(ASIMD_FLAG) + SM4_FLAG = $(ASIMD_FLAG) + else + # Make does not have useful debugging facilities. Show the user + # what happened by compiling again without the pipe. + $(info Running make again to see what failed) + $(info $(shell $(TCOMMAND))) + ASIMD_FLAG = + endif + + ifeq ($(ASIMD_FLAG),) + CXXFLAGS += -DCRYPTOPP_DISABLE_ASM + endif + + ifneq ($(ASIMD_FLAG),) + + TPROG = TestPrograms/test_arm_crc.cpp + TOPT = $(CRC_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifneq ($(strip $(HAVE_OPT)),0) + CRC_FLAG = + CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_CRC32 + endif + + TPROG = TestPrograms/test_arm_aes.cpp + TOPT = $(AES_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifneq ($(strip $(HAVE_OPT)),0) + AES_FLAG = + CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_AES + endif + + TPROG = TestPrograms/test_arm_pmull.cpp + TOPT = $(PMULL_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifneq ($(strip $(HAVE_OPT)),0) + GCM_FLAG = + GF2N_FLAG = + CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_PMULL + endif + + TPROG = TestPrograms/test_arm_sha1.cpp + TOPT = $(SHA_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifneq ($(strip $(HAVE_OPT)),0) + SHA_FLAG = + CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SHA1 + endif + + TPROG = TestPrograms/test_arm_sha256.cpp + TOPT = $(SHA_FLAG) + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifneq ($(strip $(HAVE_OPT)),0) + SHA_FLAG = + CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SHA2 + endif + + TPROG = TestPrograms/test_arm_sm3.cpp + TOPT = -march=armv8.4-a+sm3 + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SM3_FLAG = -march=armv8.4-a+sm3 + SM4_FLAG = -march=armv8.4-a+sm3 + else + #CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SM3 + #CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SM4 + endif + + TPROG = TestPrograms/test_arm_sha3.cpp + TOPT = -march=armv8.4-a+sha3 + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SHA3_FLAG = -march=armv8.4-a+sha3 + else + #CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SHA3 + endif + + TPROG = TestPrograms/test_arm_sha512.cpp + TOPT = -march=armv8.4-a+sha512 + HAVE_OPT = $(shell $(TCOMMAND) 2>&1 | wc -w) + ifeq ($(strip $(HAVE_OPT)),0) + SHA512_FLAG = -march=armv8.4-a+sha512 + else + #CXXFLAGS += -DCRYPTOPP_DISABLE_ARM_SHA512 + endif + + # ASIMD_FLAG + endif + +# DETECT_FEATURES +endif +# IS_ARMV8 +endif + +########################################################### +##### Common ##### +########################################################### + +# No ASM for Travis testing +ifeq ($(findstring no-asm,$(MAKECMDGOALS)),no-asm) + ifeq ($(findstring -DCRYPTOPP_DISABLE_ASM,$(CXXFLAGS)),) + CXXFLAGS += -DCRYPTOPP_DISABLE_ASM + endif # CXXFLAGS +endif # No ASM + +# Undefined Behavior Sanitizer (UBsan) testing. Issue 'make ubsan'. +ifeq ($(findstring ubsan,$(MAKECMDGOALS)),ubsan) + ifeq ($(findstring -fsanitize=undefined,$(CXXFLAGS)),) + CXXFLAGS += -fsanitize=undefined + endif # CXXFLAGS + ifeq ($(findstring -DCRYPTOPP_COVERAGE,$(CXXFLAGS)),) + CXXFLAGS += -DCRYPTOPP_COVERAGE + endif # CXXFLAGS +endif # UBsan + +# Address Sanitizer (Asan) testing. Issue 'make asan'. +ifeq ($(findstring asan,$(MAKECMDGOALS)),asan) + ifeq ($(findstring -fsanitize=address,$(CXXFLAGS)),) + CXXFLAGS += -fsanitize=address + endif # CXXFLAGS + ifeq ($(findstring -DCRYPTOPP_COVERAGE,$(CXXFLAGS)),) + CXXFLAGS += -DCRYPTOPP_COVERAGE + endif # CXXFLAGS + ifeq ($(findstring -fno-omit-frame-pointer,$(CXXFLAGS)),) + CXXFLAGS += -fno-omit-frame-pointer + endif # CXXFLAGS +endif # Asan + +# LD gold linker testing. Triggered by 'LD=ld.gold'. +ifeq ($(findstring ld.gold,$(LD)),ld.gold) + ifeq ($(findstring -fuse-ld=gold,$(CXXFLAGS)),) + ELF_FORMAT := $(shell file `which ld.gold` 2>&1 | cut -d":" -f 2 | $(GREP) -i -c "elf") + ifneq ($(ELF_FORMAT),0) + LDFLAGS += -fuse-ld=gold + endif # ELF/ELF64 + endif # CXXFLAGS +endif # Gold + +# Valgrind testing. Issue 'make valgrind'. +ifneq ($(filter valgrind,$(MAKECMDGOALS)),) + # Tune flags; see http://valgrind.org/docs/manual/quick-start.html + CXXFLAGS := $(CXXFLAGS:-g%=-g3) + CXXFLAGS := $(CXXFLAGS:-O%=-O1) + CXXFLAGS := $(CXXFLAGS:-xO%=-xO1) + ifeq ($(findstring -DCRYPTOPP_COVERAGE,$(CXXFLAGS)),) + CXXFLAGS += -DCRYPTOPP_COVERAGE + endif # -DCRYPTOPP_COVERAGE +endif # Valgrind + +# Debug testing on GNU systems. Triggered by -DDEBUG. +# Newlib test due to http://sourceware.org/bugzilla/show_bug.cgi?id=20268 +ifneq ($(filter -DDEBUG -DDEBUG=1,$(CXXFLAGS)),) + USING_GLIBCXX := $(shell $(CXX) $(CXXFLAGS) -E pch.cpp 2>&1 | $(GREP) -i -c "__GLIBCXX__") + ifneq ($(USING_GLIBCXX),0) + ifeq ($(HAS_NEWLIB),0) + ifeq ($(findstring -D_GLIBCXX_DEBUG,$(CXXFLAGS)),) + CXXFLAGS += -D_GLIBCXX_DEBUG + endif # CXXFLAGS + endif # HAS_NEWLIB + endif # USING_GLIBCXX +endif # GNU Debug build + +# Dead code stripping. Issue 'make lean'. +ifeq ($(findstring lean,$(MAKECMDGOALS)),lean) + ifeq ($(findstring -ffunction-sections,$(CXXFLAGS)),) + CXXFLAGS += -ffunction-sections + endif # CXXFLAGS + ifeq ($(findstring -fdata-sections,$(CXXFLAGS)),) + CXXFLAGS += -fdata-sections + endif # CXXFLAGS + ifneq ($(IS_IOS),0) + ifeq ($(findstring -Wl,-dead_strip,$(LDFLAGS)),) + LDFLAGS += -Wl,-dead_strip + endif # CXXFLAGS + else # BSD, Linux and Unix + ifeq ($(findstring -Wl,--gc-sections,$(LDFLAGS)),) + LDFLAGS += -Wl,--gc-sections + endif # LDFLAGS + endif # MAKECMDGOALS +endif # Dead code stripping + +########################################################### +##### Source and object files ##### +########################################################### + +# List cryptlib.cpp first, then cpu.cpp, then integer.cpp to tame C++ static initialization problems. +SRCS := cryptlib.cpp cpu.cpp integer.cpp $(filter-out cryptlib.cpp cpu.cpp integer.cpp pch.cpp simple.cpp,$(sort $(wildcard *.cpp))) +# For Makefile.am; resource.h is Windows +INCL := $(filter-out resource.h,$(sort $(wildcard *.h))) + +# Cryptogams source files. We couple to ARMv7. +# Limit to Linux. The source files target the GNU assembler. +# Also see https://www.cryptopp.com/wiki/Cryptogams. +ifeq ($(IS_ARM32)$(IS_LINUX),11) + ifeq ($(CLANG_COMPILER),1) + CRYPTOGAMS_ARMV4_FLAG = -march=armv7-a -Wa,--noexecstack + CRYPTOGAMS_ARMV4_THUMB_FLAG = -march=armv7-a -mthumb -Wa,--noexecstack + else + CRYPTOGAMS_ARMV4_FLAG = -march=armv7-a -Wa,--noexecstack + CRYPTOGAMS_ARMV4_THUMB_FLAG = -march=armv7-a -Wa,--noexecstack + endif + SRCS += aes_armv4.S sha1_armv4.S sha256_armv4.S sha512_armv4.S +endif + +# Remove unneeded arch specific files to speed build time. +ifeq ($(IS_PPC32)$(IS_PPC64),00) + SRCS := $(filter-out ppc_%,$(SRCS)) +endif +ifeq ($(IS_ARM32)$(IS_ARMV8),00) + SRCS := $(filter-out arm_%,$(SRCS)) + SRCS := $(filter-out neon_%,$(SRCS)) +endif +ifeq ($(IS_X86)$(IS_X32)$(IS_X64),000) + SRCS := $(filter-out sse_%,$(SRCS)) +endif + +# List cryptlib.cpp first, then cpu.cpp, then integer.cpp to tame C++ static initialization problems. +OBJS := $(SRCS:.cpp=.o) +OBJS := $(OBJS:.S=.o) + +# List test.cpp first to tame C++ static initialization problems. +TESTSRCS := adhoc.cpp test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp dlltest.cpp fipsalgt.cpp validat0.cpp validat1.cpp validat2.cpp validat3.cpp validat4.cpp validat5.cpp validat6.cpp validat7.cpp validat8.cpp validat9.cpp validat10.cpp regtest1.cpp regtest2.cpp regtest3.cpp regtest4.cpp +TESTINCL := bench.h factory.h validate.h + +# Test objects +TESTOBJS := $(TESTSRCS:.cpp=.o) +LIBOBJS := $(filter-out $(TESTOBJS),$(OBJS)) + +# Clean recipe, Issue 998. Don't filter-out some artifacts from the list of objects +# The *.S is a hack. It makes the ASM appear like C++ so the object files make the CLEAN_OBJS list +CLEAN_SRCS := $(wildcard *.cpp) $(patsubst %.S,%.cpp,$(wildcard *.S)) +CLEAN_OBJS := $(CLEAN_SRCS:.cpp=.o) $(CLEAN_SRCS:.cpp=.import.o) $(CLEAN_SRCS:.cpp=.export.o) + +# For Shared Objects, Diff, Dist/Zip rules +LIB_VER := $(shell $(GREP) "define CRYPTOPP_VERSION" config_ver.h | cut -d" " -f 3) +LIB_MAJOR := $(shell echo $(LIB_VER) | cut -c 1) +LIB_MINOR := $(shell echo $(LIB_VER) | cut -c 2) +LIB_PATCH := $(shell echo $(LIB_VER) | cut -c 3) + +ifeq ($(strip $(LIB_PATCH)),) +LIB_PATCH := 0 +endif + +ifeq ($(HAS_SOLIB_VERSION),1) +# Full version suffix for shared library +SOLIB_VERSION_SUFFIX=.$(LIB_MAJOR).$(LIB_MINOR).$(LIB_PATCH) +# Different patchlevels and minors are compatible since 6.1 +SOLIB_COMPAT_SUFFIX=.$(LIB_MAJOR) +SOLIB_FLAGS=-Wl,-soname,libcryptopp.so$(SOLIB_COMPAT_SUFFIX) +endif # HAS_SOLIB_VERSION + +########################################################### +##### Targets and Recipes ##### +########################################################### + +# Default builds program with static library only +.PHONY: default +default: cryptest.exe + +.PHONY: all static dynamic +all: static dynamic cryptest.exe + +ifneq ($(IS_IOS),0) +static: libcryptopp.a +shared dynamic dylib: libcryptopp.dylib +else +static: libcryptopp.a +shared dynamic: libcryptopp.so$(SOLIB_VERSION_SUFFIX) +endif + +.PHONY: test check +test check: cryptest.exe + ./cryptest.exe v + +# CXXFLAGS are tuned earlier. Applications must use linker flags +# -Wl,--gc-sections (Linux and Unix) or -Wl,-dead_strip (OS X) +.PHONY: lean +lean: static dynamic cryptest.exe + +.PHONY: clean +clean: + -$(RM) adhoc.cpp.o adhoc.cpp.proto.o $(CLEAN_OBJS) $(ANDROID_CPU_OBJ) rdrand-*.o + @-$(RM) libcryptopp.a libcryptopp.dylib cryptopp.dll libcryptopp.dll.a libcryptopp.import.a + @-$(RM) libcryptopp.so libcryptopp.so$(SOLIB_COMPAT_SUFFIX) libcryptopp.so$(SOLIB_VERSION_SUFFIX) + @-$(RM) cryptest.exe dlltest.exe cryptest.import.exe cryptest.dat ct et + @-$(RM) *.la *.lo *.gcov *.gcno *.gcda *.stackdump core core-* + @-$(RM) /tmp/adhoc.exe + @-$(RM) -r /tmp/cryptopp_test/ + @-$(RM) -r *.exe.dSYM/ + @-$(RM) -r *.dylib.dSYM/ + @-$(RM) -r cov-int/ + +.PHONY: autotools-clean +autotools-clean: + @-$(RM) -f configure.ac configure configure.in Makefile.am Makefile.in Makefile + @-$(RM) -f config.guess config.status config.sub config.h.in compile depcomp + @-$(RM) -f install-sh stamp-h1 ar-lib *.lo *.la *.m4 local.* lt*.sh missing + @-$(RM) -f cryptest cryptestcwd libtool* libcryptopp.la libcryptopp.pc* + @-$(RM) -rf build-aux/ m4/ auto*.cache/ .deps/ .libs/ + +.PHONY: cmake-clean +cmake-clean: + @-$(RM) -f cryptopp-config.cmake CMakeLists.txt + @-$(RM) -rf cmake_build/ + +.PHONY: android-clean +android-clean: + @-$(RM) -f $(patsubst %_simd.cpp,%_simd.cpp.neon,$(wildcard *_simd.cpp)) + @-$(RM) -rf obj/ + +.PHONY: distclean +distclean: clean autotools-clean cmake-clean android-clean + -$(RM) adhoc.cpp adhoc.cpp.copied GNUmakefile.deps benchmarks.html cryptest.txt + -$(RM) cryptest_all.info cryptest_debug.info cryptest_noasm.info cryptest_base.info cryptest.info cryptest_release.info + @-$(RM) cryptest-*.txt cryptopp.tgz libcryptopp.pc *.o *.bc *.ii *~ + @-$(RM) -r cryptlib.lib cryptest.exe *.suo *.sdf *.pdb Win32/ x64/ ipch/ + @-$(RM) -r $(LIBOBJS:.o=.obj) $(TESTOBJS:.o=.obj) + @-$(RM) -r $(LIBOBJS:.o=.lst) $(TESTOBJS:.o=.lst) + @-$(RM) -r TestCoverage/ ref*/ + @-$(RM) cryptopp$(LIB_VER)\.* CryptoPPRef.zip + +# Install cryptest.exe, libcryptopp.a and libcryptopp.so. +# The library install was broken-out into its own recipe at GH #653. +.PHONY: install +install: cryptest.exe install-lib + @-$(MKDIR) $(DESTDIR)$(BINDIR) + $(CP) cryptest.exe $(DESTDIR)$(BINDIR) + $(CHMOD) u=rwx,go=rx $(DESTDIR)$(BINDIR)/cryptest.exe + @-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestData + @-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestVectors + $(CP) TestData/*.dat $(DESTDIR)$(DATADIR)/cryptopp/TestData + $(CHMOD) u=rw,go=r $(DESTDIR)$(DATADIR)/cryptopp/TestData/*.dat + $(CP) TestVectors/*.txt $(DESTDIR)$(DATADIR)/cryptopp/TestVectors + $(CHMOD) u=rw,go=r $(DESTDIR)$(DATADIR)/cryptopp/TestVectors/*.txt + +# A recipe to install only the library, and not cryptest.exe. Also +# see https://github.com/weidai11/cryptopp/issues/653. +.PHONY: install-lib +install-lib: + @-$(MKDIR) $(DESTDIR)$(INCLUDEDIR)/cryptopp + $(CP) *.h $(DESTDIR)$(INCLUDEDIR)/cryptopp + $(CHMOD) u=rw,go=r $(DESTDIR)$(INCLUDEDIR)/cryptopp/*.h +ifneq ($(wildcard libcryptopp.a),) + @-$(MKDIR) $(DESTDIR)$(LIBDIR) + $(CP) libcryptopp.a $(DESTDIR)$(LIBDIR) + $(CHMOD) u=rw,go=r $(DESTDIR)$(LIBDIR)/libcryptopp.a +endif +ifneq ($(wildcard libcryptopp.dylib),) + @-$(MKDIR) $(DESTDIR)$(LIBDIR) + $(CP) libcryptopp.dylib $(DESTDIR)$(LIBDIR) + $(CHMOD) u=rwx,go=rx $(DESTDIR)$(LIBDIR)/libcryptopp.dylib + -install_name_tool -id $(DESTDIR)$(LIBDIR)/libcryptopp.dylib $(DESTDIR)$(LIBDIR)/libcryptopp.dylib +endif +ifneq ($(wildcard libcryptopp.so$(SOLIB_VERSION_SUFFIX)),) + @-$(MKDIR) $(DESTDIR)$(LIBDIR) + $(CP) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR) + $(CHMOD) u=rwx,go=rx $(DESTDIR)$(LIBDIR)/libcryptopp.so$(SOLIB_VERSION_SUFFIX) +ifeq ($(HAS_SOLIB_VERSION),1) + -$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)/libcryptopp.so + $(LDCONF) $(DESTDIR)$(LIBDIR) +endif +endif +ifneq ($(wildcard libcryptopp.pc),) + @-$(MKDIR) $(DESTDIR)$(LIBDIR)/pkgconfig + $(CP) libcryptopp.pc $(DESTDIR)$(LIBDIR)/pkgconfig + $(CHMOD) u=rw,go=r $(DESTDIR)$(LIBDIR)/pkgconfig/libcryptopp.pc +endif + +.PHONY: remove uninstall +remove uninstall: + -$(RM) -r $(DESTDIR)$(INCLUDEDIR)/cryptopp + -$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.a + -$(RM) $(DESTDIR)$(BINDIR)/cryptest.exe + @-$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.dylib + @-$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.so$(SOLIB_VERSION_SUFFIX) + @-$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.so$(SOLIB_COMPAT_SUFFIX) + @-$(RM) $(DESTDIR)$(LIBDIR)/libcryptopp.so + +libcryptopp.a: $(LIBOBJS) $(ANDROID_CPU_OBJ) + $(AR) $(ARFLAGS) $@ $(LIBOBJS) $(ANDROID_CPU_OBJ) + $(RANLIB) $@ + +ifeq ($(HAS_SOLIB_VERSION),1) +.PHONY: libcryptopp.so +libcryptopp.so: libcryptopp.so$(SOLIB_VERSION_SUFFIX) +endif + +libcryptopp.so$(SOLIB_VERSION_SUFFIX): $(LIBOBJS) $(ANDROID_CPU_OBJ) + $(CXX) -shared $(SOLIB_FLAGS) -o $@ $(strip $(CPPFLAGS) $(CXXFLAGS)) -Wl,--exclude-libs,ALL $(LIBOBJS) $(ANDROID_CPU_OBJ) $(LDFLAGS) $(LDLIBS) +ifeq ($(HAS_SOLIB_VERSION),1) + -$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) libcryptopp.so + -$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) libcryptopp.so$(SOLIB_COMPAT_SUFFIX) +endif + +libcryptopp.dylib: $(LIBOBJS) + $(CXX) -dynamiclib -o $@ $(strip $(CPPFLAGS) $(CXXFLAGS)) -install_name "$@" -current_version "$(LIB_MAJOR).$(LIB_MINOR).$(LIB_PATCH)" -compatibility_version "$(LIB_MAJOR).$(LIB_MINOR)" -headerpad_max_install_names $(LDFLAGS) $(LIBOBJS) + +cryptest.exe: $(LINK_LIBRARY) $(TESTOBJS) + $(CXX) -o $@ $(strip $(CPPFLAGS) $(CXXFLAGS)) $(TESTOBJS) $(LINK_LIBRARY_PATH)$(LINK_LIBRARY) $(LDFLAGS) $(LDLIBS) + +# Used to generate list of source files for Autotools, CMakeList and Android.mk +.PHONY: sources +sources: + $(info ***** Library sources *****) + $(info $(filter-out $(TESTSRCS),$(SRCS))) + $(info ) + $(info ***** Library headers *****) + $(info $(filter-out $(TESTINCL),$(INCL))) + $(info ) + $(info ***** Test sources *****) + $(info $(TESTSRCS)) + $(info ) + $(info ***** Test headers *****) + $(info $(TESTINCL)) + +adhoc.cpp: adhoc.cpp.proto +ifeq ($(wildcard adhoc.cpp),) + cp adhoc.cpp.proto adhoc.cpp +else + touch adhoc.cpp +endif + +# Include dependencies, if present. You must issue `make deps` to create them. +ifeq ($(wildcard GNUmakefile.deps),GNUmakefile.deps) +-include GNUmakefile.deps +endif # Dependencies + +# A few recipes trigger warnings for -std=c++11 and -stdlib=c++ +NOSTD_CXXFLAGS=$(filter-out -stdlib=%,$(filter-out -std=%,$(CXXFLAGS))) + +# Cryptogams ARM asm implementation. AES needs -mthumb for Clang +aes_armv4.o : aes_armv4.S + $(CXX) $(strip $(CPPFLAGS) $(NOSTD_CXXFLAGS) $(CRYPTOGAMS_ARMV4_THUMB_FLAG) -c) $< + +# Use C++ compiler on C source after patching. +# https://github.com/weidai11/cryptopp/issues/926 +cpu-features.o: cpu-features.h cpu-features.c + $(CXX) -x c $(strip $(CPPFLAGS) $(NOSTD_CXXFLAGS) -c) cpu-features.c + +# SSSE3 or NEON available +aria_simd.o : aria_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(ARIA_FLAG) -c) $< + +# SSE, NEON or POWER7 available +blake2s_simd.o : blake2s_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(BLAKE2S_FLAG) -c) $< + +# SSE, NEON or POWER8 available +blake2b_simd.o : blake2b_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(BLAKE2B_FLAG) -c) $< + +# SSE2 or NEON available +chacha_simd.o : chacha_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(CHACHA_FLAG) -c) $< + +# AVX2 available +chacha_avx.o : chacha_avx.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(CHACHA_AVX2_FLAG) -c) $< + +# SSSE3 available +cham_simd.o : cham_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(CHAM_FLAG) -c) $< + +# Power9 available +darn.o : darn.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(DARN_FLAG) -c) $< + +# SSE2 on i686 +donna_sse.o : donna_sse.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SSE2_FLAG) -c) $< + +# SSE2 on i686 +sse_simd.o : sse_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SSE2_FLAG) -c) $< + +# SSE4.2 or ARMv8a available +crc_simd.o : crc_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(CRC_FLAG) -c) $< + +# PCLMUL or ARMv7a/ARMv8a available +gcm_simd.o : gcm_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(GCM_FLAG) -c) $< + +# Carryless multiply +gf2n_simd.o : gf2n_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(GF2N_FLAG) -c) $< + +# SSSE3 available +keccak_simd.o : keccak_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(KECCAK_FLAG) -c) $< + +# SSSE3 available +lea_simd.o : lea_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LEA_FLAG) -c) $< + +# SSSE3 available +lsh256_sse.o : lsh256_sse.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LSH256_FLAG) -c) $< + +# AVX2 available +lsh256_avx.o : lsh256_avx.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LSH256_AVX2_FLAG) -c) $< + +# SSSE3 available +lsh512_sse.o : lsh512_sse.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LSH512_FLAG) -c) $< + +# AVX2 available +lsh512_avx.o : lsh512_avx.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(LSH512_AVX2_FLAG) -c) $< + +# NEON available +neon_simd.o : neon_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(NEON_FLAG) -c) $< + +# AESNI or ARMv7a/ARMv8a available +rijndael_simd.o : rijndael_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(AES_FLAG) -c) $< + +# SSE4.2/SHA-NI or ARMv8a available +sha_simd.o : sha_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SHA_FLAG) -c) $< + +# Cryptogams SHA1 asm implementation. +sha1_armv4.o : sha1_armv4.S + $(CXX) $(strip $(CPPFLAGS) $(NOSTD_CXXFLAGS) $(CRYPTOGAMS_ARMV4_FLAG) -c) $< + +# Cryptogams SHA256 asm implementation. +sha256_armv4.o : sha256_armv4.S + $(CXX) $(strip $(CPPFLAGS) $(NOSTD_CXXFLAGS) $(CRYPTOGAMS_ARMV4_FLAG) -c) $< + +# Cryptogams SHA512 asm implementation. +sha512_armv4.o : sha512_armv4.S + $(CXX) $(strip $(CPPFLAGS) $(NOSTD_CXXFLAGS) $(CRYPTOGAMS_ARMV4_FLAG) -c) $< + +# SSE4.2/SHA-NI or ARMv8a available +shacal2_simd.o : shacal2_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SHA_FLAG) -c) $< + +# SSSE3, NEON or POWER8 available +simon128_simd.o : simon128_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SIMON128_FLAG) -c) $< + +# SSSE3, NEON or POWER8 available +speck128_simd.o : speck128_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SPECK128_FLAG) -c) $< + +# ARMv8.4 available +sm3_simd.o : sm3_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SM3_FLAG) -c) $< + +# AESNI available +sm4_simd.o : sm4_simd.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) $(SM4_FLAG) -c) $< + +%.o : %.cpp + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS) -c) $< + +.PHONY: dep deps depend +dep deps depend GNUmakefile.deps: + $(CXX) $(strip $(CPPFLAGS) $(CXXFLAGS)) -MM *.cpp > GNUmakefile.deps diff --git a/external/ours/library/crypto/src/shared/original/adhoc.cpp b/external/ours/library/crypto/src/shared/original/adhoc.cpp new file mode 100755 index 000000000..1fc8c3017 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/adhoc.cpp @@ -0,0 +1,42 @@ +#include "config.h" +#include +#include + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4100 4189 4996) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +USING_NAMESPACE(CryptoPP) +USING_NAMESPACE(std) + +#ifndef CRYPTOPP_UNUSED +# define CRYPTOPP_UNUSED(x) (void(x)) +#endif + +// Used for testing the compiler and linker in cryptest.sh +#if defined(CRYPTOPP_ADHOC_MAIN) || defined(ADHOC_MAIN) + +int main(int argc, char *argv[]) +{ + CRYPTOPP_UNUSED(argc), CRYPTOPP_UNUSED(argv); + return 0; +} + +// Classic use of adhoc to setup calling convention +#else + +extern int (*AdhocTest)(int argc, char *argv[]); + +int MyAdhocTest(int argc, char *argv[]) +{ + CRYPTOPP_UNUSED(argc), CRYPTOPP_UNUSED(argv); + return 0; +} + +static int s_i = (AdhocTest = &MyAdhocTest, 0); + +#endif diff --git a/external/ours/library/crypto/src/shared/original/adler32.cpp b/external/ours/library/crypto/src/shared/original/adler32.cpp new file mode 100755 index 000000000..2cfb1f447 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/adler32.cpp @@ -0,0 +1,82 @@ +// adler32.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "adler32.h" + +NAMESPACE_BEGIN(CryptoPP) + +void Adler32::Update(const byte *input, size_t length) +{ + const unsigned long BASE = 65521; + + unsigned long s1 = m_s1; + unsigned long s2 = m_s2; + + if (length % 8 != 0) + { + do + { + s1 += *input++; + s2 += s1; + length--; + } while (length % 8 != 0); + + if (s1 >= BASE) + s1 -= BASE; + s2 %= BASE; + } + + while (length > 0) + { + s1 += input[0]; s2 += s1; + s1 += input[1]; s2 += s1; + s1 += input[2]; s2 += s1; + s1 += input[3]; s2 += s1; + s1 += input[4]; s2 += s1; + s1 += input[5]; s2 += s1; + s1 += input[6]; s2 += s1; + s1 += input[7]; s2 += s1; + + length -= 8; + input += 8; + + if (s1 >= BASE) + s1 -= BASE; + if (length % 0x8000 == 0) + s2 %= BASE; + } + + CRYPTOPP_ASSERT(s1 < BASE); + CRYPTOPP_ASSERT(s2 < BASE); + + m_s1 = (word16)s1; + m_s2 = (word16)s2; +} + +void Adler32::TruncatedFinal(byte *hash, size_t size) +{ + ThrowIfInvalidTruncatedSize(size); + + switch (size) + { + default: + hash[3] = byte(m_s1); + // fall through + case 3: + hash[2] = byte(m_s1 >> 8); + // fall through + case 2: + hash[1] = byte(m_s2); + // fall through + case 1: + hash[0] = byte(m_s2 >> 8); + // fall through + case 0: + ; + // fall through + } + + Reset(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/adler32.h b/external/ours/library/crypto/src/shared/original/adler32.h new file mode 100755 index 000000000..a50d126e0 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/adv_simd.h b/external/ours/library/crypto/src/shared/original/adv_simd.h new file mode 100755 index 000000000..0b65691d9 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/aes.h b/external/ours/library/crypto/src/shared/original/aes.h new file mode 100755 index 000000000..72ff2ccca --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/aes_armv4.h b/external/ours/library/crypto/src/shared/original/aes_armv4.h new file mode 100755 index 000000000..2c2eec72c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/algebra.cpp b/external/ours/library/crypto/src/shared/original/algebra.cpp new file mode 100755 index 000000000..c3b3fdc1e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/algebra.cpp @@ -0,0 +1,341 @@ +// algebra.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_ALGEBRA_CPP // SunCC workaround: compiler could cause this file to be included twice +#define CRYPTOPP_ALGEBRA_CPP + +#include "algebra.h" +#include "integer.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +template const T& AbstractGroup::Double(const Element &a) const +{ + return this->Add(a, a); +} + +template const T& AbstractGroup::Subtract(const Element &a, const Element &b) const +{ + // make copy of a in case Inverse() overwrites it + Element a1(a); + return this->Add(a1, Inverse(b)); +} + +template T& AbstractGroup::Accumulate(Element &a, const Element &b) const +{ + return a = this->Add(a, b); +} + +template T& AbstractGroup::Reduce(Element &a, const Element &b) const +{ + return a = this->Subtract(a, b); +} + +template const T& AbstractRing::Square(const Element &a) const +{ + return this->Multiply(a, a); +} + +template const T& AbstractRing::Divide(const Element &a, const Element &b) const +{ + // make copy of a in case MultiplicativeInverse() overwrites it + Element a1(a); + return this->Multiply(a1, this->MultiplicativeInverse(b)); +} + +template const T& AbstractEuclideanDomain::Mod(const Element &a, const Element &b) const +{ + Element q; + this->DivisionAlgorithm(result, q, a, b); + return result; +} + +template const T& AbstractEuclideanDomain::Gcd(const Element &a, const Element &b) const +{ + Element g[3]={b, a}; + unsigned int i0=0, i1=1, i2=2; + + while (!this->Equal(g[i1], this->Identity())) + { + g[i2] = this->Mod(g[i0], g[i1]); + unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; + } + + return result = g[i0]; +} + +template const typename QuotientRing::Element& QuotientRing::MultiplicativeInverse(const Element &a) const +{ + Element g[3]={m_modulus, a}; + Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()}; + Element y; + unsigned int i0=0, i1=1, i2=2; + + while (!this->Equal(g[i1], this->Identity())) + { + // y = g[i0] / g[i1]; + // g[i2] = g[i0] % g[i1]; + m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]); + // v[i2] = v[i0] - (v[i1] * y); + v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y)); + unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; + } + + return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Identity(); +} + +template T AbstractGroup::ScalarMultiply(const Element &base, const Integer &exponent) const +{ + Element result; + this->SimultaneousMultiply(&result, base, &exponent, 1); + return result; +} + +template T AbstractGroup::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const +{ + const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount()); + if (expLen==0) + return this->Identity(); + + const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3)); + const unsigned tableSize = 1< powerTable(tableSize << w); + + powerTable[1] = x; + powerTable[tableSize] = y; + if (w==1) + powerTable[3] = this->Add(x,y); + else + { + powerTable[2] = this->Double(x); + powerTable[2*tableSize] = this->Double(y); + + unsigned i, j; + + for (i=3; i=0; i--) + { + power1 = 2*power1 + e1.GetBit(i); + power2 = 2*power2 + e2.GetBit(i); + + if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize) + { + unsigned squaresBefore = prevPosition-i; + unsigned squaresAfter = 0; + prevPosition = i; + while ((power1 || power2) && power1%2 == 0 && power2%2==0) + { + power1 /= 2; + power2 /= 2; + squaresBefore--; + squaresAfter++; + } + if (firstTime) + { + result = powerTable[(power2<Double(result); + if (power1 || power2) + Accumulate(result, powerTable[(power2<Double(result); + power1 = power2 = 0; + } + } + return result; +} + +template Element GeneralCascadeMultiplication(const AbstractGroup &group, Iterator begin, Iterator end) +{ + if (end-begin == 1) + return group.ScalarMultiply(begin->base, begin->exponent); + else if (end-begin == 2) + return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent); + else + { + Integer q, t; + Iterator last = end; + --last; + + std::make_heap(begin, end); + std::pop_heap(begin, end); + + while (!!begin->exponent) + { + // last->exponent is largest exponent, begin->exponent is next largest + t = last->exponent; + Integer::Divide(last->exponent, q, t, begin->exponent); + + if (q == Integer::One()) + group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply() + else + group.Accumulate(begin->base, group.ScalarMultiply(last->base, q)); + + std::push_heap(begin, end); + std::pop_heap(begin, end); + } + + return group.ScalarMultiply(last->base, last->exponent); + } +} + +struct WindowSlider +{ + WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0) + : exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn), windowBegin(0), expWindow(0) + , fastNegate(fastNegate), negateNext(false), firstTime(true), finished(false) + { + if (windowSize == 0) + { + unsigned int expLen = exp.BitCount(); + windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 : (expLen <= 1434 ? 6 : 7))))); + } + windowModulus <<= windowSize; + } + + void FindNextWindow() + { + unsigned int expLen = exp.WordCount() * WORD_BITS; + unsigned int skipCount = firstTime ? 0 : windowSize; + firstTime = false; + while (!exp.GetBit(skipCount)) + { + if (skipCount >= expLen) + { + finished = true; + return; + } + skipCount++; + } + + exp >>= skipCount; + windowBegin += skipCount; + expWindow = word32(exp % (word(1) << windowSize)); + + if (fastNegate && exp.GetBit(windowSize)) + { + negateNext = true; + expWindow = (word32(1) << windowSize) - expWindow; + exp += windowModulus; + } + else + negateNext = false; + } + + Integer exp, windowModulus; + unsigned int windowSize, windowBegin; + word32 expWindow; + bool fastNegate, negateNext, firstTime, finished; +}; + +template +void AbstractGroup::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const +{ + std::vector > buckets(expCount); + std::vector exponents; + exponents.reserve(expCount); + unsigned int i; + + for (i=0; expBegin && iNotNegative()); + exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0)); + exponents[i].FindNextWindow(); + buckets[i].resize(((size_t) 1) << (exponents[i].windowSize-1), Identity()); + } + + unsigned int expBitPosition = 0; + Element g = base; + bool notDone = true; + + while (notDone) + { + notDone = false; + for (i=0; i 1) + { + for (int j = (int)buckets[i].size()-2; j >= 1; j--) + { + Accumulate(buckets[i][j], buckets[i][j+1]); + Accumulate(r, buckets[i][j]); + } + Accumulate(buckets[i][0], buckets[i][1]); + r = Add(Double(r), buckets[i][0]); + } + } +} + +template T AbstractRing::Exponentiate(const Element &base, const Integer &exponent) const +{ + Element result; + SimultaneousExponentiate(&result, base, &exponent, 1); + return result; +} + +template T AbstractRing::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const +{ + return MultiplicativeGroup().AbstractGroup::CascadeScalarMultiply(x, e1, y, e2); +} + +template Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end) +{ + return GeneralCascadeMultiplication(ring.MultiplicativeGroup(), begin, end); +} + +template +void AbstractRing::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const +{ + MultiplicativeGroup().AbstractGroup::SimultaneousMultiply(results, base, exponents, expCount); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/algebra.h b/external/ours/library/crypto/src/shared/original/algebra.h new file mode 100755 index 000000000..9326ec6fc --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/algparam.cpp b/external/ours/library/crypto/src/shared/original/algparam.cpp new file mode 100755 index 000000000..ff394f212 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/algparam.cpp @@ -0,0 +1,75 @@ +// algparam.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "algparam.h" +#include "integer.h" + +NAMESPACE_BEGIN(CryptoPP) + +bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (strcmp(name, "ValueNames") == 0) + return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue); + else + return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue); +} + +void AlgorithmParametersBase::operator=(const AlgorithmParametersBase &rhs) +{ + CRYPTOPP_UNUSED(rhs); + CRYPTOPP_ASSERT(false); +} + +bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (strcmp(name, "ValueNames") == 0) + { + NameValuePairs::ThrowIfTypeMismatch(name, typeid(std::string), valueType); + if (m_next.get()) + m_next->GetVoidValue(name, valueType, pValue); + (*reinterpret_cast(pValue) += m_name) += ";"; + return true; + } + else if (strcmp(name, m_name) == 0) + { + AssignValue(name, valueType, pValue); + m_used = true; + return true; + } + else if (m_next.get()) + return m_next->GetVoidValue(name, valueType, pValue); + else + return false; +} + +AlgorithmParameters::AlgorithmParameters() + : m_defaultThrowIfNotUsed(true) +{ +} + +AlgorithmParameters::AlgorithmParameters(const AlgorithmParameters &x) + : m_defaultThrowIfNotUsed(x.m_defaultThrowIfNotUsed) +{ + m_next.reset(const_cast(x).m_next.release()); +} + +AlgorithmParameters & AlgorithmParameters::operator=(const AlgorithmParameters &x) +{ + m_next.reset(const_cast(x).m_next.release()); + return *this; +} + +bool AlgorithmParameters::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (m_next.get()) + return m_next->GetVoidValue(name, valueType, pValue); + else + return false; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/algparam.h b/external/ours/library/crypto/src/shared/original/algparam.h new file mode 100755 index 000000000..f904c4f93 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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) && (_MSC_VER >= 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) && (_MSC_VER >= 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/external/ours/library/crypto/src/shared/original/allocate.cpp b/external/ours/library/crypto/src/shared/original/allocate.cpp new file mode 100755 index 000000000..745eb7811 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/allocate.cpp @@ -0,0 +1,107 @@ +// allocate.cpp - 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. + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "allocate.h" +#include "stdcpp.h" +#include "misc.h" +#include "trap.h" + +// for memalign +#if defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE) || defined(QNX) +# include +#endif +// for posix_memalign +#if defined(CRYPTOPP_POSIX_MEMALIGN_AVAILABLE) +# include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +void CallNewHandler() +{ + using std::new_handler; + using std::set_new_handler; + + new_handler newHandler = set_new_handler(NULLPTR); + if (newHandler) + set_new_handler(newHandler); + + if (newHandler) + newHandler(); + else + throw std::bad_alloc(); +} + +void * AlignedAllocate(size_t size) +{ + byte *p; +#if defined(CRYPTOPP_MM_MALLOC_AVAILABLE) + while ((p = (byte *)_mm_malloc(size, 16)) == NULLPTR) +#elif defined(CRYPTOPP_MEMALIGN_AVAILABLE) + while ((p = (byte *)memalign(16, size)) == NULLPTR) +#elif defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16) + while ((p = (byte *)malloc(size)) == NULLPTR) +#elif defined(CRYPTOPP_POSIX_MEMALIGN_AVAILABLE) + while (posix_memalign(reinterpret_cast(&p), 16, size) != 0) +#else + while ((p = (byte *)malloc(size + 16)) == NULLPTR) +#endif + CallNewHandler(); + +#ifdef CRYPTOPP_NO_ALIGNED_ALLOC + size_t adjustment = 16-((size_t)p%16); + CRYPTOPP_ASSERT(adjustment > 0); + p += adjustment; + p[-1] = (byte)adjustment; +#endif + + // If this assert fires then there are problems that need + // to be fixed. Please open a bug report. + CRYPTOPP_ASSERT(IsAlignedOn(p, 16)); + return p; +} + +void AlignedDeallocate(void *p) +{ + // Guard pointer due to crash on AIX when CRYPTOPP_NO_ALIGNED_ALLOC + // is in effect. The guard was previously in place in SecBlock, + // but it was removed at f4d68353ca7c as part of GH #875. + CRYPTOPP_ASSERT(p); + + if (p != NULLPTR) + { +#ifdef CRYPTOPP_MM_MALLOC_AVAILABLE + _mm_free(p); +#elif defined(CRYPTOPP_NO_ALIGNED_ALLOC) + p = (byte *)p - ((byte *)p)[-1]; + free(p); +#else + free(p); +#endif + } +} + +void * UnalignedAllocate(size_t size) +{ + void *p; + while ((p = malloc(size)) == NULLPTR) + CallNewHandler(); + return p; +} + +void UnalignedDeallocate(void *p) +{ + free(p); +} + +NAMESPACE_END + +#endif // CRYPTOPP_IMPORTS diff --git a/external/ours/library/crypto/src/shared/original/allocate.h b/external/ours/library/crypto/src/shared/original/allocate.h new file mode 100755 index 000000000..64e1ac79f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/arc4.cpp b/external/ours/library/crypto/src/shared/original/arc4.cpp new file mode 100755 index 000000000..2bc2dd1fd --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/arc4.cpp @@ -0,0 +1,122 @@ +// arc4.cpp - originally written and placed in the public domain by Wei Dai + +// The ARC4 algorithm was first revealed in an anonymous email to the +// cypherpunks mailing list. This file originally contained some +// code copied from this email. The code has since been rewritten in order +// to clarify the copyright status of this file. It should now be +// completely in the public domain. + +#include "pch.h" +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 +#include "arc4.h" + +NAMESPACE_BEGIN(CryptoPP) +namespace Weak1 { + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void ARC4_TestInstantiations() +{ + ARC4 x; +} +#endif + +ARC4_Base::~ARC4_Base() +{ + m_x = m_y = 0; +} + +void ARC4_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + AssertValidKeyLength(length); + + m_x = 1; + m_y = 0; + + unsigned int i; + for (i=0; i<256; i++) + m_state[i] = byte(i); + + unsigned int keyIndex = 0, stateIndex = 0; + for (i=0; i<256; i++) + { + unsigned int a = m_state[i]; + stateIndex += key[keyIndex] + a; + stateIndex &= 0xff; + m_state[i] = m_state[stateIndex]; + m_state[stateIndex] = byte(a); + if (++keyIndex >= length) + keyIndex = 0; + } + + int discardBytes = params.GetIntValueWithDefault("DiscardBytes", GetDefaultDiscardBytes()); + DiscardBytes(discardBytes); +} + +template +static inline unsigned int MakeByte(T &x, T &y, byte *s) +{ + unsigned int a = s[x]; + y = byte((y+a) & 0xff); + unsigned int b = s[y]; + s[x] = byte(b); + s[y] = byte(a); + x = byte((x+1) & 0xff); + return s[(a+b) & 0xff]; +} + +void ARC4_Base::GenerateBlock(byte *output, size_t size) +{ + while (size--) + *output++ = static_cast(MakeByte(m_x, m_y, m_state)); +} + +void ARC4_Base::ProcessData(byte *outString, const byte *inString, size_t length) +{ + if (length == 0) + return; + + byte *const s = m_state; + unsigned int x = m_x; + unsigned int y = m_y; + + if (inString == outString) + { + do + { + *outString++ ^= MakeByte(x, y, s); + } while (--length); + } + else + { + do + { + *outString++ = *inString++ ^ byte(MakeByte(x, y, s)); + } + while(--length); + } + + m_x = byte(x); + m_y = byte(y); +} + +void ARC4_Base::DiscardBytes(size_t n) +{ + if (n == 0) + return; + + byte *const s = m_state; + unsigned int x = m_x; + unsigned int y = m_y; + + do + { + MakeByte(x, y, s); + } + while(--n); + + m_x = byte(x); + m_y = byte(y); +} + +} +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/arc4.h b/external/ours/library/crypto/src/shared/original/arc4.h new file mode 100755 index 000000000..baed9e767 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/argnames.h b/external/ours/library/crypto/src/shared/original/argnames.h new file mode 100755 index 000000000..3d2859a8e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/aria.cpp b/external/ours/library/crypto/src/shared/original/aria.cpp new file mode 100755 index 000000000..bc7509fdf --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/aria.cpp @@ -0,0 +1,343 @@ +// aria.cpp - written and placed in the public domain by Jeffrey Walton + +#include "pch.h" +#include "config.h" + +#include "aria.h" +#include "misc.h" +#include "cpu.h" + +#if CRYPTOPP_SSE2_INTRIN_AVAILABLE +# define CRYPTOPP_ENABLE_ARIA_SSE2_INTRINSICS 1 +#endif + +#if CRYPTOPP_SSSE3_AVAILABLE +# define CRYPTOPP_ENABLE_ARIA_SSSE3_INTRINSICS 1 +#endif + +// GCC cast warning. Note: this is used on round key table, +// which is word32 and naturally aligned. +#define UINT32_CAST(x) ((word32 *)(void *)(x)) + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(ARIATab) + +extern const word32 S1[256]; +extern const word32 S2[256]; +extern const word32 X1[256]; +extern const word32 X2[256]; +extern const word32 KRK[3][4]; + +NAMESPACE_END +NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +using CryptoPP::ARIATab::S1; +using CryptoPP::ARIATab::S2; +using CryptoPP::ARIATab::X1; +using CryptoPP::ARIATab::X2; +using CryptoPP::ARIATab::KRK; + +inline byte ARIA_BRF(const word32 x, const int y) { + return static_cast(GETBYTE(x, y)); +} + +// Key XOR Layer +#define ARIA_KXL { \ + typedef BlockGetAndPut NativeBlock; \ + NativeBlock::Put(rk, t)(t[0])(t[1])(t[2])(t[3]); \ + } + +// S-Box Layer 1 + M +#define SBL1_M(T0,T1,T2,T3) { \ + T0=S1[ARIA_BRF(T0,3)]^S2[ARIA_BRF(T0,2)]^X1[ARIA_BRF(T0,1)]^X2[ARIA_BRF(T0,0)]; \ + T1=S1[ARIA_BRF(T1,3)]^S2[ARIA_BRF(T1,2)]^X1[ARIA_BRF(T1,1)]^X2[ARIA_BRF(T1,0)]; \ + T2=S1[ARIA_BRF(T2,3)]^S2[ARIA_BRF(T2,2)]^X1[ARIA_BRF(T2,1)]^X2[ARIA_BRF(T2,0)]; \ + T3=S1[ARIA_BRF(T3,3)]^S2[ARIA_BRF(T3,2)]^X1[ARIA_BRF(T3,1)]^X2[ARIA_BRF(T3,0)]; \ + } + +// S-Box Layer 2 + M +#define SBL2_M(T0,T1,T2,T3) { \ + T0=X1[ARIA_BRF(T0,3)]^X2[ARIA_BRF(T0,2)]^S1[ARIA_BRF(T0,1)]^S2[ARIA_BRF(T0,0)]; \ + T1=X1[ARIA_BRF(T1,3)]^X2[ARIA_BRF(T1,2)]^S1[ARIA_BRF(T1,1)]^S2[ARIA_BRF(T1,0)]; \ + T2=X1[ARIA_BRF(T2,3)]^X2[ARIA_BRF(T2,2)]^S1[ARIA_BRF(T2,1)]^S2[ARIA_BRF(T2,0)]; \ + T3=X1[ARIA_BRF(T3,3)]^X2[ARIA_BRF(T3,2)]^S1[ARIA_BRF(T3,1)]^S2[ARIA_BRF(T3,0)]; \ + } + +#define ARIA_P(T0,T1,T2,T3) { \ + (T1) = (((T1)<< 8)&0xff00ff00) ^ (((T1)>> 8)&0x00ff00ff); \ + (T2) = rotrConstant<16>(T2); \ + (T3) = ByteReverse((T3)); \ + } + +#define ARIA_M(X,Y) { \ + Y=(X)<<8 ^ (X)>>8 ^ (X)<<16 ^ (X)>>16 ^ (X)<<24 ^ (X)>>24; \ + } + +#define ARIA_MM(T0,T1,T2,T3) { \ + (T1)^=(T2); (T2)^=(T3); (T0)^=(T1); \ + (T3)^=(T1); (T2)^=(T0); (T1)^=(T2); \ + } + +#define ARIA_FO {SBL1_M(t[0],t[1],t[2],t[3]) ARIA_MM(t[0],t[1],t[2],t[3]) ARIA_P(t[0],t[1],t[2],t[3]) ARIA_MM(t[0],t[1],t[2],t[3])} +#define ARIA_FE {SBL2_M(t[0],t[1],t[2],t[3]) ARIA_MM(t[0],t[1],t[2],t[3]) ARIA_P(t[2],t[3],t[0],t[1]) ARIA_MM(t[0],t[1],t[2],t[3])} + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) +extern void ARIA_UncheckedSetKey_Schedule_NEON(byte* rk, word32* ws, unsigned int keylen); +extern void ARIA_ProcessAndXorBlock_NEON(const byte* xorBlock, byte* outblock, const byte *rk, word32 *t); +#endif + +#if (CRYPTOPP_SSSE3_AVAILABLE) +extern void ARIA_ProcessAndXorBlock_SSSE3(const byte* xorBlock, byte* outBlock, const byte *rk, word32 *t); +#endif + +// n-bit right shift of Y XORed to X +template +inline void ARIA_GSRK(const word32 X[4], const word32 Y[4], byte RK[16]) +{ + // MSVC is not generating a "rotate immediate". Constify to help it along. + static const unsigned int Q = 4-(N/32); + static const unsigned int R = N % 32; + UINT32_CAST(RK)[0] = (X[0]) ^ ((Y[(Q )%4])>>R) ^ ((Y[(Q+3)%4])<<(32-R)); + UINT32_CAST(RK)[1] = (X[1]) ^ ((Y[(Q+1)%4])>>R) ^ ((Y[(Q )%4])<<(32-R)); + UINT32_CAST(RK)[2] = (X[2]) ^ ((Y[(Q+2)%4])>>R) ^ ((Y[(Q+1)%4])<<(32-R)); + UINT32_CAST(RK)[3] = (X[3]) ^ ((Y[(Q+3)%4])>>R) ^ ((Y[(Q+2)%4])<<(32-R)); +} + +void ARIA::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + + m_rk.New(16*17); // round keys + m_w.New(4*7); // w0, w1, w2, w3, t and u + + byte *rk = m_rk.data(); + int Q, q, R, r; + + switch (keylen) + { + case 16: + R = r = m_rounds = 12; + Q = q = 0; + break; + case 32: + R = r = m_rounds = 16; + Q = q = 2; + break; + case 24: + R = r = m_rounds = 14; + Q = q = 1; + break; + default: + Q = q = R = r = m_rounds = 0; + CRYPTOPP_ASSERT(0); + } + + // w0 has room for 32 bytes. w1-w3 each has room for 16 bytes. t and u are 16 byte temp areas. + word32 *w0 = m_w.data(), *w1 = m_w.data()+8, *w2 = m_w.data()+12, *w3 = m_w.data()+16, *t = m_w.data()+20; + + GetBlockblock(key); + block(w0[0])(w0[1])(w0[2])(w0[3]); + + t[0]=w0[0]^KRK[q][0]; t[1]=w0[1]^KRK[q][1]; + t[2]=w0[2]^KRK[q][2]; t[3]=w0[3]^KRK[q][3]; + + ARIA_FO; + + if (keylen == 32) + { + block(w1[0])(w1[1])(w1[2])(w1[3]); + } + else if (keylen == 24) + { + block(w1[0])(w1[1]); w1[2] = w1[3] = 0; + } + else + { + w1[0]=w1[1]=w1[2]=w1[3]=0; + } + + w1[0]^=t[0]; w1[1]^=t[1]; w1[2]^=t[2]; w1[3]^=t[3]; + ::memcpy(t, w1, 16); + + q = (q==2) ? 0 : (q+1); + t[0]^=KRK[q][0]; t[1]^=KRK[q][1]; t[2]^=KRK[q][2]; t[3]^=KRK[q][3]; + + ARIA_FE; + + t[0]^=w0[0]; t[1]^=w0[1]; t[2]^=w0[2]; t[3]^=w0[3]; + ::memcpy(w2, t, 16); + + q = (q==2) ? 0 : (q+1); + t[0]^=KRK[q][0]; t[1]^=KRK[q][1]; t[2]^=KRK[q][2]; t[3]^=KRK[q][3]; + + ARIA_FO; + + w3[0]=t[0]^w1[0]; w3[1]=t[1]^w1[1]; w3[2]=t[2]^w1[2]; w3[3]=t[3]^w1[3]; + +#if CRYPTOPP_ARM_NEON_AVAILABLE + if (HasNEON()) + { + ARIA_UncheckedSetKey_Schedule_NEON(rk, m_w, keylen); + } + else +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + { + ARIA_GSRK<19>(w0, w1, rk + 0); + ARIA_GSRK<19>(w1, w2, rk + 16); + ARIA_GSRK<19>(w2, w3, rk + 32); + ARIA_GSRK<19>(w3, w0, rk + 48); + ARIA_GSRK<31>(w0, w1, rk + 64); + ARIA_GSRK<31>(w1, w2, rk + 80); + ARIA_GSRK<31>(w2, w3, rk + 96); + ARIA_GSRK<31>(w3, w0, rk + 112); + ARIA_GSRK<67>(w0, w1, rk + 128); + ARIA_GSRK<67>(w1, w2, rk + 144); + ARIA_GSRK<67>(w2, w3, rk + 160); + ARIA_GSRK<67>(w3, w0, rk + 176); + ARIA_GSRK<97>(w0, w1, rk + 192); + + if (keylen > 16) + { + ARIA_GSRK<97>(w1, w2, rk + 208); + ARIA_GSRK<97>(w2, w3, rk + 224); + + if (keylen > 24) + { + ARIA_GSRK< 97>(w3, w0, rk + 240); + ARIA_GSRK<109>(w0, w1, rk + 256); + } + } + } + + // Decryption operation + if (!IsForwardTransformation()) + { + word32 *a, *z, *s; + rk = m_rk.data(); + r = R; q = Q; + + a=UINT32_CAST(rk); s=m_w.data()+24; z=a+r*4; + ::memcpy(t, a, 16); ::memcpy(a, z, 16); ::memcpy(z, t, 16); + + a+=4; z-=4; + for (; a(m_rk.data()); + word32 *t = const_cast(m_w.data()+20); + + // Timing attack countermeasure. See comments in Rijndael for more details. + // We used Yun's 32-bit implementation, so we use words rather than bytes. + const int cacheLineSize = GetCacheLineSize(); + unsigned int i; + volatile word32 _u = 0; + word32 u = _u; + + for (i=0; iblock(inBlock); + block(t[0])(t[1])(t[2])(t[3]); + + if (m_rounds > 12) { + ARIA_KXL; rk+= 16; ARIA_FO; + ARIA_KXL; rk+= 16; ARIA_FE; + } + + if (m_rounds > 14) { + ARIA_KXL; rk+= 16; ARIA_FO; + ARIA_KXL; rk+= 16; ARIA_FE; + } + + ARIA_KXL; rk+= 16; ARIA_FO; ARIA_KXL; rk+= 16; ARIA_FE; + ARIA_KXL; rk+= 16; ARIA_FO; ARIA_KXL; rk+= 16; ARIA_FE; + ARIA_KXL; rk+= 16; ARIA_FO; ARIA_KXL; rk+= 16; ARIA_FE; + ARIA_KXL; rk+= 16; ARIA_FO; ARIA_KXL; rk+= 16; ARIA_FE; + ARIA_KXL; rk+= 16; ARIA_FO; ARIA_KXL; rk+= 16; ARIA_FE; + ARIA_KXL; rk+= 16; ARIA_FO; ARIA_KXL; rk+= 16; + +#if CRYPTOPP_ENABLE_ARIA_SSSE3_INTRINSICS + if (HasSSSE3()) + { + ARIA_ProcessAndXorBlock_SSSE3(xorBlock, outBlock, rk, t); + return; + } + else +#endif // CRYPTOPP_ENABLE_ARIA_SSSE3_INTRINSICS +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + { + ARIA_ProcessAndXorBlock_NEON(xorBlock, outBlock, rk, t); + return; + } + else +#endif // CRYPTOPP_ARM_NEON_AVAILABLE +#if (CRYPTOPP_LITTLE_ENDIAN) + { + outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] ) ^ rk[ 3]; + outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8) ^ rk[ 2]; + outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] ) ^ rk[ 1]; + outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] ) ^ rk[ 0]; + outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] ) ^ rk[ 7]; + outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8) ^ rk[ 6]; + outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] ) ^ rk[ 5]; + outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] ) ^ rk[ 4]; + outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] ) ^ rk[11]; + outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8) ^ rk[10]; + outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] ) ^ rk[ 9]; + outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] ) ^ rk[ 8]; + outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] ) ^ rk[15]; + outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8) ^ rk[14]; + outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] ) ^ rk[13]; + outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] ) ^ rk[12]; + } +#else + { + outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] ) ^ rk[ 0]; + outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8) ^ rk[ 1]; + outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] ) ^ rk[ 2]; + outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] ) ^ rk[ 3]; + outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] ) ^ rk[ 4]; + outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8) ^ rk[ 5]; + outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] ) ^ rk[ 6]; + outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] ) ^ rk[ 7]; + outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] ) ^ rk[ 8]; + outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8) ^ rk[ 9]; + outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] ) ^ rk[10]; + outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] ) ^ rk[11]; + outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] ) ^ rk[12]; + outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8) ^ rk[13]; + outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] ) ^ rk[14]; + outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] ) ^ rk[15]; + } +#endif // CRYPTOPP_LITTLE_ENDIAN + + if (xorBlock != NULLPTR) + for (unsigned int n=0; nRFC 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; + + AlignedByteBlock 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/external/ours/library/crypto/src/shared/original/aria_simd.cpp b/external/ours/library/crypto/src/shared/original/aria_simd.cpp new file mode 100755 index 000000000..56265e0e1 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/aria_simd.cpp @@ -0,0 +1,194 @@ +// aria_simd.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// +// This source file uses intrinsics to gain access to ARMv7a and +// ARMv8a NEON instructions. A separate source file is needed +// because additional CXXFLAGS are required to enable the +// appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" +#include "misc.h" + +#if (CRYPTOPP_SSSE3_AVAILABLE) +# include +#endif + +#if (CRYPTOPP_ARM_NEON_HEADER) +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char ARIA_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(ARIATab) + +extern const word32 S1[256]; +extern const word32 S2[256]; +extern const word32 X1[256]; +extern const word32 X2[256]; +extern const word32 KRK[3][4]; + +NAMESPACE_END +NAMESPACE_END + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; + +inline byte ARIA_BRF(const word32 x, const int y) { + return static_cast(GETBYTE(x, y)); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +using CryptoPP::ARIATab::S1; +using CryptoPP::ARIATab::S2; +using CryptoPP::ARIATab::X1; +using CryptoPP::ARIATab::X2; +using CryptoPP::ARIATab::KRK; + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + +template +inline void ARIA_GSRK_NEON(const uint32x4_t X, const uint32x4_t Y, byte RK[16]) +{ + enum { Q1 = (4-(N/32)) % 4, + Q2 = (3-(N/32)) % 4, + R = N % 32 + }; + + vst1q_u8(RK, vreinterpretq_u8_u32( + veorq_u32(X, veorq_u32( + vshrq_n_u32(vextq_u32(Y, Y, Q1), R), + vshlq_n_u32(vextq_u32(Y, Y, Q2), 32-R))))); +} + +void ARIA_UncheckedSetKey_Schedule_NEON(byte* rk, word32* ws, unsigned int keylen) +{ + const uint32x4_t w0 = vld1q_u32(ws+ 0); + const uint32x4_t w1 = vld1q_u32(ws+ 8); + const uint32x4_t w2 = vld1q_u32(ws+12); + const uint32x4_t w3 = vld1q_u32(ws+16); + + ARIA_GSRK_NEON<19>(w0, w1, rk + 0); + ARIA_GSRK_NEON<19>(w1, w2, rk + 16); + ARIA_GSRK_NEON<19>(w2, w3, rk + 32); + ARIA_GSRK_NEON<19>(w3, w0, rk + 48); + ARIA_GSRK_NEON<31>(w0, w1, rk + 64); + ARIA_GSRK_NEON<31>(w1, w2, rk + 80); + ARIA_GSRK_NEON<31>(w2, w3, rk + 96); + ARIA_GSRK_NEON<31>(w3, w0, rk + 112); + ARIA_GSRK_NEON<67>(w0, w1, rk + 128); + ARIA_GSRK_NEON<67>(w1, w2, rk + 144); + ARIA_GSRK_NEON<67>(w2, w3, rk + 160); + ARIA_GSRK_NEON<67>(w3, w0, rk + 176); + ARIA_GSRK_NEON<97>(w0, w1, rk + 192); + + if (keylen > 16) + { + ARIA_GSRK_NEON<97>(w1, w2, rk + 208); + ARIA_GSRK_NEON<97>(w2, w3, rk + 224); + + if (keylen > 24) + { + ARIA_GSRK_NEON< 97>(w3, w0, rk + 240); + ARIA_GSRK_NEON<109>(w0, w1, rk + 256); + } + } +} + +void ARIA_ProcessAndXorBlock_NEON(const byte* xorBlock, byte* outBlock, const byte *rk, word32 *t) +{ + outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] ); + outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8); + outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] ); + outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] ); + outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] ); + outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8); + outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] ); + outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] ); + outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] ); + outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8); + outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] ); + outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] ); + outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] ); + outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8); + outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] ); + outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] ); + + // 'outBlock' and 'xorBlock' may be unaligned. + if (xorBlock != NULLPTR) + { + vst1q_u8(outBlock, + veorq_u8( + vld1q_u8(xorBlock), + veorq_u8( + vld1q_u8(outBlock), + vrev32q_u8(vld1q_u8((rk)))))); + } + else + { + vst1q_u8(outBlock, + veorq_u8( + vld1q_u8(outBlock), + vrev32q_u8(vld1q_u8(rk)))); + } +} + +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +#if (CRYPTOPP_SSSE3_AVAILABLE) + +void ARIA_ProcessAndXorBlock_SSSE3(const byte* xorBlock, byte* outBlock, const byte *rk, word32 *t) +{ + const __m128i MASK = _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3); + + outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] ); + outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8); + outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] ); + outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] ); + outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] ); + outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8); + outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] ); + outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] ); + outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] ); + outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8); + outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] ); + outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] ); + outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] ); + outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8); + outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] ); + outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] ); + + // 'outBlock' and 'xorBlock' may be unaligned. + if (xorBlock != NULLPTR) + { + _mm_storeu_si128(M128_CAST(outBlock), + _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(xorBlock)), + _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(outBlock)), + _mm_shuffle_epi8(_mm_load_si128(CONST_M128_CAST(rk)), MASK))) + ); + } + else + { + _mm_storeu_si128(M128_CAST(outBlock), + _mm_xor_si128(_mm_loadu_si128(CONST_M128_CAST(outBlock)), + _mm_shuffle_epi8(_mm_load_si128(CONST_M128_CAST(rk)), MASK))); + } +} + +#endif // CRYPTOPP_SSSE3_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/ariatab.cpp b/external/ours/library/crypto/src/shared/original/ariatab.cpp new file mode 100755 index 000000000..6c8a15667 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ariatab.cpp @@ -0,0 +1,166 @@ +// ariatab.cpp - written and placed in the public domain by Jeffrey Walton + +#include "pch.h" +#include "config.h" + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(ARIATab) + +CRYPTOPP_ALIGN_DATA(16) +CRYPTOPP_TABLE +const word32 S1[256]={ + 0x00636363,0x007c7c7c,0x00777777,0x007b7b7b,0x00f2f2f2,0x006b6b6b,0x006f6f6f,0x00c5c5c5, + 0x00303030,0x00010101,0x00676767,0x002b2b2b,0x00fefefe,0x00d7d7d7,0x00ababab,0x00767676, + 0x00cacaca,0x00828282,0x00c9c9c9,0x007d7d7d,0x00fafafa,0x00595959,0x00474747,0x00f0f0f0, + 0x00adadad,0x00d4d4d4,0x00a2a2a2,0x00afafaf,0x009c9c9c,0x00a4a4a4,0x00727272,0x00c0c0c0, + 0x00b7b7b7,0x00fdfdfd,0x00939393,0x00262626,0x00363636,0x003f3f3f,0x00f7f7f7,0x00cccccc, + 0x00343434,0x00a5a5a5,0x00e5e5e5,0x00f1f1f1,0x00717171,0x00d8d8d8,0x00313131,0x00151515, + 0x00040404,0x00c7c7c7,0x00232323,0x00c3c3c3,0x00181818,0x00969696,0x00050505,0x009a9a9a, + 0x00070707,0x00121212,0x00808080,0x00e2e2e2,0x00ebebeb,0x00272727,0x00b2b2b2,0x00757575, + 0x00090909,0x00838383,0x002c2c2c,0x001a1a1a,0x001b1b1b,0x006e6e6e,0x005a5a5a,0x00a0a0a0, + 0x00525252,0x003b3b3b,0x00d6d6d6,0x00b3b3b3,0x00292929,0x00e3e3e3,0x002f2f2f,0x00848484, + 0x00535353,0x00d1d1d1,0x00000000,0x00ededed,0x00202020,0x00fcfcfc,0x00b1b1b1,0x005b5b5b, + 0x006a6a6a,0x00cbcbcb,0x00bebebe,0x00393939,0x004a4a4a,0x004c4c4c,0x00585858,0x00cfcfcf, + 0x00d0d0d0,0x00efefef,0x00aaaaaa,0x00fbfbfb,0x00434343,0x004d4d4d,0x00333333,0x00858585, + 0x00454545,0x00f9f9f9,0x00020202,0x007f7f7f,0x00505050,0x003c3c3c,0x009f9f9f,0x00a8a8a8, + 0x00515151,0x00a3a3a3,0x00404040,0x008f8f8f,0x00929292,0x009d9d9d,0x00383838,0x00f5f5f5, + 0x00bcbcbc,0x00b6b6b6,0x00dadada,0x00212121,0x00101010,0x00ffffff,0x00f3f3f3,0x00d2d2d2, + 0x00cdcdcd,0x000c0c0c,0x00131313,0x00ececec,0x005f5f5f,0x00979797,0x00444444,0x00171717, + 0x00c4c4c4,0x00a7a7a7,0x007e7e7e,0x003d3d3d,0x00646464,0x005d5d5d,0x00191919,0x00737373, + 0x00606060,0x00818181,0x004f4f4f,0x00dcdcdc,0x00222222,0x002a2a2a,0x00909090,0x00888888, + 0x00464646,0x00eeeeee,0x00b8b8b8,0x00141414,0x00dedede,0x005e5e5e,0x000b0b0b,0x00dbdbdb, + 0x00e0e0e0,0x00323232,0x003a3a3a,0x000a0a0a,0x00494949,0x00060606,0x00242424,0x005c5c5c, + 0x00c2c2c2,0x00d3d3d3,0x00acacac,0x00626262,0x00919191,0x00959595,0x00e4e4e4,0x00797979, + 0x00e7e7e7,0x00c8c8c8,0x00373737,0x006d6d6d,0x008d8d8d,0x00d5d5d5,0x004e4e4e,0x00a9a9a9, + 0x006c6c6c,0x00565656,0x00f4f4f4,0x00eaeaea,0x00656565,0x007a7a7a,0x00aeaeae,0x00080808, + 0x00bababa,0x00787878,0x00252525,0x002e2e2e,0x001c1c1c,0x00a6a6a6,0x00b4b4b4,0x00c6c6c6, + 0x00e8e8e8,0x00dddddd,0x00747474,0x001f1f1f,0x004b4b4b,0x00bdbdbd,0x008b8b8b,0x008a8a8a, + 0x00707070,0x003e3e3e,0x00b5b5b5,0x00666666,0x00484848,0x00030303,0x00f6f6f6,0x000e0e0e, + 0x00616161,0x00353535,0x00575757,0x00b9b9b9,0x00868686,0x00c1c1c1,0x001d1d1d,0x009e9e9e, + 0x00e1e1e1,0x00f8f8f8,0x00989898,0x00111111,0x00696969,0x00d9d9d9,0x008e8e8e,0x00949494, + 0x009b9b9b,0x001e1e1e,0x00878787,0x00e9e9e9,0x00cecece,0x00555555,0x00282828,0x00dfdfdf, + 0x008c8c8c,0x00a1a1a1,0x00898989,0x000d0d0d,0x00bfbfbf,0x00e6e6e6,0x00424242,0x00686868, + 0x00414141,0x00999999,0x002d2d2d,0x000f0f0f,0x00b0b0b0,0x00545454,0x00bbbbbb,0x00161616 +}; + +CRYPTOPP_ALIGN_DATA(16) +CRYPTOPP_TABLE +const word32 S2[256]={ + 0xe200e2e2,0x4e004e4e,0x54005454,0xfc00fcfc,0x94009494,0xc200c2c2,0x4a004a4a,0xcc00cccc, + 0x62006262,0x0d000d0d,0x6a006a6a,0x46004646,0x3c003c3c,0x4d004d4d,0x8b008b8b,0xd100d1d1, + 0x5e005e5e,0xfa00fafa,0x64006464,0xcb00cbcb,0xb400b4b4,0x97009797,0xbe00bebe,0x2b002b2b, + 0xbc00bcbc,0x77007777,0x2e002e2e,0x03000303,0xd300d3d3,0x19001919,0x59005959,0xc100c1c1, + 0x1d001d1d,0x06000606,0x41004141,0x6b006b6b,0x55005555,0xf000f0f0,0x99009999,0x69006969, + 0xea00eaea,0x9c009c9c,0x18001818,0xae00aeae,0x63006363,0xdf00dfdf,0xe700e7e7,0xbb00bbbb, + 0x00000000,0x73007373,0x66006666,0xfb00fbfb,0x96009696,0x4c004c4c,0x85008585,0xe400e4e4, + 0x3a003a3a,0x09000909,0x45004545,0xaa00aaaa,0x0f000f0f,0xee00eeee,0x10001010,0xeb00ebeb, + 0x2d002d2d,0x7f007f7f,0xf400f4f4,0x29002929,0xac00acac,0xcf00cfcf,0xad00adad,0x91009191, + 0x8d008d8d,0x78007878,0xc800c8c8,0x95009595,0xf900f9f9,0x2f002f2f,0xce00cece,0xcd00cdcd, + 0x08000808,0x7a007a7a,0x88008888,0x38003838,0x5c005c5c,0x83008383,0x2a002a2a,0x28002828, + 0x47004747,0xdb00dbdb,0xb800b8b8,0xc700c7c7,0x93009393,0xa400a4a4,0x12001212,0x53005353, + 0xff00ffff,0x87008787,0x0e000e0e,0x31003131,0x36003636,0x21002121,0x58005858,0x48004848, + 0x01000101,0x8e008e8e,0x37003737,0x74007474,0x32003232,0xca00caca,0xe900e9e9,0xb100b1b1, + 0xb700b7b7,0xab00abab,0x0c000c0c,0xd700d7d7,0xc400c4c4,0x56005656,0x42004242,0x26002626, + 0x07000707,0x98009898,0x60006060,0xd900d9d9,0xb600b6b6,0xb900b9b9,0x11001111,0x40004040, + 0xec00ecec,0x20002020,0x8c008c8c,0xbd00bdbd,0xa000a0a0,0xc900c9c9,0x84008484,0x04000404, + 0x49004949,0x23002323,0xf100f1f1,0x4f004f4f,0x50005050,0x1f001f1f,0x13001313,0xdc00dcdc, + 0xd800d8d8,0xc000c0c0,0x9e009e9e,0x57005757,0xe300e3e3,0xc300c3c3,0x7b007b7b,0x65006565, + 0x3b003b3b,0x02000202,0x8f008f8f,0x3e003e3e,0xe800e8e8,0x25002525,0x92009292,0xe500e5e5, + 0x15001515,0xdd00dddd,0xfd00fdfd,0x17001717,0xa900a9a9,0xbf00bfbf,0xd400d4d4,0x9a009a9a, + 0x7e007e7e,0xc500c5c5,0x39003939,0x67006767,0xfe00fefe,0x76007676,0x9d009d9d,0x43004343, + 0xa700a7a7,0xe100e1e1,0xd000d0d0,0xf500f5f5,0x68006868,0xf200f2f2,0x1b001b1b,0x34003434, + 0x70007070,0x05000505,0xa300a3a3,0x8a008a8a,0xd500d5d5,0x79007979,0x86008686,0xa800a8a8, + 0x30003030,0xc600c6c6,0x51005151,0x4b004b4b,0x1e001e1e,0xa600a6a6,0x27002727,0xf600f6f6, + 0x35003535,0xd200d2d2,0x6e006e6e,0x24002424,0x16001616,0x82008282,0x5f005f5f,0xda00dada, + 0xe600e6e6,0x75007575,0xa200a2a2,0xef00efef,0x2c002c2c,0xb200b2b2,0x1c001c1c,0x9f009f9f, + 0x5d005d5d,0x6f006f6f,0x80008080,0x0a000a0a,0x72007272,0x44004444,0x9b009b9b,0x6c006c6c, + 0x90009090,0x0b000b0b,0x5b005b5b,0x33003333,0x7d007d7d,0x5a005a5a,0x52005252,0xf300f3f3, + 0x61006161,0xa100a1a1,0xf700f7f7,0xb000b0b0,0xd600d6d6,0x3f003f3f,0x7c007c7c,0x6d006d6d, + 0xed00eded,0x14001414,0xe000e0e0,0xa500a5a5,0x3d003d3d,0x22002222,0xb300b3b3,0xf800f8f8, + 0x89008989,0xde00dede,0x71007171,0x1a001a1a,0xaf00afaf,0xba00baba,0xb500b5b5,0x81008181 +}; + +CRYPTOPP_ALIGN_DATA(16) +CRYPTOPP_TABLE +const word32 X1[256]={ + 0x52520052,0x09090009,0x6a6a006a,0xd5d500d5,0x30300030,0x36360036,0xa5a500a5,0x38380038, + 0xbfbf00bf,0x40400040,0xa3a300a3,0x9e9e009e,0x81810081,0xf3f300f3,0xd7d700d7,0xfbfb00fb, + 0x7c7c007c,0xe3e300e3,0x39390039,0x82820082,0x9b9b009b,0x2f2f002f,0xffff00ff,0x87870087, + 0x34340034,0x8e8e008e,0x43430043,0x44440044,0xc4c400c4,0xdede00de,0xe9e900e9,0xcbcb00cb, + 0x54540054,0x7b7b007b,0x94940094,0x32320032,0xa6a600a6,0xc2c200c2,0x23230023,0x3d3d003d, + 0xeeee00ee,0x4c4c004c,0x95950095,0x0b0b000b,0x42420042,0xfafa00fa,0xc3c300c3,0x4e4e004e, + 0x08080008,0x2e2e002e,0xa1a100a1,0x66660066,0x28280028,0xd9d900d9,0x24240024,0xb2b200b2, + 0x76760076,0x5b5b005b,0xa2a200a2,0x49490049,0x6d6d006d,0x8b8b008b,0xd1d100d1,0x25250025, + 0x72720072,0xf8f800f8,0xf6f600f6,0x64640064,0x86860086,0x68680068,0x98980098,0x16160016, + 0xd4d400d4,0xa4a400a4,0x5c5c005c,0xcccc00cc,0x5d5d005d,0x65650065,0xb6b600b6,0x92920092, + 0x6c6c006c,0x70700070,0x48480048,0x50500050,0xfdfd00fd,0xeded00ed,0xb9b900b9,0xdada00da, + 0x5e5e005e,0x15150015,0x46460046,0x57570057,0xa7a700a7,0x8d8d008d,0x9d9d009d,0x84840084, + 0x90900090,0xd8d800d8,0xabab00ab,0x00000000,0x8c8c008c,0xbcbc00bc,0xd3d300d3,0x0a0a000a, + 0xf7f700f7,0xe4e400e4,0x58580058,0x05050005,0xb8b800b8,0xb3b300b3,0x45450045,0x06060006, + 0xd0d000d0,0x2c2c002c,0x1e1e001e,0x8f8f008f,0xcaca00ca,0x3f3f003f,0x0f0f000f,0x02020002, + 0xc1c100c1,0xafaf00af,0xbdbd00bd,0x03030003,0x01010001,0x13130013,0x8a8a008a,0x6b6b006b, + 0x3a3a003a,0x91910091,0x11110011,0x41410041,0x4f4f004f,0x67670067,0xdcdc00dc,0xeaea00ea, + 0x97970097,0xf2f200f2,0xcfcf00cf,0xcece00ce,0xf0f000f0,0xb4b400b4,0xe6e600e6,0x73730073, + 0x96960096,0xacac00ac,0x74740074,0x22220022,0xe7e700e7,0xadad00ad,0x35350035,0x85850085, + 0xe2e200e2,0xf9f900f9,0x37370037,0xe8e800e8,0x1c1c001c,0x75750075,0xdfdf00df,0x6e6e006e, + 0x47470047,0xf1f100f1,0x1a1a001a,0x71710071,0x1d1d001d,0x29290029,0xc5c500c5,0x89890089, + 0x6f6f006f,0xb7b700b7,0x62620062,0x0e0e000e,0xaaaa00aa,0x18180018,0xbebe00be,0x1b1b001b, + 0xfcfc00fc,0x56560056,0x3e3e003e,0x4b4b004b,0xc6c600c6,0xd2d200d2,0x79790079,0x20200020, + 0x9a9a009a,0xdbdb00db,0xc0c000c0,0xfefe00fe,0x78780078,0xcdcd00cd,0x5a5a005a,0xf4f400f4, + 0x1f1f001f,0xdddd00dd,0xa8a800a8,0x33330033,0x88880088,0x07070007,0xc7c700c7,0x31310031, + 0xb1b100b1,0x12120012,0x10100010,0x59590059,0x27270027,0x80800080,0xecec00ec,0x5f5f005f, + 0x60600060,0x51510051,0x7f7f007f,0xa9a900a9,0x19190019,0xb5b500b5,0x4a4a004a,0x0d0d000d, + 0x2d2d002d,0xe5e500e5,0x7a7a007a,0x9f9f009f,0x93930093,0xc9c900c9,0x9c9c009c,0xefef00ef, + 0xa0a000a0,0xe0e000e0,0x3b3b003b,0x4d4d004d,0xaeae00ae,0x2a2a002a,0xf5f500f5,0xb0b000b0, + 0xc8c800c8,0xebeb00eb,0xbbbb00bb,0x3c3c003c,0x83830083,0x53530053,0x99990099,0x61610061, + 0x17170017,0x2b2b002b,0x04040004,0x7e7e007e,0xbaba00ba,0x77770077,0xd6d600d6,0x26260026, + 0xe1e100e1,0x69690069,0x14140014,0x63630063,0x55550055,0x21210021,0x0c0c000c,0x7d7d007d +}; + +CRYPTOPP_ALIGN_DATA(16) +CRYPTOPP_TABLE +const word32 X2[256]={ + 0x30303000,0x68686800,0x99999900,0x1b1b1b00,0x87878700,0xb9b9b900,0x21212100,0x78787800, + 0x50505000,0x39393900,0xdbdbdb00,0xe1e1e100,0x72727200,0x09090900,0x62626200,0x3c3c3c00, + 0x3e3e3e00,0x7e7e7e00,0x5e5e5e00,0x8e8e8e00,0xf1f1f100,0xa0a0a000,0xcccccc00,0xa3a3a300, + 0x2a2a2a00,0x1d1d1d00,0xfbfbfb00,0xb6b6b600,0xd6d6d600,0x20202000,0xc4c4c400,0x8d8d8d00, + 0x81818100,0x65656500,0xf5f5f500,0x89898900,0xcbcbcb00,0x9d9d9d00,0x77777700,0xc6c6c600, + 0x57575700,0x43434300,0x56565600,0x17171700,0xd4d4d400,0x40404000,0x1a1a1a00,0x4d4d4d00, + 0xc0c0c000,0x63636300,0x6c6c6c00,0xe3e3e300,0xb7b7b700,0xc8c8c800,0x64646400,0x6a6a6a00, + 0x53535300,0xaaaaaa00,0x38383800,0x98989800,0x0c0c0c00,0xf4f4f400,0x9b9b9b00,0xededed00, + 0x7f7f7f00,0x22222200,0x76767600,0xafafaf00,0xdddddd00,0x3a3a3a00,0x0b0b0b00,0x58585800, + 0x67676700,0x88888800,0x06060600,0xc3c3c300,0x35353500,0x0d0d0d00,0x01010100,0x8b8b8b00, + 0x8c8c8c00,0xc2c2c200,0xe6e6e600,0x5f5f5f00,0x02020200,0x24242400,0x75757500,0x93939300, + 0x66666600,0x1e1e1e00,0xe5e5e500,0xe2e2e200,0x54545400,0xd8d8d800,0x10101000,0xcecece00, + 0x7a7a7a00,0xe8e8e800,0x08080800,0x2c2c2c00,0x12121200,0x97979700,0x32323200,0xababab00, + 0xb4b4b400,0x27272700,0x0a0a0a00,0x23232300,0xdfdfdf00,0xefefef00,0xcacaca00,0xd9d9d900, + 0xb8b8b800,0xfafafa00,0xdcdcdc00,0x31313100,0x6b6b6b00,0xd1d1d100,0xadadad00,0x19191900, + 0x49494900,0xbdbdbd00,0x51515100,0x96969600,0xeeeeee00,0xe4e4e400,0xa8a8a800,0x41414100, + 0xdadada00,0xffffff00,0xcdcdcd00,0x55555500,0x86868600,0x36363600,0xbebebe00,0x61616100, + 0x52525200,0xf8f8f800,0xbbbbbb00,0x0e0e0e00,0x82828200,0x48484800,0x69696900,0x9a9a9a00, + 0xe0e0e000,0x47474700,0x9e9e9e00,0x5c5c5c00,0x04040400,0x4b4b4b00,0x34343400,0x15151500, + 0x79797900,0x26262600,0xa7a7a700,0xdedede00,0x29292900,0xaeaeae00,0x92929200,0xd7d7d700, + 0x84848400,0xe9e9e900,0xd2d2d200,0xbababa00,0x5d5d5d00,0xf3f3f300,0xc5c5c500,0xb0b0b000, + 0xbfbfbf00,0xa4a4a400,0x3b3b3b00,0x71717100,0x44444400,0x46464600,0x2b2b2b00,0xfcfcfc00, + 0xebebeb00,0x6f6f6f00,0xd5d5d500,0xf6f6f600,0x14141400,0xfefefe00,0x7c7c7c00,0x70707000, + 0x5a5a5a00,0x7d7d7d00,0xfdfdfd00,0x2f2f2f00,0x18181800,0x83838300,0x16161600,0xa5a5a500, + 0x91919100,0x1f1f1f00,0x05050500,0x95959500,0x74747400,0xa9a9a900,0xc1c1c100,0x5b5b5b00, + 0x4a4a4a00,0x85858500,0x6d6d6d00,0x13131300,0x07070700,0x4f4f4f00,0x4e4e4e00,0x45454500, + 0xb2b2b200,0x0f0f0f00,0xc9c9c900,0x1c1c1c00,0xa6a6a600,0xbcbcbc00,0xececec00,0x73737300, + 0x90909000,0x7b7b7b00,0xcfcfcf00,0x59595900,0x8f8f8f00,0xa1a1a100,0xf9f9f900,0x2d2d2d00, + 0xf2f2f200,0xb1b1b100,0x00000000,0x94949400,0x37373700,0x9f9f9f00,0xd0d0d000,0x2e2e2e00, + 0x9c9c9c00,0x6e6e6e00,0x28282800,0x3f3f3f00,0x80808000,0xf0f0f000,0x3d3d3d00,0xd3d3d300, + 0x25252500,0x8a8a8a00,0xb5b5b500,0xe7e7e700,0x42424200,0xb3b3b300,0xc7c7c700,0xeaeaea00, + 0xf7f7f700,0x4c4c4c00,0x11111100,0x33333300,0x03030300,0xa2a2a200,0xacacac00,0x60606000 +}; + +CRYPTOPP_ALIGN_DATA(16) +CRYPTOPP_TABLE +const word32 KRK[3][4] = { + {0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0}, + {0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0}, + {0xdb92371d, 0x2126e970, 0x03249775, 0x04e8c90e} +}; + +NAMESPACE_END +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/arm_simd.h b/external/ours/library/crypto/src/shared/original/arm_simd.h new file mode 100755 index 000000000..84298b9a5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/arm_simd.h @@ -0,0 +1,449 @@ +// 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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(_MSC_VER) + 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 +/// \param a the first value +/// \param b the second value +/// \param c the byte count +/// \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 +inline uint64x2_t VEXT_U8(uint64x2_t a, uint64x2_t b, unsigned int c) +{ +#if defined(_MSC_VER) + 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 +} + +/// \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(_MSC_VER) + 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(_MSC_VER) + 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 imm6 +/// \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 imm6) +{ +#if defined(_MSC_VER) + return vxarq_u64(a, b, imm6); +#else + uint64x2_t r; + __asm__ ("xar %0.2d, %1.2d, %2.2d, %3 \n\t" + :"=w" (r) : "w" (a), "w" (b), "I" (imm6)); + 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(_MSC_VER) + 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(_MSC_VER) + 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/external/ours/library/crypto/src/shared/original/asn.cpp b/external/ours/library/crypto/src/shared/original/asn.cpp new file mode 100755 index 000000000..d3ceef9dd --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/asn.cpp @@ -0,0 +1,717 @@ +// asn.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017 + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "cryptlib.h" +#include "asn.h" +#include "misc.h" + +#include +#include +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +size_t DERLengthEncode(BufferedTransformation &bt, lword length) +{ + size_t i=0; + if (length <= 0x7f) + { + bt.Put(byte(length)); + i++; + } + else + { + bt.Put(byte(BytePrecision(length) | 0x80)); + i++; + for (int j=BytePrecision(length); j; --j) + { + bt.Put(byte(length >> (j-1)*8)); + i++; + } + } + return i; +} + +bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength) +{ + byte b; + + if (!bt.Get(b)) + return false; + + if (!(b & 0x80)) + { + definiteLength = true; + length = b; + } + else + { + unsigned int lengthBytes = b & 0x7f; + + if (lengthBytes == 0) + { + definiteLength = false; + return true; + } + + definiteLength = true; + length = 0; + while (lengthBytes--) + { + if (length >> (8*(sizeof(length)-1))) + BERDecodeError(); // length about to overflow + + if (!bt.Get(b)) + return false; + + length = (length << 8) | b; + } + } + return true; +} + +bool BERLengthDecode(BufferedTransformation &bt, size_t &length) +{ + lword lw = 0; + bool definiteLength = false; + if (!BERLengthDecode(bt, lw, definiteLength)) + BERDecodeError(); + if (!SafeConvert(lw, length)) + BERDecodeError(); + return definiteLength; +} + +void DEREncodeNull(BufferedTransformation &out) +{ + out.Put(TAG_NULL); + out.Put(0); +} + +void BERDecodeNull(BufferedTransformation &in) +{ + byte b; + if (!in.Get(b) || b != TAG_NULL) + BERDecodeError(); + size_t length; + if (!BERLengthDecode(in, length) || length != 0) + BERDecodeError(); +} + +/// ASN Strings +size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen) +{ + bt.Put(OCTET_STRING); + size_t lengthBytes = DERLengthEncode(bt, strLen); + bt.Put(str, strLen); + return 1+lengthBytes+strLen; +} + +size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str) +{ + return DEREncodeOctetString(bt, ConstBytePtr(str), BytePtrSize(str)); +} + +size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str) +{ + byte b; + if (!bt.Get(b) || b != OCTET_STRING) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + if (bc > bt.MaxRetrievable()) // Issue 346 + BERDecodeError(); + + str.New(bc); + if (bc != bt.Get(BytePtr(str), bc)) + BERDecodeError(); + return bc; +} + +size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str) +{ + byte b; + if (!bt.Get(b) || b != OCTET_STRING) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + if (bc > bt.MaxRetrievable()) // Issue 346 + BERDecodeError(); + + bt.TransferTo(str, bc); + return bc; +} + +size_t DEREncodeTextString(BufferedTransformation &bt, const byte* str, size_t strLen, byte asnTag) +{ + bt.Put(asnTag); + size_t lengthBytes = DERLengthEncode(bt, strLen); + bt.Put(str, strLen); + return 1+lengthBytes+strLen; +} + +size_t DEREncodeTextString(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag) +{ + return DEREncodeTextString(bt, ConstBytePtr(str), BytePtrSize(str), asnTag); +} + +size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag) +{ + return DEREncodeTextString(bt, ConstBytePtr(str), BytePtrSize(str), asnTag); +} + +size_t BERDecodeTextString(BufferedTransformation &bt, SecByteBlock &str, byte asnTag) +{ + byte b; + if (!bt.Get(b) || b != asnTag) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + if (bc > bt.MaxRetrievable()) // Issue 346 + BERDecodeError(); + + str.resize(bc); + if (bc != bt.Get(BytePtr(str), BytePtrSize(str))) + BERDecodeError(); + + return bc; +} + +size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag) +{ + byte b; + if (!bt.Get(b) || b != asnTag) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + if (bc > bt.MaxRetrievable()) // Issue 346 + BERDecodeError(); + + str.resize(bc); + if (bc != bt.Get(BytePtr(str), BytePtrSize(str))) + BERDecodeError(); + + return bc; +} + +size_t DEREncodeDate(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag) +{ + bt.Put(asnTag); + size_t lengthBytes = DERLengthEncode(bt, str.size()); + bt.Put(ConstBytePtr(str), BytePtrSize(str)); + return 1+lengthBytes+str.size(); +} + +size_t BERDecodeDate(BufferedTransformation &bt, SecByteBlock &str, byte asnTag) +{ + byte b; + if (!bt.Get(b) || b != asnTag) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + if (bc > bt.MaxRetrievable()) // Issue 346 + BERDecodeError(); + + str.resize(bc); + if (bc != bt.Get(BytePtr(str), BytePtrSize(str))) + BERDecodeError(); + + return bc; +} + +size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits) +{ + bt.Put(BIT_STRING); + size_t lengthBytes = DERLengthEncode(bt, strLen+1); + bt.Put((byte)unusedBits); + bt.Put(str, strLen); + return 2+lengthBytes+strLen; +} + +size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits) +{ + byte b; + if (!bt.Get(b) || b != BIT_STRING) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + if (bc == 0) + BERDecodeError(); + if (bc > bt.MaxRetrievable()) // Issue 346 + BERDecodeError(); + + // X.690, 8.6.2.2: "The number [of unused bits] shall be in the range zero to seven" + byte unused; + if (!bt.Get(unused) || unused > 7) + BERDecodeError(); + unusedBits = unused; + str.resize(bc-1); + if ((bc-1) != bt.Get(BytePtr(str), bc-1)) + BERDecodeError(); + return bc-1; +} + +void DERReencode(BufferedTransformation &source, BufferedTransformation &dest) +{ + byte tag; + source.Peek(tag); + BERGeneralDecoder decoder(source, tag); + DERGeneralEncoder encoder(dest, tag); + if (decoder.IsDefiniteLength()) + decoder.TransferTo(encoder, decoder.RemainingLength()); + else + { + while (!decoder.EndReached()) + DERReencode(decoder, encoder); + } + decoder.MessageEnd(); + encoder.MessageEnd(); +} + +size_t BERDecodePeekLength(const BufferedTransformation &bt) +{ + lword count = (std::min)(bt.MaxRetrievable(), static_cast(16)); + if (count == 0) return 0; + + ByteQueue tagAndLength; + bt.CopyTo(tagAndLength, count); + + // Skip tag + tagAndLength.Skip(1); + + // BERLengthDecode fails for indefinite length. + size_t length; + if (!BERLengthDecode(tagAndLength, length)) + return 0; + + return length; +} + +void OID::EncodeValue(BufferedTransformation &bt, word32 v) +{ + for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7) + bt.Put((byte)(0x80 | ((v >> i) & 0x7f))); + bt.Put((byte)(v & 0x7f)); +} + +size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v) +{ + byte b; + size_t i=0; + v = 0; + while (true) + { + if (!bt.Get(b)) + BERDecodeError(); + i++; + if (v >> (8*sizeof(v)-7)) // v about to overflow + BERDecodeError(); + v <<= 7; + v += b & 0x7f; + if (!(b & 0x80)) + return i; + } +} + +void OID::DEREncode(BufferedTransformation &bt) const +{ + CRYPTOPP_ASSERT(m_values.size() >= 2); + ByteQueue temp; + temp.Put(byte(m_values[0] * 40 + m_values[1])); + for (size_t i=2; i 0) + { + word32 v; + size_t valueLen = DecodeValue(bt, v); + if (valueLen > length) + BERDecodeError(); + m_values.push_back(v); + length -= valueLen; + } +} + +void OID::BERDecodeAndCheck(BufferedTransformation &bt) const +{ + OID oid(bt); + if (*this != oid) + BERDecodeError(); +} + +std::ostream& OID::Print(std::ostream& out) const +{ + std::ostringstream oss; + for (size_t i = 0; i < m_values.size(); ++i) + { + oss << m_values[i]; + if (i+1 < m_values.size()) + oss << "."; + } + return out << oss.str(); +} + +inline BufferedTransformation & EncodedObjectFilter::CurrentTarget() +{ + if (m_flags & PUT_OBJECTS) + return *AttachedTransformation(); + else + return TheBitBucket(); +} + +void EncodedObjectFilter::Put(const byte *inString, size_t length) +{ + if (m_nCurrentObject == m_nObjects) + { + AttachedTransformation()->Put(inString, length); + return; + } + + LazyPutter lazyPutter(m_queue, inString, length); + + while (m_queue.AnyRetrievable()) + { + switch (m_state) + { + case IDENTIFIER: + if (!m_queue.Get(m_id)) + return; + m_queue.TransferTo(CurrentTarget(), 1); + m_state = LENGTH; + // fall through + case LENGTH: + { + byte b; + if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0) + { + m_queue.TransferTo(CurrentTarget(), 1); + m_level--; + m_state = IDENTIFIER; + break; + } + ByteQueue::Walker walker(m_queue); + bool definiteLength = false; + if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength)) + return; + m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition()); + if (!((m_id & CONSTRUCTED) || definiteLength)) + BERDecodeError(); + if (!definiteLength) + { + if (!(m_id & CONSTRUCTED)) + BERDecodeError(); + m_level++; + m_state = IDENTIFIER; + break; + } + m_state = BODY; + } + // fall through + case BODY: + m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining); + + if (m_lengthRemaining == 0) + m_state = IDENTIFIER; + // fall through + case TAIL: + case ALL_DONE: + default: ; + } + + if (m_state == IDENTIFIER && m_level == 0) + { + // just finished processing a level 0 object + ++m_nCurrentObject; + + if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT) + AttachedTransformation()->MessageEnd(); + + if (m_nCurrentObject == m_nObjects) + { + if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS) + AttachedTransformation()->MessageEnd(); + + if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS) + AttachedTransformation()->MessageSeriesEnd(); + + m_queue.TransferAllTo(*AttachedTransformation()); + return; + } + } + } +} + +BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue) + : m_inQueue(inQueue), m_length(0), m_finished(false) +{ + Init(DefaultTag); +} + +BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag) + : m_inQueue(inQueue), m_length(0), m_finished(false) +{ + Init(asnTag); +} + +BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag) + : m_inQueue(inQueue), m_length(0), m_finished(false) +{ + Init(asnTag); +} + +void BERGeneralDecoder::Init(byte asnTag) +{ + byte b; + if (!m_inQueue.Get(b) || b != asnTag) + BERDecodeError(); + + if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength)) + BERDecodeError(); + + if (!m_definiteLength && !(asnTag & CONSTRUCTED)) + BERDecodeError(); // cannot be primitive and have indefinite length +} + +BERGeneralDecoder::~BERGeneralDecoder() +{ + try // avoid throwing in destructor + { + if (!m_finished) + MessageEnd(); + } + catch (const Exception&) + { + // CRYPTOPP_ASSERT(0); + } +} + +bool BERGeneralDecoder::EndReached() const +{ + if (m_definiteLength) + return m_length == 0; + else + { // check end-of-content octets + word16 i; + return (m_inQueue.PeekWord16(i)==2 && i==0); + } +} + +byte BERGeneralDecoder::PeekByte() const +{ + byte b; + if (!Peek(b)) + BERDecodeError(); + return b; +} + +void BERGeneralDecoder::CheckByte(byte check) +{ + byte b; + if (!Get(b) || b != check) + BERDecodeError(); +} + +void BERGeneralDecoder::MessageEnd() +{ + m_finished = true; + if (m_definiteLength) + { + if (m_length != 0) + BERDecodeError(); + } + else + { // remove end-of-content octets + word16 i; + if (m_inQueue.GetWord16(i) != 2 || i != 0) + BERDecodeError(); + } +} + +size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + if (m_definiteLength && transferBytes > m_length) + transferBytes = m_length; + size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking); + ReduceLength(transferBytes); + return blockedBytes; +} + +size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + if (m_definiteLength) + end = STDMIN(m_length, end); + return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking); +} + +lword BERGeneralDecoder::ReduceLength(lword delta) +{ + if (m_definiteLength) + { + if (m_length < delta) + BERDecodeError(); + m_length -= delta; + } + return delta; +} + +DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue) + : m_outQueue(outQueue), m_asnTag(DefaultTag), m_finished(false) +{ +} + +DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag) + : m_outQueue(outQueue), m_asnTag(asnTag), m_finished(false) +{ +} + +DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag) + : m_outQueue(outQueue), m_asnTag(asnTag), m_finished(false) +{ +} + +DERGeneralEncoder::~DERGeneralEncoder() +{ + try // avoid throwing in constructor + { + if (!m_finished) + MessageEnd(); + } + catch (const Exception&) + { + CRYPTOPP_ASSERT(0); + } +} + +void DERGeneralEncoder::MessageEnd() +{ + m_finished = true; + lword length = CurrentSize(); + m_outQueue.Put(m_asnTag); + DERLengthEncode(m_outQueue, length); + TransferTo(m_outQueue); +} + +// ************************************************************* + +void X509PublicKey::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder subjectPublicKeyInfo(bt); + BERSequenceDecoder algorithm(subjectPublicKeyInfo); + GetAlgorithmID().BERDecodeAndCheck(algorithm); + bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm); + algorithm.MessageEnd(); + + BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); + subjectPublicKey.CheckByte(0); // unused bits + BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength()); + subjectPublicKey.MessageEnd(); + subjectPublicKeyInfo.MessageEnd(); +} + +void X509PublicKey::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder subjectPublicKeyInfo(bt); + + DERSequenceEncoder algorithm(subjectPublicKeyInfo); + GetAlgorithmID().DEREncode(algorithm); + DEREncodeAlgorithmParameters(algorithm); + algorithm.MessageEnd(); + + DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); + subjectPublicKey.Put(0); // unused bits + DEREncodePublicKey(subjectPublicKey); + subjectPublicKey.MessageEnd(); + + subjectPublicKeyInfo.MessageEnd(); +} + +void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder privateKeyInfo(bt); + word32 version; + BERDecodeUnsigned(privateKeyInfo, version, INTEGER, 0, 0); // check version + + BERSequenceDecoder algorithm(privateKeyInfo); + GetAlgorithmID().BERDecodeAndCheck(algorithm); + bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm); + algorithm.MessageEnd(); + + BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING); + BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength()); + octetString.MessageEnd(); + + if (!privateKeyInfo.EndReached()) + BERDecodeOptionalAttributes(privateKeyInfo); + privateKeyInfo.MessageEnd(); +} + +void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder privateKeyInfo(bt); + DEREncodeUnsigned(privateKeyInfo, 0); // version + + DERSequenceEncoder algorithm(privateKeyInfo); + GetAlgorithmID().DEREncode(algorithm); + DEREncodeAlgorithmParameters(algorithm); + algorithm.MessageEnd(); + + DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING); + DEREncodePrivateKey(octetString); + octetString.MessageEnd(); + + DEREncodeOptionalAttributes(privateKeyInfo); + privateKeyInfo.MessageEnd(); +} + +void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt) +{ + DERReencode(bt, m_optionalAttributes); +} + +void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const +{ + m_optionalAttributes.CopyTo(bt); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/asn.h b/external/ours/library/crypto/src/shared/original/asn.h new file mode 100755 index 000000000..dce819485 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/asn.h @@ -0,0 +1,965 @@ +// 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 execption + 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); + + 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 each element in the array of values. +inline bool operator<(const OID &lhs, const OID &rhs); +/// \brief Compare two OIDs for ordering +/// \param lhs the first OID +/// \param rhs the second OID +/// \return true if the first OID is less than or equal to the second OID, false otherwise +/// \details operator<=() is implemented in terms of operator==() and operator<(). +/// \since Crypto++ 8.3 +inline bool operator<=(const OID &lhs, const OID &rhs); +/// \brief Compare two OIDs for ordering +/// \param lhs the first OID +/// \param rhs the second OID +/// \return true if the first OID is greater than or equal to the second OID, false otherwise +/// \details operator>=() is implemented in terms of operator<(). +/// \since Crypto++ 8.3 +inline bool operator>=(const OID &lhs, const OID &rhs); +/// \brief Append a value to an OID +/// \param lhs the OID +/// \param rhs the value to append +inline OID operator+(const OID &lhs, unsigned long rhs); +/// \brief Print a OID value +/// \param out the output stream +/// \param oid the OID +inline std::ostream& operator<<(std::ostream& out, const OID &oid) + { return oid.Print(out); } +#else +inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) + {return lhs.m_values == rhs.m_values;} +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 ! (lhs= blockSize) + { + memcpy(data+num, input, blockSize-num); + AuthenticateBlocks(data, blockSize); + input += (blockSize-num); + len -= (blockSize-num); + num = 0; + // drop through and do the rest + } + else + { + memcpy(data+num, input, len); + num += (unsigned int)len; + return; + } + } + + // now process the input data in blocks of blockSize bytes and save the leftovers to m_data + if (len >= blockSize) + { + size_t leftOver = AuthenticateBlocks(input, len); + input += (len - leftOver); + len = leftOver; + } + + if (data && len) + memcpy(data, input, len); + num = (unsigned int)len; +} + +void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) +{ + m_bufferedDataLength = 0; + m_state = State_Start; + + this->SetKeyWithoutResync(userKey, keylength, params); + m_state = State_KeySet; + + size_t length; + const byte *iv = GetIVAndThrowIfInvalid(params, length); + if (iv) + Resynchronize(iv, (int)length); +} + +void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length) +{ + if (m_state < State_KeySet) + throw BadState(AlgorithmName(), "Resynchronize", "key is set"); + + m_bufferedDataLength = 0; + m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0; + m_state = State_KeySet; + + Resync(iv, this->ThrowIfInvalidIVLength(length)); + m_state = State_IVSet; +} + +void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length) +{ + // Part of original authenc.cpp code. Don't remove it. + if (length == 0) {return;} + + switch (m_state) + { + case State_Start: + case State_KeySet: + throw BadState(AlgorithmName(), "Update", "setting key and IV"); + case State_IVSet: + AuthenticateData(input, length); + m_totalHeaderLength += length; + break; + case State_AuthUntransformed: + case State_AuthTransformed: + AuthenticateLastConfidentialBlock(); + m_bufferedDataLength = 0; + m_state = State_AuthFooter; + // fall through + case State_AuthFooter: + AuthenticateData(input, length); + m_totalFooterLength += length; + break; + default: + CRYPTOPP_ASSERT(false); + } +} + +void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length) +{ + if (m_state >= State_IVSet && length > MaxMessageLength()-m_totalMessageLength) + throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum"); + m_totalMessageLength += length; + +reswitch: + switch (m_state) + { + case State_Start: + case State_KeySet: + throw BadState(AlgorithmName(), "ProcessData", "setting key and IV"); + case State_AuthFooter: + throw BadState(AlgorithmName(), "ProcessData was called after footer input has started"); + case State_IVSet: + AuthenticateLastHeaderBlock(); + m_bufferedDataLength = 0; + m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed; + goto reswitch; + case State_AuthUntransformed: + AuthenticateData(inString, length); + AccessSymmetricCipher().ProcessData(outString, inString, length); + break; + case State_AuthTransformed: + AccessSymmetricCipher().ProcessData(outString, inString, length); + AuthenticateData(outString, length); + break; + default: + CRYPTOPP_ASSERT(false); + } +} + +void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize) +{ + // https://github.com/weidai11/cryptopp/issues/954 + this->ThrowIfInvalidTruncatedSize(macSize); + + if (m_totalHeaderLength > MaxHeaderLength()) + throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength())); + + if (m_totalFooterLength > MaxFooterLength()) + { + if (MaxFooterLength() == 0) + throw InvalidArgument(AlgorithmName() + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted"); + else + throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength())); + } + + switch (m_state) + { + case State_Start: + case State_KeySet: + throw BadState(AlgorithmName(), "TruncatedFinal", "setting key and IV"); + + case State_IVSet: + AuthenticateLastHeaderBlock(); + m_bufferedDataLength = 0; + // fall through + + case State_AuthUntransformed: + case State_AuthTransformed: + AuthenticateLastConfidentialBlock(); + m_bufferedDataLength = 0; + // fall through + + case State_AuthFooter: + AuthenticateLastFooterBlock(mac, macSize); + m_bufferedDataLength = 0; + break; + + default: + CRYPTOPP_ASSERT(false); + } + + m_state = State_KeySet; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/authenc.h b/external/ours/library/crypto/src/shared/original/authenc.h new file mode 100755 index 000000000..980de0b4e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/authenc.h @@ -0,0 +1,87 @@ +// authenc.h - originally written and placed in the public domain by Wei Dai + +/// \file +/// \brief Classes for authenticated encryption modes of operation +/// \details Authenticated encryption (AE) schemes combine confidentiality and authenticity +/// into a single mode of operation They gained traction in the early 2000's because manually +/// combining them was error prone for the typical developer. Around that time, the desire to +/// authenticate but not ecrypt additional data (AAD) was also identified. When both features +/// are available from a scheme, the system is referred to as an AEAD scheme. +/// \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 + +#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/external/ours/library/crypto/src/shared/original/base32.cpp b/external/ours/library/crypto/src/shared/original/base32.cpp new file mode 100755 index 000000000..2f0c4c7f6 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/base32.cpp @@ -0,0 +1,97 @@ +// base32.cpp - 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. + +#include "pch.h" +#include "base32.h" + +NAMESPACE_BEGIN(CryptoPP) +ANONYMOUS_NAMESPACE_BEGIN + +const byte s_stdUpper[] = "ABCDEFGHIJKMNPQRSTUVWXYZ23456789"; +const byte s_stdLower[] = "abcdefghijkmnpqrstuvwxyz23456789"; +const byte s_hexUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; +const byte s_hexLower[] = "0123456789abcdefghijklmnopqrstuv"; + +const int s_array[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, 11, 12, -1, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, 11, 12, -1, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +const int s_hexArray[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +ANONYMOUS_NAMESPACE_END + +void Base32Encoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true); + m_filter->Initialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_stdUpper[0] : &s_stdLower[0], false)(Name::Log2Base(), 5, true))); +} + +void Base32Decoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 5, true))); +} + +// Unrolled initialization, http://github.com/weidai11/cryptopp/issues/376 +const int *Base32Decoder::GetDefaultDecodingLookupArray() +{ + return s_array; +} + +void Base32HexEncoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true); + m_filter->Initialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_hexUpper[0] : &s_hexLower[0], false)(Name::Log2Base(), 5, true))); +} + +void Base32HexDecoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 5, true))); +} + +// Unrolled initialization, http://github.com/weidai11/cryptopp/issues/376 +const int *Base32HexDecoder::GetDefaultDecodingLookupArray() +{ + return s_hexArray; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/base32.h b/external/ours/library/crypto/src/shared/original/base32.h new file mode 100755 index 000000000..4eeae43ce --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/base64.cpp b/external/ours/library/crypto/src/shared/original/base64.cpp new file mode 100755 index 000000000..9c899cbc2 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/base64.cpp @@ -0,0 +1,111 @@ +// base64.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" +#include "base64.h" + +NAMESPACE_BEGIN(CryptoPP) +ANONYMOUS_NAMESPACE_BEGIN + +const byte s_stdVec[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const byte s_urlVec[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +const byte s_padding = '='; +const int s_stdArray[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; +const int s_urlArray[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +ANONYMOUS_NAMESPACE_END + +void Base64Encoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + bool insertLineBreaks = parameters.GetValueWithDefault(Name::InsertLineBreaks(), true); + int maxLineLength = parameters.GetIntValueWithDefault(Name::MaxLineLength(), 72); + + const char *lineBreak = insertLineBreaks ? "\n" : ""; + + m_filter->Initialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::EncodingLookupArray(), &s_stdVec[0], false) + (Name::PaddingByte(), s_padding) + (Name::GroupSize(), insertLineBreaks ? maxLineLength : 0) + (Name::Separator(), ConstByteArrayParameter(lineBreak)) + (Name::Terminator(), ConstByteArrayParameter(lineBreak)) + (Name::Log2Base(), 6, true))); +} + +void Base64URLEncoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + bool insertLineBreaks = parameters.GetValueWithDefault(Name::InsertLineBreaks(), true); + int maxLineLength = parameters.GetIntValueWithDefault(Name::MaxLineLength(), 72); + + const char *lineBreak = insertLineBreaks ? "\n" : ""; + + m_filter->Initialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::EncodingLookupArray(), &s_urlVec[0], false) + (Name::PaddingByte(), s_padding) + (Name::GroupSize(), insertLineBreaks ? maxLineLength : 0) + (Name::Separator(), ConstByteArrayParameter(lineBreak)) + (Name::Terminator(), ConstByteArrayParameter(lineBreak)) + (Name::Log2Base(), 6, true))); +} + +void Base64Decoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::DecodingLookupArray(), GetDecodingLookupArray(), false)(Name::Log2Base(), 6, true))); +} + +const int *Base64Decoder::GetDecodingLookupArray() +{ + return s_stdArray; +} + +void Base64URLDecoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::DecodingLookupArray(), GetDecodingLookupArray(), false)(Name::Log2Base(), 6, true))); +} + +// Unrolled initialization, http://github.com/weidai11/cryptopp/issues/376 +const int *Base64URLDecoder::GetDecodingLookupArray() +{ + return s_urlArray; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/base64.h b/external/ours/library/crypto/src/shared/original/base64.h new file mode 100755 index 000000000..5defc3740 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/basecode.cpp b/external/ours/library/crypto/src/shared/original/basecode.cpp new file mode 100755 index 000000000..a9a278920 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/basecode.cpp @@ -0,0 +1,247 @@ +// basecode.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4100) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wunused-value" +#endif + +#ifndef CRYPTOPP_IMPORTS + +#include "basecode.h" +#include "fltrimpl.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +void BaseN_Encoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + parameters.GetRequiredParameter("BaseN_Encoder", Name::EncodingLookupArray(), m_alphabet); + + parameters.GetRequiredIntParameter("BaseN_Encoder", Name::Log2Base(), m_bitsPerChar); + if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8) + throw InvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7 inclusive"); + + byte padding; + bool pad; + if (parameters.GetValue(Name::PaddingByte(), padding)) + pad = parameters.GetValueWithDefault(Name::Pad(), true); + else + pad = false; + m_padding = pad ? padding : -1; + + m_bytePos = m_bitPos = 0; + + int i = 8; + while (i%m_bitsPerChar != 0) + i += 8; + m_outputBlockSize = i/m_bitsPerChar; + + m_outBuf.New(m_outputBlockSize); +} + +size_t BaseN_Encoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + FILTER_BEGIN; + while (m_inputPosition < length) + { + if (m_bytePos == 0) + memset(m_outBuf, 0, m_outputBlockSize); + + { + unsigned int b = begin[m_inputPosition++], bitsLeftInSource = 8; + while (true) + { + CRYPTOPP_ASSERT(m_bitsPerChar-m_bitPos >= 0); + unsigned int bitsLeftInTarget = (unsigned int)(m_bitsPerChar-m_bitPos); + m_outBuf[m_bytePos] |= b >> (8-bitsLeftInTarget); + if (bitsLeftInSource >= bitsLeftInTarget) + { + m_bitPos = 0; + ++m_bytePos; + bitsLeftInSource -= bitsLeftInTarget; + if (bitsLeftInSource == 0) + break; + b <<= bitsLeftInTarget; + b &= 0xff; + } + else + { + m_bitPos += bitsLeftInSource; + break; + } + } + } + + CRYPTOPP_ASSERT(m_bytePos <= m_outputBlockSize); + if (m_bytePos == m_outputBlockSize) + { + int i; + for (i=0; i 0) + ++m_bytePos; + + int i; + for (i=0; i 0) + { + memset(m_outBuf+m_bytePos, m_padding, m_outputBlockSize-m_bytePos); + m_bytePos = m_outputBlockSize; + } + FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd); + m_bytePos = m_bitPos = 0; + } + FILTER_END_NO_MESSAGE_END; +} + +void BaseN_Decoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + parameters.GetRequiredParameter("BaseN_Decoder", Name::DecodingLookupArray(), m_lookup); + + parameters.GetRequiredIntParameter("BaseN_Decoder", Name::Log2Base(), m_bitsPerChar); + if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8) + throw InvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7 inclusive"); + + m_bytePos = m_bitPos = 0; + + int i = m_bitsPerChar; + while (i%8 != 0) + i += m_bitsPerChar; + m_outputBlockSize = i/8; + + m_outBuf.New(m_outputBlockSize); +} + +size_t BaseN_Decoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + FILTER_BEGIN; + while (m_inputPosition < length) + { + unsigned int value; + value = m_lookup[begin[m_inputPosition++]]; + if (value >= 256) + continue; + + if (m_bytePos == 0 && m_bitPos == 0) + memset(m_outBuf, 0, m_outputBlockSize); + + { + int newBitPos = m_bitPos + m_bitsPerChar; + if (newBitPos <= 8) + m_outBuf[m_bytePos] |= value << (8-newBitPos); + else + { + m_outBuf[m_bytePos] |= value >> (newBitPos-8); + m_outBuf[m_bytePos+1] |= value << (16-newBitPos); + } + + m_bitPos = newBitPos; + while (m_bitPos >= 8) + { + m_bitPos -= 8; + ++m_bytePos; + } + } + + if (m_bytePos == m_outputBlockSize) + { + FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0); + m_bytePos = m_bitPos = 0; + } + } + if (messageEnd) + { + FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd); + m_bytePos = m_bitPos = 0; + } + FILTER_END_NO_MESSAGE_END; +} + +void BaseN_Decoder::InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive) +{ + std::fill(lookup, lookup+256, -1); + + for (unsigned int i=0; i +{ +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/external/ours/library/crypto/src/shared/original/bench.h b/external/ours/library/crypto/src/shared/original/bench.h new file mode 100755 index 000000000..2c30e971c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/bench1.cpp b/external/ours/library/crypto/src/shared/original/bench1.cpp new file mode 100755 index 000000000..e7197ece5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/bench1.cpp @@ -0,0 +1,520 @@ +// bench1.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017 + +#include "cryptlib.h" +#include "bench.h" +#include "validate.h" + +#include "cpu.h" +#include "factory.h" +#include "algparam.h" +#include "argnames.h" +#include "smartptr.h" +#include "stdcpp.h" + +#include "osrng.h" +#include "drbg.h" +#include "darn.h" +#include "mersenne.h" +#include "rdrand.h" +#include "padlkrng.h" + +#include +#include +#include + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4355) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +#ifdef CLOCKS_PER_SEC +const double CLOCK_TICKS_PER_SECOND = (double)CLOCKS_PER_SEC; +#elif defined(CLK_TCK) +const double CLOCK_TICKS_PER_SECOND = (double)CLK_TCK; +#else +const double CLOCK_TICKS_PER_SECOND = 1000000.0; +#endif + +extern const byte defaultKey[] = "0123456789" // 168 + NULL + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + "00000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000"; + +double g_allocatedTime = 0.0, g_hertz = 0.0, g_logTotal = 0.0; +unsigned int g_logCount = 0; +time_t g_testBegin, g_testEnd; + +inline std::string HertzToString(double hertz) +{ + std::ostringstream oss; + oss.precision(3); + + if (hertz >= 0.999e+9) + oss << hertz / 1e+9 << " GHz"; + else if (hertz >= 0.999e+6) + oss << hertz / 1e+6 << " MHz"; + else if (hertz >= 0.999e+3) + oss << hertz / 1e+3 << " KHz"; + else + oss << hertz << " Hz"; + + return oss.str(); +} + +void OutputResultBytes(const char *name, const char *provider, double length, double timeTaken) +{ + std::ostringstream oss; + + // Coverity finding + if (length < 0.000001f) length = 0.000001f; + if (timeTaken < 0.000001f) timeTaken = 0.000001f; + + double mbs = length / timeTaken / (1024*1024); + oss << "\n" << name << "" << provider; + oss << std::setiosflags(std::ios::fixed); + oss << "" << std::setprecision(0) << std::setiosflags(std::ios::fixed) << mbs; + if (g_hertz > 1.0f) + { + const double cpb = timeTaken * g_hertz / length; + if (cpb < 24.0f) + oss << "" << std::setprecision(2) << std::setiosflags(std::ios::fixed) << cpb; + else + oss << "" << std::setprecision(1) << std::setiosflags(std::ios::fixed) << cpb; + } + g_logTotal += log(mbs); + g_logCount++; + + std::cout << oss.str(); +} + +void OutputResultKeying(double iterations, double timeTaken) +{ + std::ostringstream oss; + + // Coverity finding + if (iterations < 0.000001f) iterations = 0.000001f; + if (timeTaken < 0.000001f) timeTaken = 0.000001f; + + oss << "" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << (1000*1000*timeTaken/iterations); + + // Coverity finding + if (g_hertz > 1.0f) + oss << "" << std::setprecision(0) << std::setiosflags(std::ios::fixed) << timeTaken * g_hertz / iterations; + + std::cout << oss.str(); +} + +void OutputResultOperations(const char *name, const char *provider, const char *operation, bool pc, unsigned long iterations, double timeTaken) +{ + CRYPTOPP_UNUSED(provider); + std::ostringstream oss; + + // Coverity finding + if (!iterations) iterations++; + if (timeTaken < 0.000001f) timeTaken = 0.000001f; + + oss << "\n" << name << " " << operation << (pc ? " with precomputation" : ""); + //oss << "" << provider; + oss << "" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << (1000*timeTaken/iterations); + + // Coverity finding + if (g_hertz > 1.0f) + { + const double t = timeTaken * g_hertz / iterations / 1000000; + oss << "" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << t; + } + + g_logTotal += log(iterations/timeTaken); + g_logCount++; + + std::cout << oss.str(); +} + +/* +void BenchMark(const char *name, BlockTransformation &cipher, double timeTotal) +{ + const int BUF_SIZE = RoundUpToMultipleOf(2048U, cipher.OptimalNumberOfParallelBlocks() * cipher.BlockSize()); + AlignedSecByteBlock buf(BUF_SIZE); + buf.SetMark(16); + + const int nBlocks = BUF_SIZE / cipher.BlockSize(); + unsigned long i=0, blocks=1; + double timeTaken; + + clock_t start = ::clock(); + do + { + blocks *= 2; + for (; i(&rng); + if (cipher != NULLPTR) + { + const size_t size = cipher->DefaultKeyLength(); + if (cipher->IsResynchronizable()) + cipher->SetKeyWithIV(buf, size, buf+size); + else + cipher->SetKey(buf, size); + } + + unsigned long long blocks = 1; + double timeTaken; + + clock_t start = ::clock(); + do + { + rng.GenerateBlock(buf, buf.size()); + blocks++; + timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND; + } while (timeTaken < timeTotal); + + std::string provider = rng.AlgorithmProvider(); + OutputResultBytes(name, provider.c_str(), double(blocks) * BUF_SIZE, timeTaken); +} + +// Hack, but we probably need a KeyedRandomNumberGenerator interface +// and a few methods to generalize keying a RNG. X917RNG, Hash_DRBG, +// HMAC_DRBG, AES/CFB RNG and a few others could use it. "A few others" +// includes BLAKE2, ChaCha and Poly1305 when used as a RNG. +void BenchMark(const char *name, NIST_DRBG &rng, double timeTotal) +{ + const int BUF_SIZE = 2048U; + AlignedSecByteBlock buf(BUF_SIZE); + Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE); + buf.SetMark(16); + + rng.IncorporateEntropy(buf, rng.MinEntropyLength()); + unsigned long long blocks = 1; + double timeTaken; + + clock_t start = ::clock(); + do + { + rng.GenerateBlock(buf, buf.size()); + blocks++; + timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND; + } while (timeTaken < timeTotal); + + std::string provider = rng.AlgorithmProvider(); + OutputResultBytes(name, provider.c_str(), double(blocks) * BUF_SIZE, timeTaken); +} + +template +void BenchMarkByNameKeyLess(const char *factoryName, const char *displayName = NULLPTR, const NameValuePairs ¶ms = g_nullNameValuePairs) +{ + CRYPTOPP_UNUSED(params); + std::string name = factoryName; + if (displayName) + name = displayName; + + member_ptr obj(ObjectFactoryRegistry::Registry().CreateObject(factoryName)); + BenchMark(name.c_str(), *obj, g_allocatedTime); +} + +void AddHtmlHeader() +{ + std::ostringstream oss; + + // HTML5 + oss << ""; + oss << "\n"; + + oss << "\n"; + oss << "\n"; + oss << "\nSpeed Comparison of Popular Crypto Algorithms"; + oss << "\n"; + oss << "\n"; + + oss << "\n"; + + oss << "\n

Crypto++ " << CRYPTOPP_VERSION / 100; + oss << '.' << (CRYPTOPP_VERSION % 100) / 10 << '.' << CRYPTOPP_VERSION % 10 << " Benchmarks

"; + + oss << "\n

Here are speed benchmarks for some commonly used cryptographic algorithms.

"; + + if (g_hertz > 1.0f) + oss << "\n

CPU frequency of the test platform is " << HertzToString(g_hertz) << ".

"; + else + oss << "\n

CPU frequency of the test platform was not provided.

" << std::endl; + + std::cout << oss.str(); +} + +void AddHtmlFooter() +{ + std::ostringstream oss; + oss << "\n\n\n"; + std::cout << oss.str(); +} + +void BenchmarkWithCommand(int argc, const char* const argv[]) +{ + std::string command(argv[1]); + float runningTime(argc >= 3 ? Test::StringToValue(argv[2]) : 1.0f); + float cpuFreq(argc >= 4 ? Test::StringToValue(argv[3])*float(1e9) : 0.0f); + std::string algoName(argc >= 5 ? argv[4] : ""); + + // https://github.com/weidai11/cryptopp/issues/983 + if (runningTime > 10.0f) + runningTime = 10.0f; + + if (command == "b") // All benchmarks + Benchmark(Test::All, runningTime, cpuFreq); + else if (command == "b4") // Public key algorithms over EC + Test::Benchmark(Test::PublicKeyEC, runningTime, cpuFreq); + else if (command == "b3") // Public key algorithms + Test::Benchmark(Test::PublicKey, runningTime, cpuFreq); + else if (command == "b2") // Shared key algorithms + Test::Benchmark(Test::SharedKey, runningTime, cpuFreq); + else if (command == "b1") // Unkeyed algorithms + Test::Benchmark(Test::Unkeyed, runningTime, cpuFreq); +} + +void Benchmark(Test::TestClass suites, double t, double hertz) +{ + g_allocatedTime = t; + g_hertz = hertz; + + // Add
in between tables + size_t count_breaks = 0; + + AddHtmlHeader(); + + g_testBegin = ::time(NULLPTR); + + if (static_cast(suites) == 0 || static_cast(suites) > TestLast) + suites = Test::All; + + // Unkeyed algorithms + if (suites & Test::Unkeyed) + { + if (count_breaks) + std::cout << "\n
"; + count_breaks++; + + BenchmarkUnkeyedAlgorithms(t, hertz); + } + + // Shared key algorithms + if (suites & Test::SharedKey) + { + if (count_breaks) + std::cout << "\n
"; + count_breaks++; + + BenchmarkSharedKeyedAlgorithms(t, hertz); + } + + // Public key algorithms + if (suites & Test::PublicKey) + { + if (count_breaks) + std::cout << "\n
"; + count_breaks++; + + BenchmarkPublicKeyAlgorithms(t, hertz); + } + + // Public key algorithms over EC + if (suites & Test::PublicKeyEC) + { + if (count_breaks) + std::cout << "\n
"; + count_breaks++; + + BenchmarkEllipticCurveAlgorithms(t, hertz); + } + + g_testEnd = ::time(NULLPTR); + + std::ostringstream oss; + oss << "\n

Throughput Geometric Average: " << std::setiosflags(std::ios::fixed); + oss << std::exp(g_logTotal/(g_logCount > 0.0f ? g_logCount : 1.0f)) << std::endl; + + oss << "\n

Test started at " << TimeToString(g_testBegin); + oss << "\n
Test ended at " << TimeToString(g_testEnd); + oss << "\n"; + std::cout << oss.str(); + + AddHtmlFooter(); +} + +void BenchmarkUnkeyedAlgorithms(double t, double hertz) +{ + g_allocatedTime = t; + g_hertz = hertz; + + const char *cpb; + if (g_hertz > 1.0f) + cpb = "Cycles/Byte"; + else + cpb = ""; + + std::cout << "\n"; + + std::cout << "\n"; + std::cout << ""; + std::cout << "\n"; + std::cout << "\n"; + { +#ifdef NONBLOCKING_RNG_AVAILABLE + BenchMarkByNameKeyLess("NonblockingRng"); +#endif +#ifdef OS_RNG_AVAILABLE + BenchMarkByNameKeyLess("AutoSeededRandomPool"); + BenchMarkByNameKeyLess("AutoSeededX917RNG(AES)"); +#endif + BenchMarkByNameKeyLess("MT19937"); +#if (CRYPTOPP_BOOL_X86) && !defined(CRYPTOPP_DISABLE_ASM) + if (HasPadlockRNG()) + BenchMarkByNameKeyLess("PadlockRNG"); +#endif +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) && !defined(CRYPTOPP_DISABLE_ASM) + if (HasRDRAND()) + BenchMarkByNameKeyLess("RDRAND"); + if (HasRDSEED()) + BenchMarkByNameKeyLess("RDSEED"); +#endif +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) && !defined(CRYPTOPP_DISABLE_ASM) + if (HasDARN()) + BenchMarkByNameKeyLess("DARN"); +#endif + BenchMarkByNameKeyLess("AES/OFB RNG"); + BenchMarkByNameKeyLess("Hash_DRBG(SHA1)"); + BenchMarkByNameKeyLess("Hash_DRBG(SHA256)"); + BenchMarkByNameKeyLess("HMAC_DRBG(SHA1)"); + BenchMarkByNameKeyLess("HMAC_DRBG(SHA256)"); + } + + std::cout << "\n"; + { + BenchMarkByNameKeyLess("CRC32"); + BenchMarkByNameKeyLess("CRC32C"); + BenchMarkByNameKeyLess("Adler32"); + BenchMarkByNameKeyLess("MD5"); + BenchMarkByNameKeyLess("SHA-1"); + BenchMarkByNameKeyLess("SHA-256"); + BenchMarkByNameKeyLess("SHA-512"); + BenchMarkByNameKeyLess("SHA3-224"); + BenchMarkByNameKeyLess("SHA3-256"); + BenchMarkByNameKeyLess("SHA3-384"); + BenchMarkByNameKeyLess("SHA3-512"); + BenchMarkByNameKeyLess("Keccak-224"); + BenchMarkByNameKeyLess("Keccak-256"); + BenchMarkByNameKeyLess("Keccak-384"); + BenchMarkByNameKeyLess("Keccak-512"); + BenchMarkByNameKeyLess("Tiger"); + BenchMarkByNameKeyLess("Whirlpool"); + BenchMarkByNameKeyLess("RIPEMD-160"); + BenchMarkByNameKeyLess("RIPEMD-320"); + BenchMarkByNameKeyLess("RIPEMD-128"); + BenchMarkByNameKeyLess("RIPEMD-256"); + BenchMarkByNameKeyLess("SM3"); + BenchMarkByNameKeyLess("BLAKE2s"); + BenchMarkByNameKeyLess("BLAKE2b"); + BenchMarkByNameKeyLess("LSH-256"); + BenchMarkByNameKeyLess("LSH-512"); + } + + std::cout << "\n
AlgorithmProviderMiB/Second" << cpb; + + std::cout << "\n
" << std::endl; +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/bench2.cpp b/external/ours/library/crypto/src/shared/original/bench2.cpp new file mode 100755 index 000000000..2cfd62002 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/bench2.cpp @@ -0,0 +1,267 @@ +// bench2.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017 + +#include "cryptlib.h" +#include "bench.h" +#include "validate.h" + +#include "cpu.h" +#include "factory.h" +#include "algparam.h" +#include "argnames.h" +#include "smartptr.h" +#include "stdcpp.h" + +#include "vmac.h" +#include "hmac.h" +#include "ttmac.h" +#include "cmac.h" +#include "dmac.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4355) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +void BenchMarkKeying(SimpleKeyingInterface &c, size_t keyLength, const NameValuePairs ¶ms) +{ + unsigned long iterations = 0; + double timeTaken; + + clock_t start = ::clock(); + do + { + for (unsigned int i=0; i<1024; i++) + c.SetKey(defaultKey, keyLength, params); + timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND; + iterations += 1024; + } + while (timeTaken < g_allocatedTime); + + OutputResultKeying(iterations, timeTaken); +} + +void BenchMark(const char *name, AuthenticatedSymmetricCipher &cipher, double timeTotal) +{ + if (cipher.NeedsPrespecifiedDataLengths()) + cipher.SpecifyDataLengths(0, cipher.MaxMessageLength(), 0); + + BenchMark(name, static_cast(cipher), timeTotal); +} + +template +void BenchMarkByName2(const char *factoryName, size_t keyLength=0, const char *displayName=NULLPTR, const NameValuePairs ¶ms = g_nullNameValuePairs) +{ + std::string name(factoryName ? factoryName : ""); + member_ptr obj(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + + if (keyLength == 0) + keyLength = obj->DefaultKeyLength(); + + if (displayName != NULLPTR) + name = displayName; + else if (keyLength != 0) + name += " (" + IntToString(keyLength * 8) + "-bit key)"; + + obj->SetKey(defaultKey, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), ConstByteArrayParameter(defaultKey, obj->IVSize()), false))); + BenchMark(name.c_str(), *static_cast(obj.get()), g_allocatedTime); + BenchMarkKeying(*obj, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), ConstByteArrayParameter(defaultKey, obj->IVSize()), false))); +} + +template +void BenchMarkByName(const char *factoryName, size_t keyLength=0, const char *displayName=NULLPTR, const NameValuePairs ¶ms = g_nullNameValuePairs) +{ + BenchMarkByName2(factoryName, keyLength, displayName, params); +} + +void BenchmarkSharedKeyedAlgorithms(double t, double hertz) +{ + g_allocatedTime = t; + g_hertz = hertz; + + const char *cpb, *cpk; + if (g_hertz > 1.0f) + { + cpb = "Cycles/Byte"; + cpk = "Cycles to
Setup Key and IV"; + } + else + { + cpb = cpk = ""; + } + + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\n"; + { +#if CRYPTOPP_AESNI_AVAILABLE + if (HasCLMUL()) + BenchMarkByName2("AES/GCM", 0, "GMAC(AES)"); + else +#elif CRYPTOPP_ARM_PMULL_AVAILABLE + if (HasPMULL()) + BenchMarkByName2("AES/GCM", 0, "GMAC(AES)"); + else +#elif CRYPTOPP_POWER8_VMULL_AVAILABLE + if (HasPMULL()) + BenchMarkByName2("AES/GCM", 0, "GMAC(AES)"); + else +#endif + { + BenchMarkByName2("AES/GCM", 0, "GMAC(AES) (2K tables)", MakeParameters(Name::TableSize(), 2048)); + BenchMarkByName2("AES/GCM", 0, "GMAC(AES) (64K tables)", MakeParameters(Name::TableSize(), 64 * 1024)); + } + + BenchMarkByName("VMAC(AES)-64"); + BenchMarkByName("VMAC(AES)-128"); + BenchMarkByName("HMAC(SHA-1)"); + BenchMarkByName("HMAC(SHA-256)"); + BenchMarkByName("Two-Track-MAC"); + BenchMarkByName("CMAC(AES)"); + BenchMarkByName("DMAC(AES)"); + BenchMarkByName("Poly1305(AES)"); + BenchMarkByName("Poly1305TLS"); + BenchMarkByName("BLAKE2s"); + BenchMarkByName("BLAKE2b"); + BenchMarkByName("SipHash-2-4"); + BenchMarkByName("SipHash-4-8"); + } + + std::cout << "\n"; + { + BenchMarkByName("Panama-LE"); + BenchMarkByName("Panama-BE"); + BenchMarkByName("Salsa20", 0, "Salsa20"); + BenchMarkByName("Salsa20", 0, "Salsa20/12", MakeParameters(Name::Rounds(), 12)); + BenchMarkByName("Salsa20", 0, "Salsa20/8", MakeParameters(Name::Rounds(), 8)); + BenchMarkByName("ChaCha", 0, "ChaCha20"); + BenchMarkByName("ChaCha", 0, "ChaCha12", MakeParameters(Name::Rounds(), 12)); + BenchMarkByName("ChaCha", 0, "ChaCha8", MakeParameters(Name::Rounds(), 8)); + BenchMarkByName("ChaChaTLS"); + BenchMarkByName("Sosemanuk"); + BenchMarkByName("Rabbit"); + BenchMarkByName("RabbitWithIV"); + BenchMarkByName("HC-128"); + BenchMarkByName("HC-256"); + BenchMarkByName("MARC4"); + BenchMarkByName("SEAL-3.0-LE"); + BenchMarkByName("WAKE-OFB-LE"); + } + + std::cout << "\n"; + { + BenchMarkByName("AES/CTR", 16); + BenchMarkByName("AES/CTR", 24); + BenchMarkByName("AES/CTR", 32); + BenchMarkByName("AES/CBC", 16); + BenchMarkByName("AES/CBC", 24); + BenchMarkByName("AES/CBC", 32); + BenchMarkByName("AES/XTS", 32); + BenchMarkByName("AES/XTS", 48); + BenchMarkByName("AES/XTS", 64); + BenchMarkByName("AES/OFB", 16); + BenchMarkByName("AES/CFB", 16); + BenchMarkByName("AES/ECB", 16); + BenchMarkByName("ARIA/CTR", 16); + BenchMarkByName("ARIA/CTR", 32); + BenchMarkByName("HIGHT/CTR"); + BenchMarkByName("Camellia/CTR", 16); + BenchMarkByName("Camellia/CTR", 32); + BenchMarkByName("Twofish/CTR"); + BenchMarkByName("Threefish-256(256)/CTR", 32); + BenchMarkByName("Threefish-512(512)/CTR", 64); + BenchMarkByName("Threefish-1024(1024)/CTR", 128); + BenchMarkByName("Serpent/CTR"); + BenchMarkByName("CAST-128/CTR"); + BenchMarkByName("CAST-256/CTR", 32); + BenchMarkByName("RC6/CTR"); + BenchMarkByName("MARS/CTR"); + BenchMarkByName("SHACAL-2/CTR", 16); + BenchMarkByName("SHACAL-2/CTR", 64); + BenchMarkByName("DES/CTR"); + BenchMarkByName("DES-XEX3/CTR"); + BenchMarkByName("DES-EDE3/CTR"); + BenchMarkByName("IDEA/CTR"); + BenchMarkByName("RC5/CTR", 0, "RC5 (r=16)"); + BenchMarkByName("Blowfish/CTR"); + BenchMarkByName("SKIPJACK/CTR"); + BenchMarkByName("SEED/CTR", 0, "SEED/CTR (1/2 K table)"); + BenchMarkByName("SM4/CTR"); + + BenchMarkByName("Kalyna-128/CTR", 16, "Kalyna-128(128)/CTR (128-bit key)"); + BenchMarkByName("Kalyna-128/CTR", 32, "Kalyna-128(256)/CTR (256-bit key)"); + BenchMarkByName("Kalyna-256/CTR", 32, "Kalyna-256(256)/CTR (256-bit key)"); + BenchMarkByName("Kalyna-256/CTR", 64, "Kalyna-256(512)/CTR (512-bit key)"); + BenchMarkByName("Kalyna-512/CTR", 64, "Kalyna-512(512)/CTR (512-bit key)"); + } + + std::cout << "\n"; + { + BenchMarkByName("CHAM-64/CTR", 16, "CHAM-64(128)/CTR (128-bit key)"); + BenchMarkByName("CHAM-128/CTR", 16, "CHAM-128(128)/CTR (128-bit key)"); + BenchMarkByName("CHAM-128/CTR", 32, "CHAM-128(256)/CTR (256-bit key)"); + + BenchMarkByName("LEA-128/CTR", 16, "LEA-128(128)/CTR (128-bit key)"); + BenchMarkByName("LEA-128/CTR", 24, "LEA-128(192)/CTR (192-bit key)"); + BenchMarkByName("LEA-128/CTR", 32, "LEA-128(256)/CTR (256-bit key)"); + + BenchMarkByName("SIMECK-32/CTR", 8, "SIMECK-32(64)/CTR (64-bit key)"); + BenchMarkByName("SIMECK-64/CTR", 16, "SIMECK-64(128)/CTR (128-bit key)"); + + BenchMarkByName("SIMON-64/CTR", 12, "SIMON-64(96)/CTR (96-bit key)"); + BenchMarkByName("SIMON-64/CTR", 16, "SIMON-64(128)/CTR (128-bit key)"); + BenchMarkByName("SIMON-128/CTR", 16, "SIMON-128(128)/CTR (128-bit key)"); + BenchMarkByName("SIMON-128/CTR", 24, "SIMON-128(192)/CTR (192-bit key)"); + BenchMarkByName("SIMON-128/CTR", 32, "SIMON-128(256)/CTR (256-bit key)"); + + BenchMarkByName("SPECK-64/CTR", 12, "SPECK-64(96)/CTR (96-bit key)"); + BenchMarkByName("SPECK-64/CTR", 16, "SPECK-64(128)/CTR (128-bit key)"); + BenchMarkByName("SPECK-128/CTR", 16, "SPECK-128(128)/CTR (128-bit key)"); + BenchMarkByName("SPECK-128/CTR", 24, "SPECK-128(192)/CTR (192-bit key)"); + BenchMarkByName("SPECK-128/CTR", 32, "SPECK-128(256)/CTR (256-bit key)"); + + BenchMarkByName("TEA/CTR"); + BenchMarkByName("XTEA/CTR"); + } + + std::cout << "\n"; + { +#if CRYPTOPP_AESNI_AVAILABLE + if (HasCLMUL()) + BenchMarkByName2("AES/GCM", 0, "AES/GCM"); + else +#elif CRYPTOPP_ARM_PMULL_AVAILABLE + if (HasPMULL()) + BenchMarkByName2("AES/GCM", 0, "AES/GCM"); + else +#elif CRYPTOPP_POWER8_VMULL_AVAILABLE + if (HasPMULL()) + BenchMarkByName2("AES/GCM", 0, "AES/GCM"); + else +#endif + { + BenchMarkByName2("AES/GCM", 0, "AES/GCM (2K tables)", MakeParameters(Name::TableSize(), 2048)); + BenchMarkByName2("AES/GCM", 0, "AES/GCM (64K tables)", MakeParameters(Name::TableSize(), 64 * 1024)); + } + BenchMarkByName2("AES/CCM"); + BenchMarkByName2("AES/EAX"); + BenchMarkByName2("ChaCha20/Poly1305"); + BenchMarkByName2("XChaCha20/Poly1305"); + } + + std::cout << "\n
AlgorithmProviderMiB/Second" << cpb; + std::cout << "Microseconds to
Setup Key and IV" << cpk; + + std::cout << "\n
" << std::endl; +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/bench3.cpp b/external/ours/library/crypto/src/shared/original/bench3.cpp new file mode 100755 index 000000000..7c98661b5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/bench3.cpp @@ -0,0 +1,480 @@ +// bench3.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017 + +#include "cryptlib.h" +#include "bench.h" +#include "validate.h" + +#include "cpu.h" +#include "factory.h" +#include "algparam.h" +#include "argnames.h" +#include "smartptr.h" +#include "stdcpp.h" + +#include "pubkey.h" +#include "gfpcrypt.h" +#include "eccrypto.h" +#include "pkcspad.h" + +#include "files.h" +#include "filters.h" +#include "hex.h" +#include "rsa.h" +#include "nr.h" +#include "dsa.h" +#include "luc.h" +#include "rw.h" +#include "ecp.h" +#include "ec2n.h" +#include "asn.h" +#include "dh.h" +#include "mqv.h" +#include "hmqv.h" +#include "fhmqv.h" +#include "xed25519.h" +#include "xtrcrypt.h" +#include "esign.h" +#include "pssr.h" +#include "oids.h" +#include "randpool.h" +#include "stdcpp.h" +#include "hrtimer.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +void BenchMarkEncryption(const char *name, PK_Encryptor &key, double timeTotal, bool pc = false) +{ + unsigned int len = 16; + SecByteBlock plaintext(len), ciphertext(key.CiphertextLength(len)); + Test::GlobalRNG().GenerateBlock(plaintext, len); + + unsigned int i = 0; + double timeTaken; + + ThreadUserTimer timer; + timer.StartTimer(); + + do + { + key.Encrypt(Test::GlobalRNG(), plaintext, len, ciphertext); + ++i; timeTaken = timer.ElapsedTimeAsDouble(); + } + while (timeTaken < timeTotal); + + std::string provider = key.AlgorithmProvider(); + OutputResultOperations(name, provider.c_str(), "Encryption", pc, i, timeTaken); + + if (!pc && key.GetMaterial().SupportsPrecomputation()) + { + key.AccessMaterial().Precompute(16); + BenchMarkEncryption(name, key, timeTotal, true); + } +} + +void BenchMarkDecryption(const char *name, PK_Decryptor &priv, PK_Encryptor &pub, double timeTotal) +{ + unsigned int len = 16; + SecByteBlock ciphertext(pub.CiphertextLength(len)); + SecByteBlock plaintext(pub.MaxPlaintextLength(ciphertext.size())); + Test::GlobalRNG().GenerateBlock(plaintext, len); + pub.Encrypt(Test::GlobalRNG(), plaintext, len, ciphertext); + + unsigned int i = 0; + double timeTaken; + + ThreadUserTimer timer; + timer.StartTimer(); + + do + { + priv.Decrypt(Test::GlobalRNG(), ciphertext, ciphertext.size(), plaintext); + ++i; timeTaken = timer.ElapsedTimeAsDouble(); + } + while (timeTaken < timeTotal); + + std::string provider = priv.AlgorithmProvider(); + OutputResultOperations(name, provider.c_str(), "Decryption", false, i, timeTaken); +} + +void BenchMarkSigning(const char *name, PK_Signer &key, double timeTotal, bool pc=false) +{ + unsigned int len = 16; + AlignedSecByteBlock message(len), signature(key.SignatureLength()); + Test::GlobalRNG().GenerateBlock(message, len); + + unsigned int i = 0; + double timeTaken; + + ThreadUserTimer timer; + timer.StartTimer(); + + do + { + (void)key.SignMessage(Test::GlobalRNG(), message, len, signature); + ++i; timeTaken = timer.ElapsedTimeAsDouble(); + } + while (timeTaken < timeTotal); + + std::string provider = key.AlgorithmProvider(); + OutputResultOperations(name, provider.c_str(), "Signature", pc, i, timeTaken); + + if (!pc && key.GetMaterial().SupportsPrecomputation()) + { + key.AccessMaterial().Precompute(16); + BenchMarkSigning(name, key, timeTotal, true); + } +} + +void BenchMarkVerification(const char *name, const PK_Signer &priv, PK_Verifier &pub, double timeTotal, bool pc=false) +{ + unsigned int len = 16; + AlignedSecByteBlock message(len), signature(pub.SignatureLength()); + Test::GlobalRNG().GenerateBlock(message, len); + priv.SignMessage(Test::GlobalRNG(), message, len, signature); + + unsigned int i = 0; + double timeTaken; + + ThreadUserTimer timer; + timer.StartTimer(); + + do + { + (void)pub.VerifyMessage(message, len, signature, signature.size()); + ++i; timeTaken = timer.ElapsedTimeAsDouble(); + } + while (timeTaken < timeTotal); + + std::string provider = pub.AlgorithmProvider(); + OutputResultOperations(name, provider.c_str(), "Verification", pc, i, timeTaken); + + if (!pc && pub.GetMaterial().SupportsPrecomputation()) + { + pub.AccessMaterial().Precompute(16); + BenchMarkVerification(name, priv, pub, timeTotal, true); + } +} + +void BenchMarkKeyGen(const char *name, SimpleKeyAgreementDomain &d, double timeTotal, bool pc=false) +{ + SecByteBlock priv(d.PrivateKeyLength()), pub(d.PublicKeyLength()); + + unsigned int i = 0; + double timeTaken; + + ThreadUserTimer timer; + timer.StartTimer(); + + do + { + d.GenerateKeyPair(Test::GlobalRNG(), priv, pub); + ++i; timeTaken = timer.ElapsedTimeAsDouble(); + } + while (timeTaken < timeTotal); + + std::string provider = d.AlgorithmProvider(); + OutputResultOperations(name, provider.c_str(), "Key-Pair Generation", pc, i, timeTaken); + + if (!pc && d.GetMaterial().SupportsPrecomputation()) + { + d.AccessMaterial().Precompute(16); + BenchMarkKeyGen(name, d, timeTotal, true); + } +} + +void BenchMarkKeyGen(const char *name, AuthenticatedKeyAgreementDomain &d, double timeTotal, bool pc=false) +{ + SecByteBlock priv(d.EphemeralPrivateKeyLength()), pub(d.EphemeralPublicKeyLength()); + + unsigned int i = 0; + double timeTaken; + + ThreadUserTimer timer; + timer.StartTimer(); + + do + { + d.GenerateEphemeralKeyPair(Test::GlobalRNG(), priv, pub); + ++i; timeTaken = timer.ElapsedTimeAsDouble(); + } + while (timeTaken < timeTotal); + + std::string provider = d.AlgorithmProvider(); + OutputResultOperations(name, provider.c_str(), "Key-Pair Generation", pc, i, timeTaken); + + if (!pc && d.GetMaterial().SupportsPrecomputation()) + { + d.AccessMaterial().Precompute(16); + BenchMarkKeyGen(name, d, timeTotal, true); + } +} + +void BenchMarkAgreement(const char *name, SimpleKeyAgreementDomain &d, double timeTotal, bool pc=false) +{ + SecByteBlock priv1(d.PrivateKeyLength()), priv2(d.PrivateKeyLength()); + SecByteBlock pub1(d.PublicKeyLength()), pub2(d.PublicKeyLength()); + d.GenerateKeyPair(Test::GlobalRNG(), priv1, pub1); + d.GenerateKeyPair(Test::GlobalRNG(), priv2, pub2); + SecByteBlock val(d.AgreedValueLength()); + + unsigned int i = 0; + double timeTaken; + + ThreadUserTimer timer; + timer.StartTimer(); + + do + { + d.Agree(val, priv1, pub2); + d.Agree(val, priv2, pub1); + i+=2; timeTaken = timer.ElapsedTimeAsDouble(); + } + while (timeTaken < timeTotal); + + std::string provider = d.AlgorithmProvider(); + OutputResultOperations(name, provider.c_str(), "Key Agreement", pc, i, timeTaken); +} + +void BenchMarkAgreement(const char *name, AuthenticatedKeyAgreementDomain &d, double timeTotal, bool pc=false) +{ + SecByteBlock spriv1(d.StaticPrivateKeyLength()), spriv2(d.StaticPrivateKeyLength()); + SecByteBlock epriv1(d.EphemeralPrivateKeyLength()), epriv2(d.EphemeralPrivateKeyLength()); + SecByteBlock spub1(d.StaticPublicKeyLength()), spub2(d.StaticPublicKeyLength()); + SecByteBlock epub1(d.EphemeralPublicKeyLength()), epub2(d.EphemeralPublicKeyLength()); + d.GenerateStaticKeyPair(Test::GlobalRNG(), spriv1, spub1); + d.GenerateStaticKeyPair(Test::GlobalRNG(), spriv2, spub2); + d.GenerateEphemeralKeyPair(Test::GlobalRNG(), epriv1, epub1); + d.GenerateEphemeralKeyPair(Test::GlobalRNG(), epriv2, epub2); + SecByteBlock val(d.AgreedValueLength()); + + unsigned int i = 0; + double timeTaken; + + ThreadUserTimer timer; + timer.StartTimer(); + + do + { + d.Agree(val, spriv1, epriv1, spub2, epub2); + d.Agree(val, spriv2, epriv2, spub1, epub1); + i+=2; timeTaken = timer.ElapsedTimeAsDouble(); + } + while (timeTaken < timeTotal); + + std::string provider = d.AlgorithmProvider(); + OutputResultOperations(name, provider.c_str(), "Key Agreement", pc, i, timeTaken); +} + +template +void BenchMarkCrypto(const char *filename, const char *name, double timeTotal) +{ + FileSource f(DataDir(filename).c_str(), true, new HexDecoder); + typename SCHEME::Decryptor priv(f); + typename SCHEME::Encryptor pub(priv); + BenchMarkEncryption(name, pub, timeTotal); + BenchMarkDecryption(name, priv, pub, timeTotal); +} + +template +void BenchMarkSignature(const char *filename, const char *name, double timeTotal) +{ + FileSource f(DataDir(filename).c_str(), true, new HexDecoder); + typename SCHEME::Signer priv(f); + typename SCHEME::Verifier pub(priv); + BenchMarkSigning(name, priv, timeTotal); + BenchMarkVerification(name, priv, pub, timeTotal); +} + +template +void BenchMarkKeyAgreement(const char *filename, const char *name, double timeTotal) +{ + FileSource f(DataDir(filename).c_str(), true, new HexDecoder); + D d(f); + BenchMarkKeyGen(name, d, timeTotal); + BenchMarkAgreement(name, d, timeTotal); +} + +void BenchmarkPublicKeyAlgorithms(double t, double hertz) +{ + g_allocatedTime = t; + g_hertz = hertz; + + const char *mco; + if (g_hertz > 1.0f) + mco = "Megacycles/Operation"; + else + mco = ""; + + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\n"; + { + BenchMarkCrypto > >("TestData/rsa1024.dat", "RSA 1024", t); + BenchMarkCrypto > >("TestData/luc1024.dat", "LUC 1024", t); + BenchMarkCrypto >("TestData/dlie1024.dat", "DLIES 1024", t); + BenchMarkCrypto >("TestData/lucc512.dat", "LUCELG 512", t); + } + + std::cout << "\n"; + { + BenchMarkCrypto > >("TestData/rsa2048.dat", "RSA 2048", t); + BenchMarkCrypto > >("TestData/luc2048.dat", "LUC 2048", t); + BenchMarkCrypto >("TestData/dlie2048.dat", "DLIES 2048", t); + BenchMarkCrypto >("TestData/lucc1024.dat", "LUCELG 1024", t); + } + + std::cout << "\n"; + { + BenchMarkSignature >("TestData/rsa1024.dat", "RSA 1024", t); + BenchMarkSignature >("TestData/rw1024.dat", "RW 1024", t); + BenchMarkSignature >("TestData/luc1024.dat", "LUC 1024", t); + BenchMarkSignature >("TestData/nr1024.dat", "NR 1024", t); + BenchMarkSignature("TestData/dsa1024.dat", "DSA 1024", t); + BenchMarkSignature >("TestData/lucs512.dat", "LUC-HMP 512", t); + BenchMarkSignature >("TestData/esig1023.dat", "ESIGN 1023", t); + BenchMarkSignature >("TestData/esig1536.dat", "ESIGN 1536", t); + } + + std::cout << "\n"; + { + BenchMarkSignature >("TestData/rsa2048.dat", "RSA 2048", t); + BenchMarkSignature >("TestData/rw2048.dat", "RW 2048", t); + BenchMarkSignature >("TestData/luc2048.dat", "LUC 2048", t); + BenchMarkSignature >("TestData/nr2048.dat", "NR 2048", t); + BenchMarkSignature >("TestData/lucs1024.dat", "LUC-HMP 1024", t); + BenchMarkSignature >("TestData/esig2046.dat", "ESIGN 2046", t); + } + + std::cout << "\n"; + { + BenchMarkKeyAgreement("TestData/xtrdh171.dat", "XTR-DH 171", t); + BenchMarkKeyAgreement("TestData/xtrdh342.dat", "XTR-DH 342", t); + BenchMarkKeyAgreement("TestData/dh1024.dat", "DH 1024", t); + BenchMarkKeyAgreement("TestData/dh2048.dat", "DH 2048", t); + BenchMarkKeyAgreement("TestData/lucd512.dat", "LUCDIF 512", t); + BenchMarkKeyAgreement("TestData/lucd1024.dat", "LUCDIF 1024", t); + BenchMarkKeyAgreement("TestData/mqv1024.dat", "MQV 1024", t); + BenchMarkKeyAgreement("TestData/mqv2048.dat", "MQV 2048", t); + } + + std::cout << "\n
OperationMilliseconds/Operation" << mco; + + std::cout << "\n
" << std::endl; +} + +void BenchmarkEllipticCurveAlgorithms(double t, double hertz) +{ + g_allocatedTime = t; + g_hertz = hertz; + + const char *mco; + if (g_hertz > 1.0f) + mco = "Megacycles/Operation"; + else + mco = ""; + + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\n"; + { + ed25519::Signer sign(Test::GlobalRNG()); + ed25519::Verifier verify(sign); + x25519 agree(Test::GlobalRNG()); + + BenchMarkSigning("ed25519", sign, t); + BenchMarkVerification("ed25519", sign, verify, t); + BenchMarkKeyGen("x25519", agree, t); + BenchMarkAgreement("x25519", agree, t); + } + +#if 0 + std::cout << "\n"; + { + BenchMarkKeyAgreement("TestData/mqv160.dat", "MQV P-160", t); + BenchMarkKeyAgreement("TestData/mqv256.dat", "MQV P-256", t); + BenchMarkKeyAgreement("TestData/mqv384.dat", "MQV P-384", t); + BenchMarkKeyAgreement("TestData/mqv512.dat", "MQV P-521", t); + + BenchMarkKeyAgreement("TestData/hmqv160.dat", "HMQV P-160", t); + BenchMarkKeyAgreement("TestData/hmqv256.dat", "HMQV P-256", t); + BenchMarkKeyAgreement("TestData/hmqv384.dat", "HMQV P-384", t); + BenchMarkKeyAgreement("TestData/hmqv512.dat", "HMQV P-521", t); + + BenchMarkKeyAgreement("TestData/fhmqv160.dat", "FHMQV P-160", t); + BenchMarkKeyAgreement("TestData/fhmqv256.dat", "FHMQV P-256", t); + BenchMarkKeyAgreement("TestData/fhmqv384.dat", "FHMQV P-384", t); + BenchMarkKeyAgreement("TestData/fhmqv512.dat", "FHMQV P-521", t); + } +#endif + + std::cout << "\n"; + { + ECIES::Decryptor cpriv(Test::GlobalRNG(), ASN1::secp256k1()); + ECIES::Encryptor cpub(cpriv); + ECDSA::Signer spriv(cpriv); + ECDSA::Verifier spub(spriv); + ECDSA_RFC6979::Signer spriv2(cpriv); + ECDSA_RFC6979::Verifier spub2(spriv2); + ECGDSA::Signer spriv3(Test::GlobalRNG(), ASN1::secp256k1()); + ECGDSA::Verifier spub3(spriv3); + ECDH::Domain ecdhc(ASN1::secp256k1()); + ECMQV::Domain ecmqvc(ASN1::secp256k1()); + + BenchMarkEncryption("ECIES over GF(p) 256", cpub, t); + BenchMarkDecryption("ECIES over GF(p) 256", cpriv, cpub, t); + BenchMarkSigning("ECDSA over GF(p) 256", spriv, t); + BenchMarkVerification("ECDSA over GF(p) 256", spriv, spub, t); + BenchMarkSigning("ECDSA-RFC6979 over GF(p) 256", spriv2, t); + BenchMarkVerification("ECDSA-RFC6979 over GF(p) 256", spriv2, spub2, t); + BenchMarkSigning("ECGDSA over GF(p) 256", spriv3, t); + BenchMarkVerification("ECGDSA over GF(p) 256", spriv3, spub3, t); + BenchMarkKeyGen("ECDHC over GF(p) 256", ecdhc, t); + BenchMarkAgreement("ECDHC over GF(p) 256", ecdhc, t); + BenchMarkKeyGen("ECMQVC over GF(p) 256", ecmqvc, t); + BenchMarkAgreement("ECMQVC over GF(p) 256", ecmqvc, t); + } + + std::cout << "\n"; + { + ECIES::Decryptor cpriv(Test::GlobalRNG(), ASN1::sect233r1()); + ECIES::Encryptor cpub(cpriv); + ECDSA::Signer spriv(cpriv); + ECDSA::Verifier spub(spriv); + ECDSA_RFC6979::Signer spriv2(cpriv); + ECDSA_RFC6979::Verifier spub2(spriv2); + ECGDSA::Signer spriv3(Test::GlobalRNG(), ASN1::sect233r1()); + ECGDSA::Verifier spub3(spriv3); + ECDH::Domain ecdhc(ASN1::sect233r1()); + ECMQV::Domain ecmqvc(ASN1::sect233r1()); + + BenchMarkEncryption("ECIES over GF(2^n) 233", cpub, t); + BenchMarkDecryption("ECIES over GF(2^n) 233", cpriv, cpub, t); + BenchMarkSigning("ECDSA over GF(2^n) 233", spriv, t); + BenchMarkVerification("ECDSA over GF(2^n) 233", spriv, spub, t); + BenchMarkSigning("ECDSA-RFC6979 over GF(2^n) 233", spriv2, t); + BenchMarkVerification("ECDSA-RFC6979 over GF(2^n) 233", spriv2, spub2, t); + BenchMarkSigning("ECGDSA over GF(2^n) 233", spriv3, t); + BenchMarkVerification("ECGDSA over GF(2^n) 233", spriv3, spub3, t); + BenchMarkKeyGen("ECDHC over GF(2^n) 233", ecdhc, t); + BenchMarkAgreement("ECDHC over GF(2^n) 233", ecdhc, t); + BenchMarkKeyGen("ECMQVC over GF(2^n) 233", ecmqvc, t); + BenchMarkAgreement("ECMQVC over GF(2^n) 233", ecmqvc, t); + } + + std::cout << "\n
OperationMilliseconds/Operation" << mco; + + std::cout << "\n
" << std::endl; +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/bfinit.cpp b/external/ours/library/crypto/src/shared/original/bfinit.cpp new file mode 100755 index 000000000..06db2096f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/bfinit.cpp @@ -0,0 +1,277 @@ +#include "pch.h" +#include "blowfish.h" + +NAMESPACE_BEGIN(CryptoPP) + +const word32 Blowfish::Base::p_init[Blowfish::ROUNDS+2] = +{ + 608135816U, 2242054355U, 320440878U, 57701188U, + 2752067618U, 698298832U, 137296536U, 3964562569U, + 1160258022U, 953160567U, 3193202383U, 887688300U, + 3232508343U, 3380367581U, 1065670069U, 3041331479U, + 2450970073U, 2306472731U +} ; + +const word32 Blowfish::Base::s_init[4*256] = { + 3509652390U, 2564797868U, 805139163U, 3491422135U, + 3101798381U, 1780907670U, 3128725573U, 4046225305U, + 614570311U, 3012652279U, 134345442U, 2240740374U, + 1667834072U, 1901547113U, 2757295779U, 4103290238U, + 227898511U, 1921955416U, 1904987480U, 2182433518U, + 2069144605U, 3260701109U, 2620446009U, 720527379U, + 3318853667U, 677414384U, 3393288472U, 3101374703U, + 2390351024U, 1614419982U, 1822297739U, 2954791486U, + 3608508353U, 3174124327U, 2024746970U, 1432378464U, + 3864339955U, 2857741204U, 1464375394U, 1676153920U, + 1439316330U, 715854006U, 3033291828U, 289532110U, + 2706671279U, 2087905683U, 3018724369U, 1668267050U, + 732546397U, 1947742710U, 3462151702U, 2609353502U, + 2950085171U, 1814351708U, 2050118529U, 680887927U, + 999245976U, 1800124847U, 3300911131U, 1713906067U, + 1641548236U, 4213287313U, 1216130144U, 1575780402U, + 4018429277U, 3917837745U, 3693486850U, 3949271944U, + 596196993U, 3549867205U, 258830323U, 2213823033U, + 772490370U, 2760122372U, 1774776394U, 2652871518U, + 566650946U, 4142492826U, 1728879713U, 2882767088U, + 1783734482U, 3629395816U, 2517608232U, 2874225571U, + 1861159788U, 326777828U, 3124490320U, 2130389656U, + 2716951837U, 967770486U, 1724537150U, 2185432712U, + 2364442137U, 1164943284U, 2105845187U, 998989502U, + 3765401048U, 2244026483U, 1075463327U, 1455516326U, + 1322494562U, 910128902U, 469688178U, 1117454909U, + 936433444U, 3490320968U, 3675253459U, 1240580251U, + 122909385U, 2157517691U, 634681816U, 4142456567U, + 3825094682U, 3061402683U, 2540495037U, 79693498U, + 3249098678U, 1084186820U, 1583128258U, 426386531U, + 1761308591U, 1047286709U, 322548459U, 995290223U, + 1845252383U, 2603652396U, 3431023940U, 2942221577U, + 3202600964U, 3727903485U, 1712269319U, 422464435U, + 3234572375U, 1170764815U, 3523960633U, 3117677531U, + 1434042557U, 442511882U, 3600875718U, 1076654713U, + 1738483198U, 4213154764U, 2393238008U, 3677496056U, + 1014306527U, 4251020053U, 793779912U, 2902807211U, + 842905082U, 4246964064U, 1395751752U, 1040244610U, + 2656851899U, 3396308128U, 445077038U, 3742853595U, + 3577915638U, 679411651U, 2892444358U, 2354009459U, + 1767581616U, 3150600392U, 3791627101U, 3102740896U, + 284835224U, 4246832056U, 1258075500U, 768725851U, + 2589189241U, 3069724005U, 3532540348U, 1274779536U, + 3789419226U, 2764799539U, 1660621633U, 3471099624U, + 4011903706U, 913787905U, 3497959166U, 737222580U, + 2514213453U, 2928710040U, 3937242737U, 1804850592U, + 3499020752U, 2949064160U, 2386320175U, 2390070455U, + 2415321851U, 4061277028U, 2290661394U, 2416832540U, + 1336762016U, 1754252060U, 3520065937U, 3014181293U, + 791618072U, 3188594551U, 3933548030U, 2332172193U, + 3852520463U, 3043980520U, 413987798U, 3465142937U, + 3030929376U, 4245938359U, 2093235073U, 3534596313U, + 375366246U, 2157278981U, 2479649556U, 555357303U, + 3870105701U, 2008414854U, 3344188149U, 4221384143U, + 3956125452U, 2067696032U, 3594591187U, 2921233993U, + 2428461U, 544322398U, 577241275U, 1471733935U, + 610547355U, 4027169054U, 1432588573U, 1507829418U, + 2025931657U, 3646575487U, 545086370U, 48609733U, + 2200306550U, 1653985193U, 298326376U, 1316178497U, + 3007786442U, 2064951626U, 458293330U, 2589141269U, + 3591329599U, 3164325604U, 727753846U, 2179363840U, + 146436021U, 1461446943U, 4069977195U, 705550613U, + 3059967265U, 3887724982U, 4281599278U, 3313849956U, + 1404054877U, 2845806497U, 146425753U, 1854211946U, + + 1266315497U, 3048417604U, 3681880366U, 3289982499U, + 2909710000U, 1235738493U, 2632868024U, 2414719590U, + 3970600049U, 1771706367U, 1449415276U, 3266420449U, + 422970021U, 1963543593U, 2690192192U, 3826793022U, + 1062508698U, 1531092325U, 1804592342U, 2583117782U, + 2714934279U, 4024971509U, 1294809318U, 4028980673U, + 1289560198U, 2221992742U, 1669523910U, 35572830U, + 157838143U, 1052438473U, 1016535060U, 1802137761U, + 1753167236U, 1386275462U, 3080475397U, 2857371447U, + 1040679964U, 2145300060U, 2390574316U, 1461121720U, + 2956646967U, 4031777805U, 4028374788U, 33600511U, + 2920084762U, 1018524850U, 629373528U, 3691585981U, + 3515945977U, 2091462646U, 2486323059U, 586499841U, + 988145025U, 935516892U, 3367335476U, 2599673255U, + 2839830854U, 265290510U, 3972581182U, 2759138881U, + 3795373465U, 1005194799U, 847297441U, 406762289U, + 1314163512U, 1332590856U, 1866599683U, 4127851711U, + 750260880U, 613907577U, 1450815602U, 3165620655U, + 3734664991U, 3650291728U, 3012275730U, 3704569646U, + 1427272223U, 778793252U, 1343938022U, 2676280711U, + 2052605720U, 1946737175U, 3164576444U, 3914038668U, + 3967478842U, 3682934266U, 1661551462U, 3294938066U, + 4011595847U, 840292616U, 3712170807U, 616741398U, + 312560963U, 711312465U, 1351876610U, 322626781U, + 1910503582U, 271666773U, 2175563734U, 1594956187U, + 70604529U, 3617834859U, 1007753275U, 1495573769U, + 4069517037U, 2549218298U, 2663038764U, 504708206U, + 2263041392U, 3941167025U, 2249088522U, 1514023603U, + 1998579484U, 1312622330U, 694541497U, 2582060303U, + 2151582166U, 1382467621U, 776784248U, 2618340202U, + 3323268794U, 2497899128U, 2784771155U, 503983604U, + 4076293799U, 907881277U, 423175695U, 432175456U, + 1378068232U, 4145222326U, 3954048622U, 3938656102U, + 3820766613U, 2793130115U, 2977904593U, 26017576U, + 3274890735U, 3194772133U, 1700274565U, 1756076034U, + 4006520079U, 3677328699U, 720338349U, 1533947780U, + 354530856U, 688349552U, 3973924725U, 1637815568U, + 332179504U, 3949051286U, 53804574U, 2852348879U, + 3044236432U, 1282449977U, 3583942155U, 3416972820U, + 4006381244U, 1617046695U, 2628476075U, 3002303598U, + 1686838959U, 431878346U, 2686675385U, 1700445008U, + 1080580658U, 1009431731U, 832498133U, 3223435511U, + 2605976345U, 2271191193U, 2516031870U, 1648197032U, + 4164389018U, 2548247927U, 300782431U, 375919233U, + 238389289U, 3353747414U, 2531188641U, 2019080857U, + 1475708069U, 455242339U, 2609103871U, 448939670U, + 3451063019U, 1395535956U, 2413381860U, 1841049896U, + 1491858159U, 885456874U, 4264095073U, 4001119347U, + 1565136089U, 3898914787U, 1108368660U, 540939232U, + 1173283510U, 2745871338U, 3681308437U, 4207628240U, + 3343053890U, 4016749493U, 1699691293U, 1103962373U, + 3625875870U, 2256883143U, 3830138730U, 1031889488U, + 3479347698U, 1535977030U, 4236805024U, 3251091107U, + 2132092099U, 1774941330U, 1199868427U, 1452454533U, + 157007616U, 2904115357U, 342012276U, 595725824U, + 1480756522U, 206960106U, 497939518U, 591360097U, + 863170706U, 2375253569U, 3596610801U, 1814182875U, + 2094937945U, 3421402208U, 1082520231U, 3463918190U, + 2785509508U, 435703966U, 3908032597U, 1641649973U, + 2842273706U, 3305899714U, 1510255612U, 2148256476U, + 2655287854U, 3276092548U, 4258621189U, 236887753U, + 3681803219U, 274041037U, 1734335097U, 3815195456U, + 3317970021U, 1899903192U, 1026095262U, 4050517792U, + 356393447U, 2410691914U, 3873677099U, 3682840055U, + + 3913112168U, 2491498743U, 4132185628U, 2489919796U, + 1091903735U, 1979897079U, 3170134830U, 3567386728U, + 3557303409U, 857797738U, 1136121015U, 1342202287U, + 507115054U, 2535736646U, 337727348U, 3213592640U, + 1301675037U, 2528481711U, 1895095763U, 1721773893U, + 3216771564U, 62756741U, 2142006736U, 835421444U, + 2531993523U, 1442658625U, 3659876326U, 2882144922U, + 676362277U, 1392781812U, 170690266U, 3921047035U, + 1759253602U, 3611846912U, 1745797284U, 664899054U, + 1329594018U, 3901205900U, 3045908486U, 2062866102U, + 2865634940U, 3543621612U, 3464012697U, 1080764994U, + 553557557U, 3656615353U, 3996768171U, 991055499U, + 499776247U, 1265440854U, 648242737U, 3940784050U, + 980351604U, 3713745714U, 1749149687U, 3396870395U, + 4211799374U, 3640570775U, 1161844396U, 3125318951U, + 1431517754U, 545492359U, 4268468663U, 3499529547U, + 1437099964U, 2702547544U, 3433638243U, 2581715763U, + 2787789398U, 1060185593U, 1593081372U, 2418618748U, + 4260947970U, 69676912U, 2159744348U, 86519011U, + 2512459080U, 3838209314U, 1220612927U, 3339683548U, + 133810670U, 1090789135U, 1078426020U, 1569222167U, + 845107691U, 3583754449U, 4072456591U, 1091646820U, + 628848692U, 1613405280U, 3757631651U, 526609435U, + 236106946U, 48312990U, 2942717905U, 3402727701U, + 1797494240U, 859738849U, 992217954U, 4005476642U, + 2243076622U, 3870952857U, 3732016268U, 765654824U, + 3490871365U, 2511836413U, 1685915746U, 3888969200U, + 1414112111U, 2273134842U, 3281911079U, 4080962846U, + 172450625U, 2569994100U, 980381355U, 4109958455U, + 2819808352U, 2716589560U, 2568741196U, 3681446669U, + 3329971472U, 1835478071U, 660984891U, 3704678404U, + 4045999559U, 3422617507U, 3040415634U, 1762651403U, + 1719377915U, 3470491036U, 2693910283U, 3642056355U, + 3138596744U, 1364962596U, 2073328063U, 1983633131U, + 926494387U, 3423689081U, 2150032023U, 4096667949U, + 1749200295U, 3328846651U, 309677260U, 2016342300U, + 1779581495U, 3079819751U, 111262694U, 1274766160U, + 443224088U, 298511866U, 1025883608U, 3806446537U, + 1145181785U, 168956806U, 3641502830U, 3584813610U, + 1689216846U, 3666258015U, 3200248200U, 1692713982U, + 2646376535U, 4042768518U, 1618508792U, 1610833997U, + 3523052358U, 4130873264U, 2001055236U, 3610705100U, + 2202168115U, 4028541809U, 2961195399U, 1006657119U, + 2006996926U, 3186142756U, 1430667929U, 3210227297U, + 1314452623U, 4074634658U, 4101304120U, 2273951170U, + 1399257539U, 3367210612U, 3027628629U, 1190975929U, + 2062231137U, 2333990788U, 2221543033U, 2438960610U, + 1181637006U, 548689776U, 2362791313U, 3372408396U, + 3104550113U, 3145860560U, 296247880U, 1970579870U, + 3078560182U, 3769228297U, 1714227617U, 3291629107U, + 3898220290U, 166772364U, 1251581989U, 493813264U, + 448347421U, 195405023U, 2709975567U, 677966185U, + 3703036547U, 1463355134U, 2715995803U, 1338867538U, + 1343315457U, 2802222074U, 2684532164U, 233230375U, + 2599980071U, 2000651841U, 3277868038U, 1638401717U, + 4028070440U, 3237316320U, 6314154U, 819756386U, + 300326615U, 590932579U, 1405279636U, 3267499572U, + 3150704214U, 2428286686U, 3959192993U, 3461946742U, + 1862657033U, 1266418056U, 963775037U, 2089974820U, + 2263052895U, 1917689273U, 448879540U, 3550394620U, + 3981727096U, 150775221U, 3627908307U, 1303187396U, + 508620638U, 2975983352U, 2726630617U, 1817252668U, + 1876281319U, 1457606340U, 908771278U, 3720792119U, + 3617206836U, 2455994898U, 1729034894U, 1080033504U, + + 976866871U, 3556439503U, 2881648439U, 1522871579U, + 1555064734U, 1336096578U, 3548522304U, 2579274686U, + 3574697629U, 3205460757U, 3593280638U, 3338716283U, + 3079412587U, 564236357U, 2993598910U, 1781952180U, + 1464380207U, 3163844217U, 3332601554U, 1699332808U, + 1393555694U, 1183702653U, 3581086237U, 1288719814U, + 691649499U, 2847557200U, 2895455976U, 3193889540U, + 2717570544U, 1781354906U, 1676643554U, 2592534050U, + 3230253752U, 1126444790U, 2770207658U, 2633158820U, + 2210423226U, 2615765581U, 2414155088U, 3127139286U, + 673620729U, 2805611233U, 1269405062U, 4015350505U, + 3341807571U, 4149409754U, 1057255273U, 2012875353U, + 2162469141U, 2276492801U, 2601117357U, 993977747U, + 3918593370U, 2654263191U, 753973209U, 36408145U, + 2530585658U, 25011837U, 3520020182U, 2088578344U, + 530523599U, 2918365339U, 1524020338U, 1518925132U, + 3760827505U, 3759777254U, 1202760957U, 3985898139U, + 3906192525U, 674977740U, 4174734889U, 2031300136U, + 2019492241U, 3983892565U, 4153806404U, 3822280332U, + 352677332U, 2297720250U, 60907813U, 90501309U, + 3286998549U, 1016092578U, 2535922412U, 2839152426U, + 457141659U, 509813237U, 4120667899U, 652014361U, + 1966332200U, 2975202805U, 55981186U, 2327461051U, + 676427537U, 3255491064U, 2882294119U, 3433927263U, + 1307055953U, 942726286U, 933058658U, 2468411793U, + 3933900994U, 4215176142U, 1361170020U, 2001714738U, + 2830558078U, 3274259782U, 1222529897U, 1679025792U, + 2729314320U, 3714953764U, 1770335741U, 151462246U, + 3013232138U, 1682292957U, 1483529935U, 471910574U, + 1539241949U, 458788160U, 3436315007U, 1807016891U, + 3718408830U, 978976581U, 1043663428U, 3165965781U, + 1927990952U, 4200891579U, 2372276910U, 3208408903U, + 3533431907U, 1412390302U, 2931980059U, 4132332400U, + 1947078029U, 3881505623U, 4168226417U, 2941484381U, + 1077988104U, 1320477388U, 886195818U, 18198404U, + 3786409000U, 2509781533U, 112762804U, 3463356488U, + 1866414978U, 891333506U, 18488651U, 661792760U, + 1628790961U, 3885187036U, 3141171499U, 876946877U, + 2693282273U, 1372485963U, 791857591U, 2686433993U, + 3759982718U, 3167212022U, 3472953795U, 2716379847U, + 445679433U, 3561995674U, 3504004811U, 3574258232U, + 54117162U, 3331405415U, 2381918588U, 3769707343U, + 4154350007U, 1140177722U, 4074052095U, 668550556U, + 3214352940U, 367459370U, 261225585U, 2610173221U, + 4209349473U, 3468074219U, 3265815641U, 314222801U, + 3066103646U, 3808782860U, 282218597U, 3406013506U, + 3773591054U, 379116347U, 1285071038U, 846784868U, + 2669647154U, 3771962079U, 3550491691U, 2305946142U, + 453669953U, 1268987020U, 3317592352U, 3279303384U, + 3744833421U, 2610507566U, 3859509063U, 266596637U, + 3847019092U, 517658769U, 3462560207U, 3443424879U, + 370717030U, 4247526661U, 2224018117U, 4143653529U, + 4112773975U, 2788324899U, 2477274417U, 1456262402U, + 2901442914U, 1517677493U, 1846949527U, 2295493580U, + 3734397586U, 2176403920U, 1280348187U, 1908823572U, + 3871786941U, 846861322U, 1172426758U, 3287448474U, + 3383383037U, 1655181056U, 3139813346U, 901632758U, + 1897031941U, 2986607138U, 3066810236U, 3447102507U, + 1393639104U, 373351379U, 950779232U, 625454576U, + 3124240540U, 4148612726U, 2007998917U, 544563296U, + 2244738638U, 2330496472U, 2058025392U, 1291430526U, + 424198748U, 50039436U, 29584100U, 3605783033U, + 2429876329U, 2791104160U, 1057563949U, 3255363231U, + 3075367218U, 3463963227U, 1469046755U, 985887462U +}; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/blake2.cpp b/external/ours/library/crypto/src/shared/original/blake2.cpp new file mode 100755 index 000000000..3504f1319 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/blake2.cpp @@ -0,0 +1,797 @@ +// blake2.cpp - 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. +// +// The BLAKE2b and BLAKE2s numbers are consistent with the BLAKE2 team's +// numbers. However, we have an Altivec implementation of BLAKE2s, +// and a POWER8 implementation of BLAKE2b (BLAKE2 team is missing them). +// Altivec code is about 2x faster than C++ when using GCC 5.0 or +// above. The POWER8 code is about 2.5x faster than C++ when using GCC 5.0 +// or above. If you use GCC 4.0 (PowerMac) or GCC 4.8 (GCC Compile Farm) +// then the PowerPC code will be slower than C++. Be sure to use GCC 5.0 +// or above for PowerPC builds or disable Altivec for BLAKE2b and BLAKE2s +// if using the old compilers. + +#include "pch.h" +#include "config.h" +#include "cryptlib.h" +#include "argnames.h" +#include "algparam.h" +#include "blake2.h" +#include "cpu.h" + +// Uncomment for benchmarking C++ against SSE2 or NEON. +// Do so in both blake2.cpp and blake2_simd.cpp. +// #undef CRYPTOPP_SSE41_AVAILABLE +// #undef CRYPTOPP_ARM_NEON_AVAILABLE +// #undef CRYPTOPP_ALTIVEC_AVAILABLE +// #undef CRYPTOPP_POWER8_AVAILABLE + +// Disable NEON/ASIMD for Cortex-A53 and A57. The shifts are too slow and C/C++ is about +// 3 cpb faster than NEON/ASIMD. Also see http://github.com/weidai11/cryptopp/issues/367. +#if (defined(__aarch32__) || defined(__aarch64__)) && defined(CRYPTOPP_SLOW_ARMV8_SHIFT) +# undef CRYPTOPP_ARM_NEON_AVAILABLE +#endif + +// BLAKE2s bug on AIX 7.1 (POWER7) with XLC 12.01 +// https://github.com/weidai11/cryptopp/issues/743 +#if defined(__xlC__) && (__xlC__ < 0x0d01) +# define CRYPTOPP_DISABLE_ALTIVEC 1 +# undef CRYPTOPP_POWER7_AVAILABLE +# undef CRYPTOPP_POWER8_AVAILABLE +# undef CRYPTOPP_ALTIVEC_AVAILABLE +#endif + +// Can't use GetAlignmentOf() because of C++11 and constexpr +// Can use 'const unsigned int' because of MSVC 2013 +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +# define ALIGN_SPEC32 16 +# define ALIGN_SPEC64 16 +#else +# define ALIGN_SPEC32 4 +# define ALIGN_SPEC64 8 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// Export the tables to the SIMD files +extern const word32 BLAKE2S_IV[8]; +extern const word64 BLAKE2B_IV[8]; + +CRYPTOPP_ALIGN_DATA(ALIGN_SPEC32) +const word32 BLAKE2S_IV[8] = { + 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, + 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL +}; + +CRYPTOPP_ALIGN_DATA(ALIGN_SPEC64) +const word64 BLAKE2B_IV[8] = { + W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b), + W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1), + W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f), + W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179) +}; + +NAMESPACE_END + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::rotrConstant; + +CRYPTOPP_ALIGN_DATA(ALIGN_SPEC32) +const byte BLAKE2S_SIGMA[10][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 }, +}; + +CRYPTOPP_ALIGN_DATA(ALIGN_SPEC32) +const byte BLAKE2B_SIGMA[12][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + +template +inline void BLAKE2B_G(const word64 m[16], word64& a, word64& b, word64& c, word64& d) +{ + a = a + b + m[BLAKE2B_SIGMA[R][2*N+0]]; + d = rotrConstant<32>(d ^ a); + c = c + d; + b = rotrConstant<24>(b ^ c); + a = a + b + m[BLAKE2B_SIGMA[R][2*N+1]]; + d = rotrConstant<16>(d ^ a); + c = c + d; + b = rotrConstant<63>(b ^ c); +} + +template +inline void BLAKE2B_ROUND(const word64 m[16], word64 v[16]) +{ + BLAKE2B_G(m,v[ 0],v[ 4],v[ 8],v[12]); + BLAKE2B_G(m,v[ 1],v[ 5],v[ 9],v[13]); + BLAKE2B_G(m,v[ 2],v[ 6],v[10],v[14]); + BLAKE2B_G(m,v[ 3],v[ 7],v[11],v[15]); + BLAKE2B_G(m,v[ 0],v[ 5],v[10],v[15]); + BLAKE2B_G(m,v[ 1],v[ 6],v[11],v[12]); + BLAKE2B_G(m,v[ 2],v[ 7],v[ 8],v[13]); + BLAKE2B_G(m,v[ 3],v[ 4],v[ 9],v[14]); +} + +template +inline void BLAKE2S_G(const word32 m[16], word32& a, word32& b, word32& c, word32& d) +{ + a = a + b + m[BLAKE2S_SIGMA[R][2*N+0]]; + d = rotrConstant<16>(d ^ a); + c = c + d; + b = rotrConstant<12>(b ^ c); + a = a + b + m[BLAKE2S_SIGMA[R][2*N+1]]; + d = rotrConstant<8>(d ^ a); + c = c + d; + b = rotrConstant<7>(b ^ c); +} + +template +inline void BLAKE2S_ROUND(const word32 m[16], word32 v[]) +{ + BLAKE2S_G(m,v[ 0],v[ 4],v[ 8],v[12]); + BLAKE2S_G(m,v[ 1],v[ 5],v[ 9],v[13]); + BLAKE2S_G(m,v[ 2],v[ 6],v[10],v[14]); + BLAKE2S_G(m,v[ 3],v[ 7],v[11],v[15]); + BLAKE2S_G(m,v[ 0],v[ 5],v[10],v[15]); + BLAKE2S_G(m,v[ 1],v[ 6],v[11],v[12]); + BLAKE2S_G(m,v[ 2],v[ 7],v[ 8],v[13]); + BLAKE2S_G(m,v[ 3],v[ 4],v[ 9],v[14]); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void BLAKE2_Compress32_CXX(const byte* input, BLAKE2s_State& state); +void BLAKE2_Compress64_CXX(const byte* input, BLAKE2b_State& state); + +#if CRYPTOPP_SSE41_AVAILABLE +extern void BLAKE2_Compress32_SSE4(const byte* input, BLAKE2s_State& state); +extern void BLAKE2_Compress64_SSE4(const byte* input, BLAKE2b_State& state); +#endif + +#if CRYPTOPP_ARM_NEON_AVAILABLE +extern void BLAKE2_Compress32_NEON(const byte* input, BLAKE2s_State& state); +extern void BLAKE2_Compress64_NEON(const byte* input, BLAKE2b_State& state); +#endif + +#if CRYPTOPP_ALTIVEC_AVAILABLE +extern void BLAKE2_Compress32_ALTIVEC(const byte* input, BLAKE2s_State& state); +#endif + +#if CRYPTOPP_POWER8_AVAILABLE +extern void BLAKE2_Compress64_POWER8(const byte* input, BLAKE2b_State& state); +#endif + +unsigned int BLAKE2b::OptimalDataAlignment() const +{ +#if defined(CRYPTOPP_SSE41_AVAILABLE) + if (HasSSE41()) + return 16; // load __m128i + else +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return 8; // load uint64x2_t + else +#endif +#if (CRYPTOPP_POWER8_AVAILABLE) + if (HasPower8()) + return 16; // load vector long long + else +#endif + return GetAlignmentOf(); +} + +std::string BLAKE2b::AlgorithmProvider() const +{ +#if defined(CRYPTOPP_SSE41_AVAILABLE) + if (HasSSE41()) + return "SSE4.1"; + else +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return "NEON"; + else +#endif +#if (CRYPTOPP_POWER8_AVAILABLE) + if (HasPower8()) + return "Power8"; + else +#endif + return "C++"; +} + +unsigned int BLAKE2s::OptimalDataAlignment() const +{ +#if defined(CRYPTOPP_SSE41_AVAILABLE) + if (HasSSE41()) + return 16; // load __m128i + else +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return 4; // load uint32x4_t + else +#endif +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return 16; // load vector unsigned int + else +#endif + return GetAlignmentOf(); +} + +std::string BLAKE2s::AlgorithmProvider() const +{ +#if defined(CRYPTOPP_SSE41_AVAILABLE) + if (HasSSE41()) + return "SSE4.1"; + else +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return "NEON"; + else +#endif +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return "Altivec"; + else +#endif + return "C++"; +} + +void BLAKE2s_State::Reset() +{ + std::memset(m_hft, 0x00, m_hft.SizeInBytes()); + m_len = 0; +} + +void BLAKE2b_State::Reset() +{ + std::memset(m_hft, 0x00, m_hft.SizeInBytes()); + m_len = 0; +} + +BLAKE2s_ParameterBlock::BLAKE2s_ParameterBlock(size_t digestLen, size_t keyLen, + const byte* saltStr, size_t saltLen, + const byte* personalizationStr, size_t personalizationLen) +{ + Reset(digestLen, keyLen); + + if (saltStr && saltLen) + memcpy_s(salt(), SALTSIZE, saltStr, saltLen); + + if (personalizationStr && personalizationLen) + memcpy_s(personalization(), PERSONALIZATIONSIZE, personalizationStr, personalizationLen); +} + +BLAKE2b_ParameterBlock::BLAKE2b_ParameterBlock(size_t digestLen, size_t keyLen, + const byte* saltStr, size_t saltLen, + const byte* personalizationStr, size_t personalizationLen) +{ + Reset(digestLen, keyLen); + + if (saltStr && saltLen) + memcpy_s(salt(), SALTSIZE, saltStr, saltLen); + + if (personalizationStr && personalizationLen) + memcpy_s(personalization(), PERSONALIZATIONSIZE, personalizationStr, personalizationLen); +} + +void BLAKE2s_ParameterBlock::Reset(size_t digestLen, size_t keyLen) +{ + std::memset(m_data, 0x00, m_data.size()); + m_data[DigestOff] = static_cast(digestLen); + m_data[KeyOff] = static_cast(keyLen); + m_data[FanoutOff] = m_data[DepthOff] = 1; +} + +void BLAKE2b_ParameterBlock::Reset(size_t digestLen, size_t keyLen) +{ + std::memset(m_data, 0x00, m_data.size()); + m_data[DigestOff] = static_cast(digestLen); + m_data[KeyOff] = static_cast(keyLen); + m_data[FanoutOff] = m_data[DepthOff] = 1; +} + +BLAKE2s::BLAKE2s(bool treeMode, unsigned int digestSize) + : m_digestSize(digestSize), m_keyLength(0), m_treeMode(treeMode) +{ + CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE); + + UncheckedSetKey(NULLPTR, 0, MakeParameters + (Name::DigestSize(), (int)digestSize) + (Name::TreeMode(), treeMode)); +} + +BLAKE2b::BLAKE2b(bool treeMode, unsigned int digestSize) + : m_digestSize(digestSize), m_keyLength(0), m_treeMode(treeMode) +{ + CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE); + + UncheckedSetKey(NULLPTR, 0, MakeParameters + (Name::DigestSize(), (int)digestSize) + (Name::TreeMode(), treeMode)); +} + +BLAKE2s::BLAKE2s(unsigned int digestSize) + : m_digestSize(digestSize), m_keyLength(0), m_treeMode(false) +{ + CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE); + + UncheckedSetKey(NULLPTR, 0, MakeParameters + (Name::DigestSize(), (int)digestSize) + (Name::TreeMode(), false)); +} + +BLAKE2b::BLAKE2b(unsigned int digestSize) + : m_digestSize(digestSize), m_keyLength(0), m_treeMode(false) +{ + CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE); + + UncheckedSetKey(NULLPTR, 0, MakeParameters + (Name::DigestSize(), (int)digestSize) + (Name::TreeMode(), false)); +} + +BLAKE2s::BLAKE2s(const byte *key, size_t keyLength, const byte* salt, size_t saltLength, + const byte* personalization, size_t personalizationLength, bool treeMode, unsigned int digestSize) + : m_digestSize(digestSize), m_keyLength(static_cast(keyLength)), m_treeMode(treeMode) +{ + CRYPTOPP_ASSERT(keyLength <= MAX_KEYLENGTH); + CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE); + CRYPTOPP_ASSERT(saltLength <= SALTSIZE); + CRYPTOPP_ASSERT(personalizationLength <= PERSONALIZATIONSIZE); + + UncheckedSetKey(key, static_cast(keyLength), MakeParameters + (Name::DigestSize(),(int)digestSize) + (Name::TreeMode(),treeMode) + (Name::Salt(), ConstByteArrayParameter(salt, saltLength)) + (Name::Personalization(), ConstByteArrayParameter(personalization, personalizationLength))); +} + +BLAKE2b::BLAKE2b(const byte *key, size_t keyLength, const byte* salt, size_t saltLength, + const byte* personalization, size_t personalizationLength, bool treeMode, unsigned int digestSize) + : m_digestSize(digestSize), m_keyLength(static_cast(keyLength)), m_treeMode(treeMode) +{ + CRYPTOPP_ASSERT(keyLength <= MAX_KEYLENGTH); + CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE); + CRYPTOPP_ASSERT(saltLength <= SALTSIZE); + CRYPTOPP_ASSERT(personalizationLength <= PERSONALIZATIONSIZE); + + UncheckedSetKey(key, static_cast(keyLength), MakeParameters + (Name::DigestSize(),(int)digestSize) + (Name::TreeMode(),treeMode) + (Name::Salt(), ConstByteArrayParameter(salt, saltLength)) + (Name::Personalization(), ConstByteArrayParameter(personalization, personalizationLength))); +} + +void BLAKE2s::UncheckedSetKey(const byte *key, unsigned int length, const CryptoPP::NameValuePairs& params) +{ + if (key && length) + { + m_key.New(BLOCKSIZE); + std::memcpy(m_key, key, length); + std::memset(m_key + length, 0x00, BLOCKSIZE - length); + m_keyLength = length; + } + else + { + m_key.resize(0); + m_keyLength = 0; + } + + m_digestSize = static_cast(params.GetIntValueWithDefault( + Name::DigestSize(), static_cast(m_digestSize))); + + m_state.Reset(); + m_block.Reset(m_digestSize, m_keyLength); + (void)params.GetValue(Name::TreeMode(), m_treeMode); + + ConstByteArrayParameter t; + if (params.GetValue(Name::Salt(), t) && t.begin() && t.size()) + memcpy_s(m_block.salt(), SALTSIZE, t.begin(), t.size()); + + if (params.GetValue(Name::Personalization(), t) && t.begin() && t.size()) + memcpy_s(m_block.personalization(), PERSONALIZATIONSIZE, t.begin(), t.size()); + + Restart(); +} + +void BLAKE2b::UncheckedSetKey(const byte *key, unsigned int length, const CryptoPP::NameValuePairs& params) +{ + if (key && length) + { + m_key.New(BLOCKSIZE); + std::memcpy(m_key, key, length); + std::memset(m_key + length, 0x00, BLOCKSIZE - length); + m_keyLength = length; + } + else + { + m_key.resize(0); + m_keyLength = 0; + } + + m_digestSize = static_cast(params.GetIntValueWithDefault( + Name::DigestSize(), static_cast(m_digestSize))); + + m_state.Reset(); + m_block.Reset(m_digestSize, m_keyLength); + (void)params.GetValue(Name::TreeMode(), m_treeMode); + + ConstByteArrayParameter t; + if (params.GetValue(Name::Salt(), t) && t.begin() && t.size()) + memcpy_s(m_block.salt(), SALTSIZE, t.begin(), t.size()); + + if (params.GetValue(Name::Personalization(), t) && t.begin() && t.size()) + memcpy_s(m_block.personalization(), PERSONALIZATIONSIZE, t.begin(), t.size()); + + Restart(); +} + +void BLAKE2s::Restart() +{ + static const word32 zero[2] = {0,0}; + Restart(m_block, zero); +} + +void BLAKE2b::Restart() +{ + static const word64 zero[2] = {0,0}; + Restart(m_block, zero); +} + +void BLAKE2s::Restart(const BLAKE2s_ParameterBlock& block, const word32 counter[2]) +{ + // We take a counter as a parameter to allow customized state. + m_state.Reset(); + if (counter != NULLPTR) + { + word32* t = m_state.t(); + t[0] = counter[0]; + t[1] = counter[1]; + } + + // We take a parameter block as a parameter to allow customized state. + // Avoid the copy of the parameter block when we are passing our own block. + if (block.data() != m_block.data()) { + std::memcpy(m_block.data(), block.data(), m_block.size()); + } + + m_block.m_data[BLAKE2s_ParameterBlock::DigestOff] = (byte)m_digestSize; + m_block.m_data[BLAKE2s_ParameterBlock::KeyOff] = (byte)m_keyLength; + + const word32* iv = BLAKE2S_IV; + PutBlock put(m_block.data(), m_state.h()); + put(iv[0])(iv[1])(iv[2])(iv[3])(iv[4])(iv[5])(iv[6])(iv[7]); + + // When BLAKE2 is keyed, the input stream is simply {key || 0 || message}. + // The key is padded to a full Blocksize with 0. Key it during Restart to + // avoid FirstPut and friends. Key size == 0 means no key. + if (m_keyLength) + Update(m_key, BLOCKSIZE); +} + +void BLAKE2b::Restart(const BLAKE2b_ParameterBlock& block, const word64 counter[2]) +{ + // We take a counter as a parameter to allow customized state. + m_state.Reset(); + if (counter != NULLPTR) + { + word64* t = m_state.t(); + t[0] = counter[0]; + t[1] = counter[1]; + } + + // We take a parameter block as a parameter to allow customized state. + // Avoid the copy of the parameter block when we are passing our own block. + if (block.data() != m_block.data()) { + std::memcpy(m_block.data(), block.data(), m_block.size()); + } + + m_block.m_data[BLAKE2b_ParameterBlock::DigestOff] = (byte)m_digestSize; + m_block.m_data[BLAKE2b_ParameterBlock::KeyOff] = (byte)m_keyLength; + + const word64* iv = BLAKE2B_IV; + PutBlock put(m_block.data(), m_state.h()); + put(iv[0])(iv[1])(iv[2])(iv[3])(iv[4])(iv[5])(iv[6])(iv[7]); + + // When BLAKE2 is keyed, the input stream is simply {key || 0 || message}. + // The key is padded to a full Blocksize with 0. Key it during Restart to + // avoid FirstPut and friends. Key size == 0 means no key. + if (m_keyLength) + Update(m_key, BLOCKSIZE); +} + +void BLAKE2s::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT(input != NULLPTR || length == 0); + + if (length > BLOCKSIZE - m_state.m_len) + { + if (m_state.m_len != 0) + { + // Complete current block + const size_t fill = BLOCKSIZE - m_state.m_len; + std::memcpy(m_state.m_buf+m_state.m_len, input, fill); + + IncrementCounter(BLOCKSIZE); + Compress(m_state.m_buf); + m_state.m_len = 0; + + length -= fill, input += fill; + } + + // Compress in-place to avoid copies + while (length > BLOCKSIZE) + { + IncrementCounter(BLOCKSIZE); + Compress(input); + length -= BLOCKSIZE, input += BLOCKSIZE; + } + } + + // Copy tail bytes + if (length) + { + CRYPTOPP_ASSERT(length <= BLOCKSIZE - m_state.m_len); + std::memcpy(m_state.m_buf+m_state.m_len, input, length); + m_state.m_len += static_cast(length); + } +} + +void BLAKE2b::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT(input != NULLPTR || length == 0); + + if (length > BLOCKSIZE - m_state.m_len) + { + if (m_state.m_len != 0) + { + // Complete current block + const size_t fill = BLOCKSIZE - m_state.m_len; + std::memcpy(m_state.m_buf+m_state.m_len, input, fill); + + IncrementCounter(BLOCKSIZE); + Compress(m_state.m_buf); + m_state.m_len = 0; + + length -= fill, input += fill; + } + + // Compress in-place to avoid copies + while (length > BLOCKSIZE) + { + CRYPTOPP_ASSERT(m_state.m_len == 0); + IncrementCounter(BLOCKSIZE); + Compress(input); + length -= BLOCKSIZE, input += BLOCKSIZE; + } + } + + // Copy tail bytes + if (length) + { + CRYPTOPP_ASSERT(length <= BLOCKSIZE - m_state.m_len); + std::memcpy(m_state.m_buf + m_state.m_len, input, length); + m_state.m_len += static_cast(length); + } +} + +void BLAKE2s::TruncatedFinal(byte *hash, size_t size) +{ + CRYPTOPP_ASSERT(hash != NULLPTR); + this->ThrowIfInvalidTruncatedSize(size); + word32* f = m_state.f(); + + // Set last block unconditionally + f[0] = ~static_cast(0); + + // Set last node if tree mode + if (m_treeMode) + f[1] = ~static_cast(0); + + // Increment counter for tail bytes only + IncrementCounter(m_state.m_len); + + std::memset(m_state.m_buf + m_state.m_len, 0x00, BLOCKSIZE - m_state.m_len); + Compress(m_state.m_buf); + + // Copy to caller buffer + std::memcpy(hash, m_state.h(), size); + + Restart(); +} + +void BLAKE2b::TruncatedFinal(byte *hash, size_t size) +{ + CRYPTOPP_ASSERT(hash != NULLPTR); + this->ThrowIfInvalidTruncatedSize(size); + word64* f = m_state.f(); + + // Set last block unconditionally + f[0] = ~static_cast(0); + + // Set last node if tree mode + if (m_treeMode) + f[1] = ~static_cast(0); + + // Increment counter for tail bytes only + IncrementCounter(m_state.m_len); + + std::memset(m_state.m_buf + m_state.m_len, 0x00, BLOCKSIZE - m_state.m_len); + Compress(m_state.m_buf); + + // Copy to caller buffer + std::memcpy(hash, m_state.h(), size); + + Restart(); +} + +void BLAKE2s::IncrementCounter(size_t count) +{ + word32* t = m_state.t(); + t[0] += static_cast(count); + t[1] += !!(t[0] < count); +} + +void BLAKE2b::IncrementCounter(size_t count) +{ + word64* t = m_state.t(); + t[0] += static_cast(count); + t[1] += !!(t[0] < count); +} + +void BLAKE2s::Compress(const byte *input) +{ +#if CRYPTOPP_SSE41_AVAILABLE + if(HasSSE41()) + { + return BLAKE2_Compress32_SSE4(input, m_state); + } +#endif +#if CRYPTOPP_ARM_NEON_AVAILABLE + if(HasNEON()) + { + return BLAKE2_Compress32_NEON(input, m_state); + } +#endif +#if CRYPTOPP_ALTIVEC_AVAILABLE + if(HasAltivec()) + { + return BLAKE2_Compress32_ALTIVEC(input, m_state); + } +#endif + return BLAKE2_Compress32_CXX(input, m_state); +} + +void BLAKE2b::Compress(const byte *input) +{ +#if CRYPTOPP_SSE41_AVAILABLE + if(HasSSE41()) + { + return BLAKE2_Compress64_SSE4(input, m_state); + } +#endif +#if CRYPTOPP_ARM_NEON_AVAILABLE + if(HasNEON()) + { + return BLAKE2_Compress64_NEON(input, m_state); + } +#endif +#if CRYPTOPP_POWER8_AVAILABLE + if(HasPower8()) + { + return BLAKE2_Compress64_POWER8(input, m_state); + } +#endif + return BLAKE2_Compress64_CXX(input, m_state); +} + +void BLAKE2_Compress64_CXX(const byte* input, BLAKE2b_State& state) +{ + word64 m[16], v[16]; + + GetBlock get1(input); + get1(m[0])(m[1])(m[2])(m[3])(m[4])(m[5])(m[6])(m[7])(m[8])(m[9])(m[10])(m[11])(m[12])(m[13])(m[14])(m[15]); + + GetBlock get2(state.h()); + get2(v[0])(v[1])(v[2])(v[3])(v[4])(v[5])(v[6])(v[7]); + + const word64* iv = BLAKE2B_IV; + const word64* tf = state.t(); + v[ 8] = iv[0]; + v[ 9] = iv[1]; + v[10] = iv[2]; + v[11] = iv[3]; + v[12] = tf[0] ^ iv[4]; + v[13] = tf[1] ^ iv[5]; + v[14] = tf[2] ^ iv[6]; + v[15] = tf[3] ^ iv[7]; + + BLAKE2B_ROUND<0>(m, v); + BLAKE2B_ROUND<1>(m, v); + BLAKE2B_ROUND<2>(m, v); + BLAKE2B_ROUND<3>(m, v); + BLAKE2B_ROUND<4>(m, v); + BLAKE2B_ROUND<5>(m, v); + BLAKE2B_ROUND<6>(m, v); + BLAKE2B_ROUND<7>(m, v); + BLAKE2B_ROUND<8>(m, v); + BLAKE2B_ROUND<9>(m, v); + BLAKE2B_ROUND<10>(m, v); + BLAKE2B_ROUND<11>(m, v); + + word64* h = state.h(); + for (unsigned int i = 0; i < 8; ++i) + h[i] = h[i] ^ ConditionalByteReverse(LITTLE_ENDIAN_ORDER, v[i] ^ v[i + 8]); +} + +void BLAKE2_Compress32_CXX(const byte* input, BLAKE2s_State& state) +{ + word32 m[16], v[16]; + + GetBlock get1(input); + get1(m[0])(m[1])(m[2])(m[3])(m[4])(m[5])(m[6])(m[7])(m[8])(m[9])(m[10])(m[11])(m[12])(m[13])(m[14])(m[15]); + + GetBlock get2(state.h()); + get2(v[0])(v[1])(v[2])(v[3])(v[4])(v[5])(v[6])(v[7]); + + const word32* iv = BLAKE2S_IV; + const word32* tf = state.t(); + v[ 8] = iv[0]; + v[ 9] = iv[1]; + v[10] = iv[2]; + v[11] = iv[3]; + v[12] = tf[0] ^ iv[4]; + v[13] = tf[1] ^ iv[5]; + v[14] = tf[2] ^ iv[6]; + v[15] = tf[3] ^ iv[7]; + + BLAKE2S_ROUND<0>(m, v); + BLAKE2S_ROUND<1>(m, v); + BLAKE2S_ROUND<2>(m, v); + BLAKE2S_ROUND<3>(m, v); + BLAKE2S_ROUND<4>(m, v); + BLAKE2S_ROUND<5>(m, v); + BLAKE2S_ROUND<6>(m, v); + BLAKE2S_ROUND<7>(m, v); + BLAKE2S_ROUND<8>(m, v); + BLAKE2S_ROUND<9>(m, v); + + word32* h = state.h(); + for (unsigned int i = 0; i < 8; ++i) + h[i] = h[i] ^ ConditionalByteReverse(LITTLE_ENDIAN_ORDER, v[i] ^ v[i + 8]); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/blake2.h b/external/ours/library/crypto/src/shared/original/blake2.h new file mode 100755 index 000000000..896421a89 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/blake2b_simd.cpp b/external/ours/library/crypto/src/shared/original/blake2b_simd.cpp new file mode 100755 index 000000000..f408b8fa7 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/blake2b_simd.cpp @@ -0,0 +1,1276 @@ +// blake2_simd.cpp - written and placed in the public domain by +// Samuel Neves, Jeffrey Walton, Uri Blumenthal +// and Marcel Raad. +// +// This source file uses intrinsics to gain access to ARMv7a/ARMv8a +// NEON, Power8 and SSE4.1 instructions. A separate source file is +// needed because additional CXXFLAGS are required to enable the +// appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" +#include "misc.h" +#include "blake2.h" + +// Uncomment for benchmarking C++ against SSE2 or NEON. +// Do so in both blake2.cpp and blake2_simd.cpp. +// #undef CRYPTOPP_SSE41_AVAILABLE +// #undef CRYPTOPP_ARM_NEON_AVAILABLE +// #undef CRYPTOPP_ALTIVEC_AVAILABLE + +// Disable NEON/ASIMD for Cortex-A53 and A57. The shifts are too slow and C/C++ is about +// 3 cpb faster than NEON/ASIMD. Also see http://github.com/weidai11/cryptopp/issues/367. +#if (defined(__aarch32__) || defined(__aarch64__)) && defined(CRYPTOPP_SLOW_ARMV8_SHIFT) +# undef CRYPTOPP_ARM_NEON_AVAILABLE +#endif + +// BLAKE2s bug on AIX 7.1 (POWER7) with XLC 12.01 +// https://github.com/weidai11/cryptopp/issues/743 +#if defined(__xlC__) && (__xlC__ < 0x0d01) +# define CRYPTOPP_DISABLE_ALTIVEC 1 +# undef CRYPTOPP_POWER8_AVAILABLE +# undef CRYPTOPP_ALTIVEC_AVAILABLE +#endif + +#if defined(__XOP__) +# include +# if defined(__GNUC__) +# include +# endif +#endif + +#if (CRYPTOPP_SSE41_AVAILABLE) +# include +# include +# include +#endif + +#if (CRYPTOPP_ARM_NEON_HEADER) +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +#if (CRYPTOPP_POWER8_AVAILABLE) +# include "ppc_simd.h" +#endif + +#if defined(CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE) +/* Ignore "warning: vec_lvsl is deprecated..." */ +# pragma GCC diagnostic ignored "-Wdeprecated" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char BLAKE2B_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +// Exported by blake2.cpp +extern const word32 BLAKE2S_IV[8]; +extern const word64 BLAKE2B_IV[8]; + +#if CRYPTOPP_SSE41_AVAILABLE + +#define LOADU(p) _mm_loadu_si128((const __m128i *)(const void*)(p)) +#define STOREU(p,r) _mm_storeu_si128((__m128i *)(void*)(p), r) +#define TOF(reg) _mm_castsi128_ps((reg)) +#define TOI(reg) _mm_castps_si128((reg)) + +void BLAKE2_Compress64_SSE4(const byte* input, BLAKE2b_State& state) +{ + #define BLAKE2B_LOAD_MSG_0_1(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m0, m1); \ + b1 = _mm_unpacklo_epi64(m2, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_0_2(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m0, m1); \ + b1 = _mm_unpackhi_epi64(m2, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_0_3(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m4, m5); \ + b1 = _mm_unpacklo_epi64(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_0_4(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m4, m5); \ + b1 = _mm_unpackhi_epi64(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_1_1(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m7, m2); \ + b1 = _mm_unpackhi_epi64(m4, m6); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_1_2(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m5, m4); \ + b1 = _mm_alignr_epi8(m3, m7, 8); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_1_3(b0, b1) \ + do { \ + b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \ + b1 = _mm_unpackhi_epi64(m5, m2); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_1_4(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m6, m1); \ + b1 = _mm_unpackhi_epi64(m3, m1); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_2_1(b0, b1) \ + do { \ + b0 = _mm_alignr_epi8(m6, m5, 8); \ + b1 = _mm_unpackhi_epi64(m2, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_2_2(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m4, m0); \ + b1 = _mm_blend_epi16(m1, m6, 0xF0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_2_3(b0, b1) \ + do { \ + b0 = _mm_blend_epi16(m5, m1, 0xF0); \ + b1 = _mm_unpackhi_epi64(m3, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_2_4(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m7, m3); \ + b1 = _mm_alignr_epi8(m2, m0, 8); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_3_1(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m3, m1); \ + b1 = _mm_unpackhi_epi64(m6, m5); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_3_2(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m4, m0); \ + b1 = _mm_unpacklo_epi64(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_3_3(b0, b1) \ + do { \ + b0 = _mm_blend_epi16(m1, m2, 0xF0); \ + b1 = _mm_blend_epi16(m2, m7, 0xF0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_3_4(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m3, m5); \ + b1 = _mm_unpacklo_epi64(m0, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_4_1(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m4, m2); \ + b1 = _mm_unpacklo_epi64(m1, m5); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_4_2(b0, b1) \ + do { \ + b0 = _mm_blend_epi16(m0, m3, 0xF0); \ + b1 = _mm_blend_epi16(m2, m7, 0xF0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_4_3(b0, b1) \ + do { \ + b0 = _mm_blend_epi16(m7, m5, 0xF0); \ + b1 = _mm_blend_epi16(m3, m1, 0xF0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_4_4(b0, b1) \ + do { \ + b0 = _mm_alignr_epi8(m6, m0, 8); \ + b1 = _mm_blend_epi16(m4, m6, 0xF0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_5_1(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m1, m3); \ + b1 = _mm_unpacklo_epi64(m0, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_5_2(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m6, m5); \ + b1 = _mm_unpackhi_epi64(m5, m1); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_5_3(b0, b1) \ + do { \ + b0 = _mm_blend_epi16(m2, m3, 0xF0); \ + b1 = _mm_unpackhi_epi64(m7, m0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_5_4(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m6, m2); \ + b1 = _mm_blend_epi16(m7, m4, 0xF0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_6_1(b0, b1) \ + do { \ + b0 = _mm_blend_epi16(m6, m0, 0xF0); \ + b1 = _mm_unpacklo_epi64(m7, m2); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_6_2(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m2, m7); \ + b1 = _mm_alignr_epi8(m5, m6, 8); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_6_3(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m0, m3); \ + b1 = _mm_shuffle_epi32(m4, _MM_SHUFFLE(1,0,3,2)); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_6_4(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m3, m1); \ + b1 = _mm_blend_epi16(m1, m5, 0xF0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_7_1(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m6, m3); \ + b1 = _mm_blend_epi16(m6, m1, 0xF0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_7_2(b0, b1) \ + do { \ + b0 = _mm_alignr_epi8(m7, m5, 8); \ + b1 = _mm_unpackhi_epi64(m0, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_7_3(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m2, m7); \ + b1 = _mm_unpacklo_epi64(m4, m1); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_7_4(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m0, m2); \ + b1 = _mm_unpacklo_epi64(m3, m5); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_8_1(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m3, m7); \ + b1 = _mm_alignr_epi8(m0, m5, 8); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_8_2(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m7, m4); \ + b1 = _mm_alignr_epi8(m4, m1, 8); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_8_3(b0, b1) \ + do { \ + b0 = m6; \ + b1 = _mm_alignr_epi8(m5, m0, 8); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_8_4(b0, b1) \ + do { \ + b0 = _mm_blend_epi16(m1, m3, 0xF0); \ + b1 = m2; \ + } while(0) + + #define BLAKE2B_LOAD_MSG_9_1(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m5, m4); \ + b1 = _mm_unpackhi_epi64(m3, m0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_9_2(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m1, m2); \ + b1 = _mm_blend_epi16(m3, m2, 0xF0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_9_3(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m7, m4); \ + b1 = _mm_unpackhi_epi64(m1, m6); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_9_4(b0, b1) \ + do { \ + b0 = _mm_alignr_epi8(m7, m5, 8); \ + b1 = _mm_unpacklo_epi64(m6, m0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_10_1(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m0, m1); \ + b1 = _mm_unpacklo_epi64(m2, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_10_2(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m0, m1); \ + b1 = _mm_unpackhi_epi64(m2, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_10_3(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m4, m5); \ + b1 = _mm_unpacklo_epi64(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_10_4(b0, b1) \ + do { \ + b0 = _mm_unpackhi_epi64(m4, m5); \ + b1 = _mm_unpackhi_epi64(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_11_1(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m7, m2); \ + b1 = _mm_unpackhi_epi64(m4, m6); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_11_2(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m5, m4); \ + b1 = _mm_alignr_epi8(m3, m7, 8); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_11_3(b0, b1) \ + do { \ + b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \ + b1 = _mm_unpackhi_epi64(m5, m2); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_11_4(b0, b1) \ + do { \ + b0 = _mm_unpacklo_epi64(m6, m1); \ + b1 = _mm_unpackhi_epi64(m3, m1); \ + } while(0) + +#ifdef __XOP__ +# define MM_ROTI_EPI64(r, c) \ + _mm_roti_epi64(r, c) +#else +# define MM_ROTI_EPI64(x, c) \ + (-(c) == 32) ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2,3,0,1)) \ + : (-(c) == 24) ? _mm_shuffle_epi8((x), r24) \ + : (-(c) == 16) ? _mm_shuffle_epi8((x), r16) \ + : (-(c) == 63) ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_add_epi64((x), (x))) \ + : _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_slli_epi64((x), 64-(-(c)))) +#endif + +#define BLAKE2B_G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ + row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \ + row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \ + \ + row4l = _mm_xor_si128(row4l, row1l); \ + row4h = _mm_xor_si128(row4h, row1h); \ + \ + row4l = MM_ROTI_EPI64(row4l, -32); \ + row4h = MM_ROTI_EPI64(row4h, -32); \ + \ + row3l = _mm_add_epi64(row3l, row4l); \ + row3h = _mm_add_epi64(row3h, row4h); \ + \ + row2l = _mm_xor_si128(row2l, row3l); \ + row2h = _mm_xor_si128(row2h, row3h); \ + \ + row2l = MM_ROTI_EPI64(row2l, -24); \ + row2h = MM_ROTI_EPI64(row2h, -24); + +#define BLAKE2B_G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ + row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \ + row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \ + \ + row4l = _mm_xor_si128(row4l, row1l); \ + row4h = _mm_xor_si128(row4h, row1h); \ + \ + row4l = MM_ROTI_EPI64(row4l, -16); \ + row4h = MM_ROTI_EPI64(row4h, -16); \ + \ + row3l = _mm_add_epi64(row3l, row4l); \ + row3h = _mm_add_epi64(row3h, row4h); \ + \ + row2l = _mm_xor_si128(row2l, row3l); \ + row2h = _mm_xor_si128(row2h, row3h); \ + \ + row2l = MM_ROTI_EPI64(row2l, -63); \ + row2h = MM_ROTI_EPI64(row2h, -63); \ + +#define BLAKE2B_DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ + t0 = row4l;\ + t1 = row2l;\ + row4l = row3l;\ + row3l = row3h;\ + row3h = row4l;\ + row4l = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t0, t0)); \ + row4h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row4h, row4h)); \ + row2l = _mm_unpackhi_epi64(row2l, _mm_unpacklo_epi64(row2h, row2h)); \ + row2h = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(t1, t1)) + +#define BLAKE2B_UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ + t0 = row3l;\ + row3l = row3h;\ + row3h = t0;\ + t0 = row2l;\ + t1 = row4l;\ + row2l = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(row2l, row2l)); \ + row2h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row2h, row2h)); \ + row4l = _mm_unpackhi_epi64(row4l, _mm_unpacklo_epi64(row4h, row4h)); \ + row4h = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t1, t1)) + +#define BLAKE2B_ROUND(r) \ + BLAKE2B_LOAD_MSG_ ##r ##_1(b0, b1); \ + BLAKE2B_G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_LOAD_MSG_ ##r ##_2(b0, b1); \ + BLAKE2B_G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ + BLAKE2B_LOAD_MSG_ ##r ##_3(b0, b1); \ + BLAKE2B_G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_LOAD_MSG_ ##r ##_4(b0, b1); \ + BLAKE2B_G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); + + __m128i row1l, row1h; + __m128i row2l, row2h; + __m128i row3l, row3h; + __m128i row4l, row4h; + __m128i b0, b1; + __m128i t0, t1; + + const __m128i r16 = _mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9); + const __m128i r24 = _mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10); + + const __m128i m0 = LOADU(input + 00); + const __m128i m1 = LOADU(input + 16); + const __m128i m2 = LOADU(input + 32); + const __m128i m3 = LOADU(input + 48); + const __m128i m4 = LOADU(input + 64); + const __m128i m5 = LOADU(input + 80); + const __m128i m6 = LOADU(input + 96); + const __m128i m7 = LOADU(input + 112); + + row1l = LOADU(state.h()+0); + row1h = LOADU(state.h()+2); + row2l = LOADU(state.h()+4); + row2h = LOADU(state.h()+6); + row3l = LOADU(BLAKE2B_IV+0); + row3h = LOADU(BLAKE2B_IV+2); + row4l = _mm_xor_si128(LOADU(BLAKE2B_IV+4), LOADU(state.t()+0)); + row4h = _mm_xor_si128(LOADU(BLAKE2B_IV+6), LOADU(state.f()+0)); + + BLAKE2B_ROUND(0); + BLAKE2B_ROUND(1); + BLAKE2B_ROUND(2); + BLAKE2B_ROUND(3); + BLAKE2B_ROUND(4); + BLAKE2B_ROUND(5); + BLAKE2B_ROUND(6); + BLAKE2B_ROUND(7); + BLAKE2B_ROUND(8); + BLAKE2B_ROUND(9); + BLAKE2B_ROUND(10); + BLAKE2B_ROUND(11); + + row1l = _mm_xor_si128(row3l, row1l); + row1h = _mm_xor_si128(row3h, row1h); + STOREU(state.h()+0, _mm_xor_si128(LOADU(state.h()+0), row1l)); + STOREU(state.h()+2, _mm_xor_si128(LOADU(state.h()+2), row1h)); + row2l = _mm_xor_si128(row4l, row2l); + row2h = _mm_xor_si128(row4h, row2h); + STOREU(state.h()+4, _mm_xor_si128(LOADU(state.h()+4), row2l)); + STOREU(state.h()+6, _mm_xor_si128(LOADU(state.h()+6), row2h)); +} +#endif // CRYPTOPP_SSE41_AVAILABLE + +#if CRYPTOPP_ARM_NEON_AVAILABLE +void BLAKE2_Compress64_NEON(const byte* input, BLAKE2b_State& state) +{ + #define BLAKE2B_LOAD_MSG_0_1(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m1)); b1 = vcombine_u64(vget_low_u64(m2), vget_low_u64(m3)); } while(0) + + #define BLAKE2B_LOAD_MSG_0_2(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m0), vget_high_u64(m1)); b1 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m3)); } while(0) + + #define BLAKE2B_LOAD_MSG_0_3(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m5)); b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m7)); } while(0) + + #define BLAKE2B_LOAD_MSG_0_4(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m5)); b1 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m7)); } while(0) + + #define BLAKE2B_LOAD_MSG_1_1(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m2)); b1 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m6)); } while(0) + + #define BLAKE2B_LOAD_MSG_1_2(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m5), vget_low_u64(m4)); b1 = vextq_u64(m7, m3, 1); } while(0) + + #define BLAKE2B_LOAD_MSG_1_3(b0, b1) \ + do { b0 = vextq_u64(m0, m0, 1); b1 = vcombine_u64(vget_high_u64(m5), vget_high_u64(m2)); } while(0) + + #define BLAKE2B_LOAD_MSG_1_4(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m1)); b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); } while(0) + + #define BLAKE2B_LOAD_MSG_2_1(b0, b1) \ + do { b0 = vextq_u64(m5, m6, 1); b1 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m7)); } while(0) + + #define BLAKE2B_LOAD_MSG_2_2(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m0)); b1 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m6)); } while(0) + + #define BLAKE2B_LOAD_MSG_2_3(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m5), vget_high_u64(m1)); b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m4)); } while(0) + + #define BLAKE2B_LOAD_MSG_2_4(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m3)); b1 = vextq_u64(m0, m2, 1); } while(0) + + #define BLAKE2B_LOAD_MSG_3_1(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); b1 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m5)); } while(0) + + #define BLAKE2B_LOAD_MSG_3_2(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m0)); b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m7)); } while(0) + + #define BLAKE2B_LOAD_MSG_3_3(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m2)); b1 = vcombine_u64(vget_low_u64(m2), vget_high_u64(m7)); } while(0) + + #define BLAKE2B_LOAD_MSG_3_4(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m3), vget_low_u64(m5)); b1 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m4)); } while(0) + + #define BLAKE2B_LOAD_MSG_4_1(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m2)); b1 = vcombine_u64(vget_low_u64(m1), vget_low_u64(m5)); } while(0) + + #define BLAKE2B_LOAD_MSG_4_2(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m0), vget_high_u64(m3)); b1 = vcombine_u64(vget_low_u64(m2), vget_high_u64(m7)); } while(0) + + #define BLAKE2B_LOAD_MSG_4_3(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m7), vget_high_u64(m5)); b1 = vcombine_u64(vget_low_u64(m3), vget_high_u64(m1)); } while(0) + + #define BLAKE2B_LOAD_MSG_4_4(b0, b1) \ + do { b0 = vextq_u64(m0, m6, 1); b1 = vcombine_u64(vget_low_u64(m4), vget_high_u64(m6)); } while(0) + + #define BLAKE2B_LOAD_MSG_5_1(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m1), vget_low_u64(m3)); b1 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m4)); } while(0) + + #define BLAKE2B_LOAD_MSG_5_2(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m5)); b1 = vcombine_u64(vget_high_u64(m5), vget_high_u64(m1)); } while(0) + + #define BLAKE2B_LOAD_MSG_5_3(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m2), vget_high_u64(m3)); b1 = vcombine_u64(vget_high_u64(m7), vget_high_u64(m0)); } while(0) + + #define BLAKE2B_LOAD_MSG_5_4(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m2)); b1 = vcombine_u64(vget_low_u64(m7), vget_high_u64(m4)); } while(0) + + #define BLAKE2B_LOAD_MSG_6_1(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m6), vget_high_u64(m0)); b1 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m2)); } while(0) + + #define BLAKE2B_LOAD_MSG_6_2(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m7)); b1 = vextq_u64(m6, m5, 1); } while(0) + + #define BLAKE2B_LOAD_MSG_6_3(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m3)); b1 = vextq_u64(m4, m4, 1); } while(0) + + #define BLAKE2B_LOAD_MSG_6_4(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); b1 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m5)); } while(0) + + #define BLAKE2B_LOAD_MSG_7_1(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m3)); b1 = vcombine_u64(vget_low_u64(m6), vget_high_u64(m1)); } while(0) + + #define BLAKE2B_LOAD_MSG_7_2(b0, b1) \ + do { b0 = vextq_u64(m5, m7, 1); b1 = vcombine_u64(vget_high_u64(m0), vget_high_u64(m4)); } while(0) + + #define BLAKE2B_LOAD_MSG_7_3(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m7)); b1 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m1)); } while(0) + + #define BLAKE2B_LOAD_MSG_7_4(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m2)); b1 = vcombine_u64(vget_low_u64(m3), vget_low_u64(m5)); } while(0) + + #define BLAKE2B_LOAD_MSG_8_1(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m3), vget_low_u64(m7)); b1 = vextq_u64(m5, m0, 1); } while(0) + + #define BLAKE2B_LOAD_MSG_8_2(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m7), vget_high_u64(m4)); b1 = vextq_u64(m1, m4, 1); } while(0) + + #define BLAKE2B_LOAD_MSG_8_3(b0, b1) \ + do { b0 = m6; b1 = vextq_u64(m0, m5, 1); } while(0) + + #define BLAKE2B_LOAD_MSG_8_4(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m3)); b1 = m2; } while(0) + + #define BLAKE2B_LOAD_MSG_9_1(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m5), vget_low_u64(m4)); b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m0)); } while(0) + + #define BLAKE2B_LOAD_MSG_9_2(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m1), vget_low_u64(m2)); b1 = vcombine_u64(vget_low_u64(m3), vget_high_u64(m2)); } while(0) + + #define BLAKE2B_LOAD_MSG_9_3(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m7), vget_high_u64(m4)); b1 = vcombine_u64(vget_high_u64(m1), vget_high_u64(m6)); } while(0) + + #define BLAKE2B_LOAD_MSG_9_4(b0, b1) \ + do { b0 = vextq_u64(m5, m7, 1); b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m0)); } while(0) + + #define BLAKE2B_LOAD_MSG_10_1(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m1)); b1 = vcombine_u64(vget_low_u64(m2), vget_low_u64(m3)); } while(0) + + #define BLAKE2B_LOAD_MSG_10_2(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m0), vget_high_u64(m1)); b1 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m3)); } while(0) + + #define BLAKE2B_LOAD_MSG_10_3(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m5)); b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m7)); } while(0) + + #define BLAKE2B_LOAD_MSG_10_4(b0, b1) \ + do { b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m5)); b1 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m7)); } while(0) + + #define BLAKE2B_LOAD_MSG_11_1(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m2)); b1 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m6)); } while(0) + + #define BLAKE2B_LOAD_MSG_11_2(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m5), vget_low_u64(m4)); b1 = vextq_u64(m7, m3, 1); } while(0) + + #define BLAKE2B_LOAD_MSG_11_3(b0, b1) \ + do { b0 = vextq_u64(m0, m0, 1); b1 = vcombine_u64(vget_high_u64(m5), vget_high_u64(m2)); } while(0) + + #define BLAKE2B_LOAD_MSG_11_4(b0, b1) \ + do { b0 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m1)); b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); } while(0) + + #define vrorq_n_u64_32(x) vreinterpretq_u64_u32(vrev64q_u32(vreinterpretq_u32_u64((x)))) + + #define vrorq_n_u64_24(x) vcombine_u64( \ + vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 3)), \ + vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 3))) + + #define vrorq_n_u64_16(x) vcombine_u64( \ + vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 2)), \ + vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 2))) + + #define vrorq_n_u64_63(x) veorq_u64(vaddq_u64(x, x), vshrq_n_u64(x, 63)) + + #define BLAKE2B_G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ + do { \ + row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \ + row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \ + row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \ + row4l = vrorq_n_u64_32(row4l); row4h = vrorq_n_u64_32(row4h); \ + row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \ + row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \ + row2l = vrorq_n_u64_24(row2l); row2h = vrorq_n_u64_24(row2h); \ + } while(0) + + #define BLAKE2B_G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ + do { \ + row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \ + row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \ + row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \ + row4l = vrorq_n_u64_16(row4l); row4h = vrorq_n_u64_16(row4h); \ + row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \ + row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \ + row2l = vrorq_n_u64_63(row2l); row2h = vrorq_n_u64_63(row2h); \ + } while(0) + + #define BLAKE2B_DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ + do { \ + uint64x2_t t0 = vextq_u64(row2l, row2h, 1); \ + uint64x2_t t1 = vextq_u64(row2h, row2l, 1); \ + row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \ + t0 = vextq_u64(row4h, row4l, 1); t1 = vextq_u64(row4l, row4h, 1); \ + row4l = t0; row4h = t1; \ + } while(0) + + #define BLAKE2B_UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ + do { \ + uint64x2_t t0 = vextq_u64(row2h, row2l, 1); \ + uint64x2_t t1 = vextq_u64(row2l, row2h, 1); \ + row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \ + t0 = vextq_u64(row4l, row4h, 1); t1 = vextq_u64(row4h, row4l, 1); \ + row4l = t0; row4h = t1; \ + } while(0) + + #define BLAKE2B_ROUND(r) \ + do { \ + uint64x2_t b0, b1; \ + BLAKE2B_LOAD_MSG_ ##r ##_1(b0, b1); \ + BLAKE2B_G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_LOAD_MSG_ ##r ##_2(b0, b1); \ + BLAKE2B_G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ + BLAKE2B_LOAD_MSG_ ##r ##_3(b0, b1); \ + BLAKE2B_G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_LOAD_MSG_ ##r ##_4(b0, b1); \ + BLAKE2B_G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ + } while(0) + + const uint64x2_t m0 = vreinterpretq_u64_u8(vld1q_u8(input + 00)); + const uint64x2_t m1 = vreinterpretq_u64_u8(vld1q_u8(input + 16)); + const uint64x2_t m2 = vreinterpretq_u64_u8(vld1q_u8(input + 32)); + const uint64x2_t m3 = vreinterpretq_u64_u8(vld1q_u8(input + 48)); + const uint64x2_t m4 = vreinterpretq_u64_u8(vld1q_u8(input + 64)); + const uint64x2_t m5 = vreinterpretq_u64_u8(vld1q_u8(input + 80)); + const uint64x2_t m6 = vreinterpretq_u64_u8(vld1q_u8(input + 96)); + const uint64x2_t m7 = vreinterpretq_u64_u8(vld1q_u8(input + 112)); + + uint64x2_t row1l, row1h, row2l, row2h; + uint64x2_t row3l, row3h, row4l, row4h; + + const uint64x2_t h0 = row1l = vld1q_u64(state.h()+0); + const uint64x2_t h1 = row1h = vld1q_u64(state.h()+2); + const uint64x2_t h2 = row2l = vld1q_u64(state.h()+4); + const uint64x2_t h3 = row2h = vld1q_u64(state.h()+6); + + row3l = vld1q_u64(BLAKE2B_IV+0); + row3h = vld1q_u64(BLAKE2B_IV+2); + row4l = veorq_u64(vld1q_u64(BLAKE2B_IV+4), vld1q_u64(state.t()+0)); + row4h = veorq_u64(vld1q_u64(BLAKE2B_IV+6), vld1q_u64(state.f()+0)); + + BLAKE2B_ROUND(0); + BLAKE2B_ROUND(1); + BLAKE2B_ROUND(2); + BLAKE2B_ROUND(3); + BLAKE2B_ROUND(4); + BLAKE2B_ROUND(5); + BLAKE2B_ROUND(6); + BLAKE2B_ROUND(7); + BLAKE2B_ROUND(8); + BLAKE2B_ROUND(9); + BLAKE2B_ROUND(10); + BLAKE2B_ROUND(11); + + vst1q_u64(state.h()+0, veorq_u64(h0, veorq_u64(row1l, row3l))); + vst1q_u64(state.h()+2, veorq_u64(h1, veorq_u64(row1h, row3h))); + vst1q_u64(state.h()+4, veorq_u64(h2, veorq_u64(row2l, row4l))); + vst1q_u64(state.h()+6, veorq_u64(h3, veorq_u64(row2h, row4h))); +} +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +#if (CRYPTOPP_POWER8_AVAILABLE) + +inline uint64x2_p VecLoad64(const void* p) +{ + return (uint64x2_p)vec_xl(0, CONST_V32_CAST(p)); +} + +inline uint64x2_p VecLoad64LE(const void* p, const uint8x16_p le_mask) +{ +#if defined(CRYPTOPP_BIG_ENDIAN) + const uint32x4_p v = vec_xl(0, CONST_V32_CAST(p)); + return (uint64x2_p)VecPermute(v, v, le_mask); +#else + CRYPTOPP_UNUSED(le_mask); + return (uint64x2_p)vec_xl(0, CONST_V32_CAST(p)); +#endif +} + +inline void VecStore64(void* p, const uint64x2_p x) +{ + vec_xst((uint32x4_p)x, 0, NCONST_V32_CAST(p)); +} + +inline void VecStore64LE(void* p, const uint64x2_p x, const uint8x16_p le_mask) +{ +#if defined(CRYPTOPP_BIG_ENDIAN) + const uint64x2_p v = VecPermute(x, x, le_mask); + vec_xst((uint32x4_p)v, 0, NCONST_V32_CAST(p)); +#else + CRYPTOPP_UNUSED(le_mask); + vec_xst((uint32x4_p)x, 0, NCONST_V32_CAST(p)); +#endif +} + +#if defined(CRYPTOPP_BIG_ENDIAN) +#define vec_shl_8(a,b) (uint64x2_p)vec_sld((uint8x16_p)a,(uint8x16_p)b,8) +#else +#define vec_shl_8(a,b) (uint64x2_p)vec_sld((uint8x16_p)b,(uint8x16_p)a,8) +#endif + +#define vec_merge_hi(a, b) vec_mergeh(a,b) +#define vec_merge_hi_lo(a, b) vec_mergeh(a,(uint64x2_p)vec_sld((uint8x16_p)b,(uint8x16_p)b,8)) +#define vec_merge_lo(a, b) vec_mergel(a,b) + +void BLAKE2_Compress64_POWER8(const byte* input, BLAKE2b_State& state) +{ + #define BLAKE2B_LOAD_MSG_0_1(b0, b1) \ + do { \ + b0 = vec_merge_hi(m0, m1); \ + b1 = vec_merge_hi(m2, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_0_2(b0, b1) \ + do { \ + b0 = vec_merge_lo(m0, m1); \ + b1 = vec_merge_lo(m2, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_0_3(b0, b1) \ + do { \ + b0 = vec_merge_hi(m4, m5); \ + b1 = vec_merge_hi(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_0_4(b0, b1) \ + do { \ + b0 = vec_merge_lo(m4, m5); \ + b1 = vec_merge_lo(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_1_1(b0, b1) \ + do { \ + b0 = vec_merge_hi(m7, m2); \ + b1 = vec_merge_lo(m4, m6); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_1_2(b0, b1) \ + do { \ + b0 = vec_merge_hi(m5, m4); \ + b1 = vec_shl_8(m7, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_1_3(b0, b1) \ + do { \ + b0 = vec_shl_8(m0, m0); \ + b1 = vec_merge_lo(m5, m2); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_1_4(b0, b1) \ + do { \ + b0 = vec_merge_hi(m6, m1); \ + b1 = vec_merge_lo(m3, m1); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_2_1(b0, b1) \ + do { \ + b0 = vec_shl_8(m5, m6); \ + b1 = vec_merge_lo(m2, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_2_2(b0, b1) \ + do { \ + b0 = vec_merge_hi(m4, m0); \ + b1 = vec_merge_hi_lo(m1, m6); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_2_3(b0, b1) \ + do { \ + b0 = vec_merge_hi_lo(m5, m1); \ + b1 = vec_merge_lo(m3, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_2_4(b0, b1) \ + do { \ + b0 = vec_merge_hi(m7, m3); \ + b1 = vec_shl_8(m0, m2); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_3_1(b0, b1) \ + do { \ + b0 = vec_merge_lo(m3, m1); \ + b1 = vec_merge_lo(m6, m5); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_3_2(b0, b1) \ + do { \ + b0 = vec_merge_lo(m4, m0); \ + b1 = vec_merge_hi(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_3_3(b0, b1) \ + do { \ + b0 = vec_merge_hi_lo(m1, m2); \ + b1 = vec_merge_hi_lo(m2, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_3_4(b0, b1) \ + do { \ + b0 = vec_merge_hi(m3, m5); \ + b1 = vec_merge_hi(m0, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_4_1(b0, b1) \ + do { \ + b0 = vec_merge_lo(m4, m2); \ + b1 = vec_merge_hi(m1, m5); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_4_2(b0, b1) \ + do { \ + b0 = vec_merge_hi_lo(m0, m3); \ + b1 = vec_merge_hi_lo(m2, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_4_3(b0, b1) \ + do { \ + b0 = vec_merge_hi_lo(m7, m5); \ + b1 = vec_merge_hi_lo(m3, m1); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_4_4(b0, b1) \ + do { \ + b0 = vec_shl_8(m0, m6); \ + b1 = vec_merge_hi_lo(m4, m6); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_5_1(b0, b1) \ + do { \ + b0 = vec_merge_hi(m1, m3); \ + b1 = vec_merge_hi(m0, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_5_2(b0, b1) \ + do { \ + b0 = vec_merge_hi(m6, m5); \ + b1 = vec_merge_lo(m5, m1); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_5_3(b0, b1) \ + do { \ + b0 = vec_merge_hi_lo(m2, m3); \ + b1 = vec_merge_lo(m7, m0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_5_4(b0, b1) \ + do { \ + b0 = vec_merge_lo(m6, m2); \ + b1 = vec_merge_hi_lo(m7, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_6_1(b0, b1) \ + do { \ + b0 = vec_merge_hi_lo(m6, m0); \ + b1 = vec_merge_hi(m7, m2); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_6_2(b0, b1) \ + do { \ + b0 = vec_merge_lo(m2, m7); \ + b1 = vec_shl_8(m6, m5); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_6_3(b0, b1) \ + do { \ + b0 = vec_merge_hi(m0, m3); \ + b1 = vec_shl_8(m4, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_6_4(b0, b1) \ + do { \ + b0 = vec_merge_lo(m3, m1); \ + b1 = vec_merge_hi_lo(m1, m5); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_7_1(b0, b1) \ + do { \ + b0 = vec_merge_lo(m6, m3); \ + b1 = vec_merge_hi_lo(m6, m1); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_7_2(b0, b1) \ + do { \ + b0 = vec_shl_8(m5, m7); \ + b1 = vec_merge_lo(m0, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_7_3(b0, b1) \ + do { \ + b0 = vec_merge_lo(m2, m7); \ + b1 = vec_merge_hi(m4, m1); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_7_4(b0, b1) \ + do { \ + b0 = vec_merge_hi(m0, m2); \ + b1 = vec_merge_hi(m3, m5); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_8_1(b0, b1) \ + do { \ + b0 = vec_merge_hi(m3, m7); \ + b1 = vec_shl_8(m5, m0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_8_2(b0, b1) \ + do { \ + b0 = vec_merge_lo(m7, m4); \ + b1 = vec_shl_8(m1, m4); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_8_3(b0, b1) \ + do { \ + b0 = m6; \ + b1 = vec_shl_8(m0, m5); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_8_4(b0, b1) \ + do { \ + b0 = vec_merge_hi_lo(m1, m3); \ + b1 = m2; \ + } while(0) + + #define BLAKE2B_LOAD_MSG_9_1(b0, b1) \ + do { \ + b0 = vec_merge_hi(m5, m4); \ + b1 = vec_merge_lo(m3, m0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_9_2(b0, b1) \ + do { \ + b0 = vec_merge_hi(m1, m2); \ + b1 = vec_merge_hi_lo(m3, m2); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_9_3(b0, b1) \ + do { \ + b0 = vec_merge_lo(m7, m4); \ + b1 = vec_merge_lo(m1, m6); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_9_4(b0, b1) \ + do { \ + b0 = vec_shl_8(m5, m7); \ + b1 = vec_merge_hi(m6, m0); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_10_1(b0, b1) \ + do { \ + b0 = vec_merge_hi(m0, m1); \ + b1 = vec_merge_hi(m2, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_10_2(b0, b1) \ + do { \ + b0 = vec_merge_lo(m0, m1); \ + b1 = vec_merge_lo(m2, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_10_3(b0, b1) \ + do { \ + b0 = vec_merge_hi(m4, m5); \ + b1 = vec_merge_hi(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_10_4(b0, b1) \ + do { \ + b0 = vec_merge_lo(m4, m5); \ + b1 = vec_merge_lo(m6, m7); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_11_1(b0, b1) \ + do { \ + b0 = vec_merge_hi(m7, m2); \ + b1 = vec_merge_lo(m4, m6); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_11_2(b0, b1) \ + do { \ + b0 = vec_merge_hi(m5, m4); \ + b1 = vec_shl_8(m7, m3); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_11_3(b0, b1) \ + do { \ + b0 = vec_shl_8(m0, m0); \ + b1 = vec_merge_lo(m5, m2); \ + } while(0) + + #define BLAKE2B_LOAD_MSG_11_4(b0, b1) \ + do { \ + b0 = vec_merge_hi(m6, m1); \ + b1 = vec_merge_lo(m3, m1); \ + } while(0) + + // Power8 has packed 64-bit rotate, but in terms of left rotate + const uint64x2_p ROR16_MASK = { 64-16, 64-16 }; + const uint64x2_p ROR24_MASK = { 64-24, 64-24 }; + const uint64x2_p ROR32_MASK = { 64-32, 64-32 }; + const uint64x2_p ROR63_MASK = { 64-63, 64-63 }; + + #define vec_ror_32(x) vec_rl(x, ROR32_MASK) + #define vec_ror_24(x) vec_rl(x, ROR24_MASK) + #define vec_ror_16(x) vec_rl(x, ROR16_MASK) + #define vec_ror_63(x) vec_rl(x, ROR63_MASK) + + #define BLAKE2B_G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ + do { \ + row1l = VecAdd(VecAdd(row1l, b0), row2l); \ + row1h = VecAdd(VecAdd(row1h, b1), row2h); \ + row4l = VecXor(row4l, row1l); row4h = VecXor(row4h, row1h); \ + row4l = vec_ror_32(row4l); row4h = vec_ror_32(row4h); \ + row3l = VecAdd(row3l, row4l); row3h = VecAdd(row3h, row4h); \ + row2l = VecXor(row2l, row3l); row2h = VecXor(row2h, row3h); \ + row2l = vec_ror_24(row2l); row2h = vec_ror_24(row2h); \ + } while(0) + + #define BLAKE2B_G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ + do { \ + row1l = VecAdd(VecAdd(row1l, b0), row2l); \ + row1h = VecAdd(VecAdd(row1h, b1), row2h); \ + row4l = VecXor(row4l, row1l); row4h = VecXor(row4h, row1h); \ + row4l = vec_ror_16(row4l); row4h = vec_ror_16(row4h); \ + row3l = VecAdd(row3l, row4l); row3h = VecAdd(row3h, row4h); \ + row2l = VecXor(row2l, row3l); row2h = VecXor(row2h, row3h); \ + row2l = vec_ror_63(row2l); row2h = vec_ror_63(row2h); \ + } while(0) + + #define BLAKE2B_DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ + do { \ + uint64x2_p t0 = vec_shl_8(row2l, row2h); \ + uint64x2_p t1 = vec_shl_8(row2h, row2l); \ + row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \ + t0 = vec_shl_8(row4h, row4l); t1 = vec_shl_8(row4l, row4h); \ + row4l = t0; row4h = t1; \ + } while(0) + + #define BLAKE2B_UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ + do { \ + uint64x2_p t0 = vec_shl_8(row2h, row2l); \ + uint64x2_p t1 = vec_shl_8(row2l, row2h); \ + row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \ + t0 = vec_shl_8(row4l, row4h); t1 = vec_shl_8(row4h, row4l); \ + row4l = t0; row4h = t1; \ + } while(0) + + #define BLAKE2B_ROUND(r) \ + do { \ + uint64x2_p b0, b1; \ + BLAKE2B_LOAD_MSG_ ##r ##_1(b0, b1); \ + BLAKE2B_G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_LOAD_MSG_ ##r ##_2(b0, b1); \ + BLAKE2B_G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ + BLAKE2B_LOAD_MSG_ ##r ##_3(b0, b1); \ + BLAKE2B_G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_LOAD_MSG_ ##r ##_4(b0, b1); \ + BLAKE2B_G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ + BLAKE2B_UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ + } while(0) + + // Possibly unaligned user messages + uint64x2_p m0, m1, m2, m3, m4, m5, m6, m7; + // Endian conversion mask + const uint8x16_p le_mask = {7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8}; + +#if defined(_ARCH_PWR9) + // POWER9 provides loads for char's and short's + m0 = (uint64x2_p) vec_xl( 0, CONST_V8_CAST( input )); + m1 = (uint64x2_p) vec_xl( 16, CONST_V8_CAST( input )); + m2 = (uint64x2_p) vec_xl( 32, CONST_V8_CAST( input )); + m3 = (uint64x2_p) vec_xl( 48, CONST_V8_CAST( input )); + m4 = (uint64x2_p) vec_xl( 64, CONST_V8_CAST( input )); + m5 = (uint64x2_p) vec_xl( 80, CONST_V8_CAST( input )); + m6 = (uint64x2_p) vec_xl( 96, CONST_V8_CAST( input )); + m7 = (uint64x2_p) vec_xl(112, CONST_V8_CAST( input )); + +# if defined(CRYPTOPP_BIG_ENDIAN) + m0 = vec_perm(m0, m0, le_mask); + m1 = vec_perm(m1, m1, le_mask); + m2 = vec_perm(m2, m2, le_mask); + m3 = vec_perm(m3, m3, le_mask); + m4 = vec_perm(m4, m4, le_mask); + m5 = vec_perm(m5, m5, le_mask); + m6 = vec_perm(m6, m6, le_mask); + m7 = vec_perm(m7, m7, le_mask); +# endif +#else + // Altivec only provides 16-byte aligned loads + // http://www.nxp.com/docs/en/reference-manual/ALTIVECPEM.pdf + m0 = (uint64x2_p) vec_ld( 0, CONST_V8_CAST( input )); + m1 = (uint64x2_p) vec_ld( 16, CONST_V8_CAST( input )); + m2 = (uint64x2_p) vec_ld( 32, CONST_V8_CAST( input )); + m3 = (uint64x2_p) vec_ld( 48, CONST_V8_CAST( input )); + m4 = (uint64x2_p) vec_ld( 64, CONST_V8_CAST( input )); + m5 = (uint64x2_p) vec_ld( 80, CONST_V8_CAST( input )); + m6 = (uint64x2_p) vec_ld( 96, CONST_V8_CAST( input )); + m7 = (uint64x2_p) vec_ld(112, CONST_V8_CAST( input )); + + // Alignment check for load of the message buffer + const uintptr_t addr = (uintptr_t)input; + if (addr%16 == 0) + { + // Already aligned. Perform a little-endian swap as required +# if defined(CRYPTOPP_BIG_ENDIAN) + m0 = vec_perm(m0, m0, le_mask); + m1 = vec_perm(m1, m1, le_mask); + m2 = vec_perm(m2, m2, le_mask); + m3 = vec_perm(m3, m3, le_mask); + m4 = vec_perm(m4, m4, le_mask); + m5 = vec_perm(m5, m5, le_mask); + m6 = vec_perm(m6, m6, le_mask); + m7 = vec_perm(m7, m7, le_mask); +# endif + } + else + { + // Not aligned. Fix vectors and perform a little-endian swap as required + // http://mirror.informatimago.com/next/developer.apple.com/ + // hardwaredrivers/ve/code_optimization.html + uint64x2_p ex; uint8x16_p perm; + ex = (uint64x2_p) vec_ld(112+15, CONST_V8_CAST( input )); + perm = vec_lvsl(0, CONST_V8_CAST( addr )); + +# if defined(CRYPTOPP_BIG_ENDIAN) + // Combine the vector permute with the little-endian swap + perm = vec_perm(perm, perm, le_mask); +# endif + + m0 = vec_perm(m0, m1, perm); + m1 = vec_perm(m1, m2, perm); + m2 = vec_perm(m2, m3, perm); + m3 = vec_perm(m3, m4, perm); + m4 = vec_perm(m4, m5, perm); + m5 = vec_perm(m5, m6, perm); + m6 = vec_perm(m6, m7, perm); + m7 = vec_perm(m7, ex, perm); + } +#endif + + uint64x2_p row1l, row1h, row2l, row2h; + uint64x2_p row3l, row3h, row4l, row4h; + + const uint64x2_p h0 = row1l = VecLoad64LE(state.h()+0, le_mask); + const uint64x2_p h1 = row1h = VecLoad64LE(state.h()+2, le_mask); + const uint64x2_p h2 = row2l = VecLoad64LE(state.h()+4, le_mask); + const uint64x2_p h3 = row2h = VecLoad64LE(state.h()+6, le_mask); + + row3l = VecLoad64(BLAKE2B_IV+0); + row3h = VecLoad64(BLAKE2B_IV+2); + row4l = VecXor(VecLoad64(BLAKE2B_IV+4), VecLoad64(state.t()+0)); + row4h = VecXor(VecLoad64(BLAKE2B_IV+6), VecLoad64(state.f()+0)); + + BLAKE2B_ROUND(0); + BLAKE2B_ROUND(1); + BLAKE2B_ROUND(2); + BLAKE2B_ROUND(3); + BLAKE2B_ROUND(4); + BLAKE2B_ROUND(5); + BLAKE2B_ROUND(6); + BLAKE2B_ROUND(7); + BLAKE2B_ROUND(8); + BLAKE2B_ROUND(9); + BLAKE2B_ROUND(10); + BLAKE2B_ROUND(11); + + VecStore64LE(state.h()+0, VecXor(h0, VecXor(row1l, row3l)), le_mask); + VecStore64LE(state.h()+2, VecXor(h1, VecXor(row1h, row3h)), le_mask); + VecStore64LE(state.h()+4, VecXor(h2, VecXor(row2l, row4l)), le_mask); + VecStore64LE(state.h()+6, VecXor(h3, VecXor(row2h, row4h)), le_mask); +} +#endif // CRYPTOPP_POWER8_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/blake2s_simd.cpp b/external/ours/library/crypto/src/shared/original/blake2s_simd.cpp new file mode 100755 index 000000000..4d00f609e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/blake2s_simd.cpp @@ -0,0 +1,1091 @@ +// blake2_simd.cpp - written and placed in the public domain by +// Samuel Neves, Jeffrey Walton, Uri Blumenthal +// and Marcel Raad. +// +// This source file uses intrinsics to gain access to ARMv7a/ARMv8a +// NEON, Power7 and SSE4.1 instructions. A separate source file is +// needed because additional CXXFLAGS are required to enable the +// appropriate instructions sets in some build configurations. + +// The BLAKE2b and BLAKE2s numbers are consistent with the BLAKE2 team's +// numbers. However, we have an Altivec implementation of BLAKE2s, +// and a POWER8 implementation of BLAKE2b (BLAKE2 team is missing them). +// Altivec code is about 2x faster than C++ when using GCC 5.0 or +// above. The POWER8 code is about 2.5x faster than C++ when using GCC 5.0 +// or above. If you use GCC 4.0 (PowerMac) or GCC 4.8 (GCC Compile Farm) +// then the PowerPC code will be slower than C++. Be sure to use GCC 5.0 +// or above for PowerPC builds or disable Altivec for BLAKE2b and BLAKE2s +// if using the old compilers. + +#include "pch.h" +#include "config.h" +#include "misc.h" +#include "blake2.h" + +// Uncomment for benchmarking C++ against SSE2 or NEON. +// Do so in both blake2.cpp and blake2_simd.cpp. +// #undef CRYPTOPP_SSE41_AVAILABLE +// #undef CRYPTOPP_ARM_NEON_AVAILABLE +// #undef CRYPTOPP_ALTIVEC_AVAILABLE + +// Disable NEON/ASIMD for Cortex-A53 and A57. The shifts are too slow and C/C++ is about +// 3 cpb faster than NEON/ASIMD. Also see http://github.com/weidai11/cryptopp/issues/367. +#if (defined(__aarch32__) || defined(__aarch64__)) && defined(CRYPTOPP_SLOW_ARMV8_SHIFT) +# undef CRYPTOPP_ARM_NEON_AVAILABLE +#endif + +// BLAKE2s bug on AIX 7.1 (POWER7) with XLC 12.01 +// https://github.com/weidai11/cryptopp/issues/743 +#if defined(__xlC__) && (__xlC__ < 0x0d01) +# define CRYPTOPP_DISABLE_ALTIVEC 1 +# undef CRYPTOPP_POWER7_AVAILABLE +# undef CRYPTOPP_ALTIVEC_AVAILABLE +#endif + +#if defined(__XOP__) +# include +# if defined(__GNUC__) +# include +# endif +#endif + +#if (CRYPTOPP_SSE41_AVAILABLE) +# include +# include +# include +#endif + +#if (CRYPTOPP_ARM_NEON_HEADER) +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) +# include "ppc_simd.h" +#endif + +#if defined(CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE) +/* Ignore "warning: vec_lvsl is deprecated..." */ +# pragma GCC diagnostic ignored "-Wdeprecated" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char BLAKE2S_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +// Exported by blake2.cpp +extern const word32 BLAKE2S_IV[8]; +extern const word64 BLAKE2B_IV[8]; + +#if CRYPTOPP_SSE41_AVAILABLE + +#define LOADU(p) _mm_loadu_si128((const __m128i *)(const void*)(p)) +#define STOREU(p,r) _mm_storeu_si128((__m128i *)(void*)(p), r) +#define TOF(reg) _mm_castsi128_ps((reg)) +#define TOI(reg) _mm_castps_si128((reg)) + +void BLAKE2_Compress32_SSE4(const byte* input, BLAKE2s_State& state) +{ + #define BLAKE2S_LOAD_MSG_0_1(buf) \ + buf = TOI(_mm_shuffle_ps(TOF(m0), TOF(m1), _MM_SHUFFLE(2,0,2,0))); + + #define BLAKE2S_LOAD_MSG_0_2(buf) \ + buf = TOI(_mm_shuffle_ps(TOF(m0), TOF(m1), _MM_SHUFFLE(3,1,3,1))); + + #define BLAKE2S_LOAD_MSG_0_3(buf) \ + t0 = _mm_shuffle_epi32(m2, _MM_SHUFFLE(3,2,0,1)); \ + t1 = _mm_shuffle_epi32(m3, _MM_SHUFFLE(0,1,3,2)); \ + buf = _mm_blend_epi16(t0, t1, 0xC3); + + #define BLAKE2S_LOAD_MSG_0_4(buf) \ + t0 = _mm_blend_epi16(t0, t1, 0x3C); \ + buf = _mm_shuffle_epi32(t0, _MM_SHUFFLE(2,3,0,1)); + + #define BLAKE2S_LOAD_MSG_1_1(buf) \ + t0 = _mm_blend_epi16(m1, m2, 0x0C); \ + t1 = _mm_slli_si128(m3, 4); \ + t2 = _mm_blend_epi16(t0, t1, 0xF0); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,1,0,3)); + + #define BLAKE2S_LOAD_MSG_1_2(buf) \ + t0 = _mm_shuffle_epi32(m2,_MM_SHUFFLE(0,0,2,0)); \ + t1 = _mm_blend_epi16(m1,m3,0xC0); \ + t2 = _mm_blend_epi16(t0, t1, 0xF0); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,3,0,1)); + + #define BLAKE2S_LOAD_MSG_1_3(buf) \ + t0 = _mm_slli_si128(m1, 4); \ + t1 = _mm_blend_epi16(m2, t0, 0x30); \ + t2 = _mm_blend_epi16(m0, t1, 0xF0); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3,0,1,2)); + + #define BLAKE2S_LOAD_MSG_1_4(buf) \ + t0 = _mm_unpackhi_epi32(m0,m1); \ + t1 = _mm_slli_si128(m3, 4); \ + t2 = _mm_blend_epi16(t0, t1, 0x0C); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3,0,1,2)); + + #define BLAKE2S_LOAD_MSG_2_1(buf) \ + t0 = _mm_unpackhi_epi32(m2,m3); \ + t1 = _mm_blend_epi16(m3,m1,0x0C); \ + t2 = _mm_blend_epi16(t0, t1, 0x0F); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3,1,0,2)); + + #define BLAKE2S_LOAD_MSG_2_2(buf) \ + t0 = _mm_unpacklo_epi32(m2,m0); \ + t1 = _mm_blend_epi16(t0, m0, 0xF0); \ + t2 = _mm_slli_si128(m3, 8); \ + buf = _mm_blend_epi16(t1, t2, 0xC0); + + #define BLAKE2S_LOAD_MSG_2_3(buf) \ + t0 = _mm_blend_epi16(m0, m2, 0x3C); \ + t1 = _mm_srli_si128(m1, 12); \ + t2 = _mm_blend_epi16(t0,t1,0x03); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(0,3,2,1)); + + #define BLAKE2S_LOAD_MSG_2_4(buf) \ + t0 = _mm_slli_si128(m3, 4); \ + t1 = _mm_blend_epi16(m0, m1, 0x33); \ + t2 = _mm_blend_epi16(t1, t0, 0xC0); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,2,3,0)); + + #define BLAKE2S_LOAD_MSG_3_1(buf) \ + t0 = _mm_unpackhi_epi32(m0,m1); \ + t1 = _mm_unpackhi_epi32(t0, m2); \ + t2 = _mm_blend_epi16(t1, m3, 0x0C); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3,1,0,2)); + + #define BLAKE2S_LOAD_MSG_3_2(buf) \ + t0 = _mm_slli_si128(m2, 8); \ + t1 = _mm_blend_epi16(m3,m0,0x0C); \ + t2 = _mm_blend_epi16(t1, t0, 0xC0); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,0,1,3)); + + #define BLAKE2S_LOAD_MSG_3_3(buf) \ + t0 = _mm_blend_epi16(m0,m1,0x0F); \ + t1 = _mm_blend_epi16(t0, m3, 0xC0); \ + buf = _mm_shuffle_epi32(t1, _MM_SHUFFLE(0,1,2,3)); + + #define BLAKE2S_LOAD_MSG_3_4(buf) \ + t0 = _mm_alignr_epi8(m0, m1, 4); \ + buf = _mm_blend_epi16(t0, m2, 0x33); + + #define BLAKE2S_LOAD_MSG_4_1(buf) \ + t0 = _mm_unpacklo_epi64(m1,m2); \ + t1 = _mm_unpackhi_epi64(m0,m2); \ + t2 = _mm_blend_epi16(t0,t1,0x33); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,0,1,3)); + + #define BLAKE2S_LOAD_MSG_4_2(buf) \ + t0 = _mm_unpackhi_epi64(m1,m3); \ + t1 = _mm_unpacklo_epi64(m0,m1); \ + buf = _mm_blend_epi16(t0,t1,0x33); + + #define BLAKE2S_LOAD_MSG_4_3(buf) \ + t0 = _mm_unpackhi_epi64(m3,m1); \ + t1 = _mm_unpackhi_epi64(m2,m0); \ + t2 = _mm_blend_epi16(t1,t0,0x33); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,1,0,3)); + + #define BLAKE2S_LOAD_MSG_4_4(buf) \ + t0 = _mm_blend_epi16(m0,m2,0x03); \ + t1 = _mm_slli_si128(t0, 8); \ + t2 = _mm_blend_epi16(t1,m3,0x0F); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,0,3,1)); + + #define BLAKE2S_LOAD_MSG_5_1(buf) \ + t0 = _mm_unpackhi_epi32(m0,m1); \ + t1 = _mm_unpacklo_epi32(m0,m2); \ + buf = _mm_unpacklo_epi64(t0,t1); + + #define BLAKE2S_LOAD_MSG_5_2(buf) \ + t0 = _mm_srli_si128(m2, 4); \ + t1 = _mm_blend_epi16(m0,m3,0x03); \ + buf = _mm_blend_epi16(t1,t0,0x3C); + + #define BLAKE2S_LOAD_MSG_5_3(buf) \ + t0 = _mm_blend_epi16(m1,m0,0x0C); \ + t1 = _mm_srli_si128(m3, 4); \ + t2 = _mm_blend_epi16(t0,t1,0x30); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,3,0,1)); + + #define BLAKE2S_LOAD_MSG_5_4(buf) \ + t0 = _mm_unpacklo_epi64(m2,m1); \ + t1 = _mm_shuffle_epi32(m3, _MM_SHUFFLE(2,0,1,0)); \ + t2 = _mm_srli_si128(t0, 4); \ + buf = _mm_blend_epi16(t1,t2,0x33); + + #define BLAKE2S_LOAD_MSG_6_1(buf) \ + t0 = _mm_slli_si128(m1, 12); \ + t1 = _mm_blend_epi16(m0,m3,0x33); \ + buf = _mm_blend_epi16(t1,t0,0xC0); + + #define BLAKE2S_LOAD_MSG_6_2(buf) \ + t0 = _mm_blend_epi16(m3,m2,0x30); \ + t1 = _mm_srli_si128(m1, 4); \ + t2 = _mm_blend_epi16(t0,t1,0x03); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,1,3,0)); + + #define BLAKE2S_LOAD_MSG_6_3(buf) \ + t0 = _mm_unpacklo_epi64(m0,m2); \ + t1 = _mm_srli_si128(m1, 4); \ + t2 = _mm_blend_epi16(t0,t1,0x0C); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3,1,0,2)); + + #define BLAKE2S_LOAD_MSG_6_4(buf) \ + t0 = _mm_unpackhi_epi32(m1,m2); \ + t1 = _mm_unpackhi_epi64(m0,t0); \ + buf = _mm_shuffle_epi32(t1, _MM_SHUFFLE(0,1,2,3)); + + #define BLAKE2S_LOAD_MSG_7_1(buf) \ + t0 = _mm_unpackhi_epi32(m0,m1); \ + t1 = _mm_blend_epi16(t0,m3,0x0F); \ + buf = _mm_shuffle_epi32(t1,_MM_SHUFFLE(2,0,3,1)); + + #define BLAKE2S_LOAD_MSG_7_2(buf) \ + t0 = _mm_blend_epi16(m2,m3,0x30); \ + t1 = _mm_srli_si128(m0,4); \ + t2 = _mm_blend_epi16(t0,t1,0x03); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,0,2,3)); + + #define BLAKE2S_LOAD_MSG_7_3(buf) \ + t0 = _mm_unpackhi_epi64(m0,m3); \ + t1 = _mm_unpacklo_epi64(m1,m2); \ + t2 = _mm_blend_epi16(t0,t1,0x3C); \ + buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(2,3,1,0)); + + #define BLAKE2S_LOAD_MSG_7_4(buf) \ + t0 = _mm_unpacklo_epi32(m0,m1); \ + t1 = _mm_unpackhi_epi32(m1,m2); \ + t2 = _mm_unpacklo_epi64(t0,t1); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,1,0,3)); + + #define BLAKE2S_LOAD_MSG_8_1(buf) \ + t0 = _mm_unpackhi_epi32(m1,m3); \ + t1 = _mm_unpacklo_epi64(t0,m0); \ + t2 = _mm_blend_epi16(t1,m2,0xC0); \ + buf = _mm_shufflehi_epi16(t2,_MM_SHUFFLE(1,0,3,2)); + + #define BLAKE2S_LOAD_MSG_8_2(buf) \ + t0 = _mm_unpackhi_epi32(m0,m3); \ + t1 = _mm_blend_epi16(m2,t0,0xF0); \ + buf = _mm_shuffle_epi32(t1,_MM_SHUFFLE(0,2,1,3)); + + #define BLAKE2S_LOAD_MSG_8_3(buf) \ + t0 = _mm_unpacklo_epi64(m0,m3); \ + t1 = _mm_srli_si128(m2,8); \ + t2 = _mm_blend_epi16(t0,t1,0x03); \ + buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,3,2,0)); + + #define BLAKE2S_LOAD_MSG_8_4(buf) \ + t0 = _mm_blend_epi16(m1,m0,0x30); \ + buf = _mm_shuffle_epi32(t0,_MM_SHUFFLE(0,3,2,1)); + + #define BLAKE2S_LOAD_MSG_9_1(buf) \ + t0 = _mm_blend_epi16(m0,m2,0x03); \ + t1 = _mm_blend_epi16(m1,m2,0x30); \ + t2 = _mm_blend_epi16(t1,t0,0x0F); \ + buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(1,3,0,2)); + + #define BLAKE2S_LOAD_MSG_9_2(buf) \ + t0 = _mm_slli_si128(m0,4); \ + t1 = _mm_blend_epi16(m1,t0,0xC0); \ + buf = _mm_shuffle_epi32(t1,_MM_SHUFFLE(1,2,0,3)); + + #define BLAKE2S_LOAD_MSG_9_3(buf) \ + t0 = _mm_unpackhi_epi32(m0,m3); \ + t1 = _mm_unpacklo_epi32(m2,m3); \ + t2 = _mm_unpackhi_epi64(t0,t1); \ + buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(0,2,1,3)); + + #define BLAKE2S_LOAD_MSG_9_4(buf) \ + t0 = _mm_blend_epi16(m3,m2,0xC0); \ + t1 = _mm_unpacklo_epi32(m0,m3); \ + t2 = _mm_blend_epi16(t0,t1,0x0F); \ + buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(1,2,3,0)); + +#ifdef __XOP__ +# define MM_ROTI_EPI32(r, c) \ + _mm_roti_epi32(r, c) +#else +# define MM_ROTI_EPI32(r, c) ( \ + (8==-(c)) ? _mm_shuffle_epi8(r,r8) \ + : (16==-(c)) ? _mm_shuffle_epi8(r,r16) \ + : _mm_xor_si128(_mm_srli_epi32((r), -(c)), \ + _mm_slli_epi32((r), 32-(-(c))))) +#endif + +#define BLAKE2S_G1(row1,row2,row3,row4,buf) \ + row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \ + row4 = _mm_xor_si128( row4, row1 ); \ + row4 = MM_ROTI_EPI32(row4, -16); \ + row3 = _mm_add_epi32( row3, row4 ); \ + row2 = _mm_xor_si128( row2, row3 ); \ + row2 = MM_ROTI_EPI32(row2, -12); + +#define BLAKE2S_G2(row1,row2,row3,row4,buf) \ + row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \ + row4 = _mm_xor_si128( row4, row1 ); \ + row4 = MM_ROTI_EPI32(row4, -8); \ + row3 = _mm_add_epi32( row3, row4 ); \ + row2 = _mm_xor_si128( row2, row3 ); \ + row2 = MM_ROTI_EPI32(row2, -7); + +#define DIAGONALIZE(row1,row2,row3,row4) \ + row1 = _mm_shuffle_epi32( row1, _MM_SHUFFLE(2,1,0,3) ); \ + row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(1,0,3,2) ); \ + row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(0,3,2,1) ); + +#define UNDIAGONALIZE(row1,row2,row3,row4) \ + row1 = _mm_shuffle_epi32( row1, _MM_SHUFFLE(0,3,2,1) ); \ + row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(1,0,3,2) ); \ + row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(2,1,0,3) ); + +#define BLAKE2S_ROUND(r) \ + BLAKE2S_LOAD_MSG_ ##r ##_1(buf1); \ + BLAKE2S_G1(row1,row2,row3,row4,buf1); \ + BLAKE2S_LOAD_MSG_ ##r ##_2(buf2); \ + BLAKE2S_G2(row1,row2,row3,row4,buf2); \ + DIAGONALIZE(row1,row2,row3,row4); \ + BLAKE2S_LOAD_MSG_ ##r ##_3(buf3); \ + BLAKE2S_G1(row1,row2,row3,row4,buf3); \ + BLAKE2S_LOAD_MSG_ ##r ##_4(buf4); \ + BLAKE2S_G2(row1,row2,row3,row4,buf4); \ + UNDIAGONALIZE(row1,row2,row3,row4); + + __m128i row1, row2, row3, row4; + __m128i buf1, buf2, buf3, buf4; + __m128i t0, t1, t2, ff0, ff1; + + const __m128i r8 = _mm_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1); + const __m128i r16 = _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + + const __m128i m0 = LOADU(input + 00); + const __m128i m1 = LOADU(input + 16); + const __m128i m2 = LOADU(input + 32); + const __m128i m3 = LOADU(input + 48); + + row1 = ff0 = LOADU(state.h()+0); + row2 = ff1 = LOADU(state.h()+4); + row3 = LOADU(BLAKE2S_IV+0); + row4 = _mm_xor_si128(LOADU(BLAKE2S_IV+4), LOADU(state.t()+0)); + + BLAKE2S_ROUND(0); + BLAKE2S_ROUND(1); + BLAKE2S_ROUND(2); + BLAKE2S_ROUND(3); + BLAKE2S_ROUND(4); + BLAKE2S_ROUND(5); + BLAKE2S_ROUND(6); + BLAKE2S_ROUND(7); + BLAKE2S_ROUND(8); + BLAKE2S_ROUND(9); + + STOREU(state.h()+0, _mm_xor_si128(ff0, _mm_xor_si128(row1, row3))); + STOREU(state.h()+4, _mm_xor_si128(ff1, _mm_xor_si128(row2, row4))); +} +#endif // CRYPTOPP_SSE41_AVAILABLE + +#if CRYPTOPP_ARM_NEON_AVAILABLE +void BLAKE2_Compress32_NEON(const byte* input, BLAKE2s_State& state) +{ + #define BLAKE2S_LOAD_MSG_0_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m0), vget_high_u32(m0)).val[0]; \ + t1 = vzip_u32(vget_low_u32(m1), vget_high_u32(m1)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_0_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m0), vget_high_u32(m0)).val[1]; \ + t1 = vzip_u32(vget_low_u32(m1), vget_high_u32(m1)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_0_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m2), vget_high_u32(m2)).val[0]; \ + t1 = vzip_u32(vget_low_u32(m3), vget_high_u32(m3)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_0_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m2), vget_high_u32(m2)).val[1]; \ + t1 = vzip_u32(vget_low_u32(m3), vget_high_u32(m3)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_1_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m3), vget_low_u32(m1)).val[0]; \ + t1 = vzip_u32(vget_low_u32(m2), vget_low_u32(m3)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_1_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m2), vget_low_u32(m2)).val[0]; \ + t1 = vext_u32(vget_high_u32(m3), vget_high_u32(m1), 1); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_1_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vext_u32(vget_low_u32(m0), vget_low_u32(m0), 1); \ + t1 = vzip_u32(vget_high_u32(m2), vget_low_u32(m1)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_1_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m3), vget_high_u32(m0)).val[0]; \ + t1 = vzip_u32(vget_high_u32(m1), vget_high_u32(m0)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_2_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vext_u32(vget_high_u32(m2), vget_low_u32(m3), 1); \ + t1 = vzip_u32(vget_low_u32(m1), vget_high_u32(m3)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_2_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m2), vget_low_u32(m0)).val[0]; \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_high_u32(m0), vget_low_u32(m3)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_2_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_high_u32(m2), vget_high_u32(m0)); \ + t1 = vzip_u32(vget_high_u32(m1), vget_low_u32(m2)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_2_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m3), vget_high_u32(m1)).val[0]; \ + t1 = vext_u32(vget_low_u32(m0), vget_low_u32(m1), 1); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_3_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m1), vget_high_u32(m0)).val[1]; \ + t1 = vzip_u32(vget_low_u32(m3), vget_high_u32(m2)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_3_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m2), vget_low_u32(m0)).val[1]; \ + t1 = vzip_u32(vget_low_u32(m3), vget_high_u32(m3)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_3_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_high_u32(m0), vget_low_u32(m1)); \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_low_u32(m1), vget_high_u32(m3)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_3_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m1), vget_high_u32(m2)).val[0]; \ + t1 = vzip_u32(vget_low_u32(m0), vget_low_u32(m2)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_4_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m2), vget_low_u32(m1)).val[1]; \ + t1 = vzip_u32((vget_high_u32(m0)), vget_high_u32(m2)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_4_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_low_u32(m0), vget_high_u32(m1)); \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_low_u32(m1), vget_high_u32(m3)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_4_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_high_u32(m3), vget_high_u32(m2)); \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_high_u32(m1), vget_high_u32(m0)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_4_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vext_u32(vget_low_u32(m0), vget_low_u32(m3), 1); \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_low_u32(m2), vget_low_u32(m3)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_5_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32((vget_high_u32(m0)), vget_high_u32(m1)).val[0]; \ + t1 = vzip_u32(vget_low_u32(m0), vget_low_u32(m2)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_5_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m3), vget_high_u32(m2)).val[0]; \ + t1 = vzip_u32(vget_high_u32(m2), vget_high_u32(m0)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_5_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_low_u32(m1), vget_high_u32(m1)); \ + t1 = vzip_u32(vget_high_u32(m3), vget_low_u32(m0)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_5_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m3), vget_low_u32(m1)).val[1]; \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_high_u32(m3), vget_low_u32(m2)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_6_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_low_u32(m3), vget_low_u32(m0)); \ + t1 = vzip_u32(vget_high_u32(m3), vget_low_u32(m1)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_6_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m1), vget_high_u32(m3)).val[1]; \ + t1 = vext_u32(vget_low_u32(m3), vget_high_u32(m2), 1); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_6_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m0), vget_high_u32(m1)).val[0]; \ + t1 = vext_u32(vget_low_u32(m2), vget_low_u32(m2), 1); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_6_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m1), vget_high_u32(m0)).val[1]; \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_high_u32(m0), vget_high_u32(m2)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_7_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m3), vget_high_u32(m1)).val[1]; \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_low_u32(m3), vget_high_u32(m0)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_7_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vext_u32(vget_high_u32(m2), vget_high_u32(m3), 1); \ + t1 = vzip_u32(vget_low_u32(m0), vget_low_u32(m2)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_7_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m1), vget_high_u32(m3)).val[1]; \ + t1 = vzip_u32(vget_low_u32(m2), vget_high_u32(m0)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_7_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_low_u32(m0), vget_low_u32(m1)).val[0]; \ + t1 = vzip_u32(vget_high_u32(m1), vget_high_u32(m2)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_8_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m1), vget_high_u32(m3)).val[0]; \ + t1 = vext_u32(vget_high_u32(m2), vget_low_u32(m0), 1); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_8_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m3), vget_low_u32(m2)).val[1]; \ + t1 = vext_u32(vget_high_u32(m0), vget_low_u32(m2), 1); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_8_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_low_u32(m3), vget_low_u32(m3)); \ + t1 = vext_u32(vget_low_u32(m0), vget_high_u32(m2), 1); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_8_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_high_u32(m0), vget_high_u32(m1)); \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_low_u32(m1), vget_low_u32(m1)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_9_1(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m2), vget_low_u32(m2)).val[0]; \ + t1 = vzip_u32(vget_high_u32(m1), vget_low_u32(m0)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_9_2(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32((vget_high_u32(m0)), vget_low_u32(m1)).val[0]; \ + t1 = vbsl_u32(vcreate_u32(0xFFFFFFFF), vget_high_u32(m1), vget_low_u32(m1)); \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_9_3(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vzip_u32(vget_high_u32(m3), vget_low_u32(m2)).val[1]; \ + t1 = vzip_u32((vget_high_u32(m0)), vget_low_u32(m3)).val[1]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define BLAKE2S_LOAD_MSG_9_4(buf) \ + do { uint32x2_t t0, t1; \ + t0 = vext_u32(vget_high_u32(m2), vget_high_u32(m3), 1); \ + t1 = vzip_u32(vget_low_u32(m3), vget_low_u32(m0)).val[0]; \ + buf = vcombine_u32(t0, t1); } while(0) + + #define vrorq_n_u32_16(x) vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(x))) + + #define vrorq_n_u32_8(x) vsriq_n_u32(vshlq_n_u32((x), 24), (x), 8) + + #define vrorq_n_u32(x, c) vsriq_n_u32(vshlq_n_u32((x), 32-(c)), (x), (c)) + + #define BLAKE2S_G1(row1,row2,row3,row4,buf) \ + do { \ + row1 = vaddq_u32(vaddq_u32(row1, buf), row2); row4 = veorq_u32(row4, row1); \ + row4 = vrorq_n_u32_16(row4); row3 = vaddq_u32(row3, row4); \ + row2 = veorq_u32(row2, row3); row2 = vrorq_n_u32(row2, 12); \ + } while(0) + + #define BLAKE2S_G2(row1,row2,row3,row4,buf) \ + do { \ + row1 = vaddq_u32(vaddq_u32(row1, buf), row2); row4 = veorq_u32(row4, row1); \ + row4 = vrorq_n_u32_8(row4); row3 = vaddq_u32(row3, row4); \ + row2 = veorq_u32(row2, row3); row2 = vrorq_n_u32(row2, 7); \ + } while(0) + + #define BLAKE2S_DIAGONALIZE(row1,row2,row3,row4) \ + do { \ + row4 = vextq_u32(row4, row4, 3); row3 = vextq_u32(row3, row3, 2); row2 = vextq_u32(row2, row2, 1); \ + } while(0) + + #define BLAKE2S_UNDIAGONALIZE(row1,row2,row3,row4) \ + do { \ + row4 = vextq_u32(row4, row4, 1); \ + row3 = vextq_u32(row3, row3, 2); \ + row2 = vextq_u32(row2, row2, 3); \ + } while(0) + + #define BLAKE2S_ROUND(r) \ + do { \ + uint32x4_t buf1, buf2, buf3, buf4; \ + BLAKE2S_LOAD_MSG_ ##r ##_1(buf1); \ + BLAKE2S_G1(row1,row2,row3,row4,buf1); \ + BLAKE2S_LOAD_MSG_ ##r ##_2(buf2); \ + BLAKE2S_G2(row1,row2,row3,row4,buf2); \ + BLAKE2S_DIAGONALIZE(row1,row2,row3,row4); \ + BLAKE2S_LOAD_MSG_ ##r ##_3(buf3); \ + BLAKE2S_G1(row1,row2,row3,row4,buf3); \ + BLAKE2S_LOAD_MSG_ ##r ##_4(buf4); \ + BLAKE2S_G2(row1,row2,row3,row4,buf4); \ + BLAKE2S_UNDIAGONALIZE(row1,row2,row3,row4); \ + } while(0) + + const uint32x4_t m0 = vreinterpretq_u32_u8(vld1q_u8(input + 00)); + const uint32x4_t m1 = vreinterpretq_u32_u8(vld1q_u8(input + 16)); + const uint32x4_t m2 = vreinterpretq_u32_u8(vld1q_u8(input + 32)); + const uint32x4_t m3 = vreinterpretq_u32_u8(vld1q_u8(input + 48)); + + uint32x4_t row1, row2, row3, row4; + + const uint32x4_t f0 = row1 = vld1q_u32(state.h()+0); + const uint32x4_t f1 = row2 = vld1q_u32(state.h()+4); + row3 = vld1q_u32(BLAKE2S_IV+0); + row4 = veorq_u32(vld1q_u32(BLAKE2S_IV+4), vld1q_u32(state.t()+0)); + + BLAKE2S_ROUND(0); + BLAKE2S_ROUND(1); + BLAKE2S_ROUND(2); + BLAKE2S_ROUND(3); + BLAKE2S_ROUND(4); + BLAKE2S_ROUND(5); + BLAKE2S_ROUND(6); + BLAKE2S_ROUND(7); + BLAKE2S_ROUND(8); + BLAKE2S_ROUND(9); + + vst1q_u32(state.h()+0, veorq_u32(f0, veorq_u32(row1, row3))); + vst1q_u32(state.h()+4, veorq_u32(f1, veorq_u32(row2, row4))); +} +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + +template +inline uint32x4_p VecLoad32(const T* p) +{ + return VecLoad(p); +} + +template +inline uint32x4_p VecLoad32LE(const T* p, const uint8x16_p le_mask) +{ +#if defined(CRYPTOPP_BIG_ENDIAN) + const uint32x4_p v = VecLoad(p); + return VecPermute(v, v, le_mask); +#else + CRYPTOPP_UNUSED(le_mask); + return VecLoad(p); +#endif +} + +template +inline void VecStore32(T* p, const uint32x4_p x) +{ + VecStore(x, p); +} + +template +inline void VecStore32LE(T* p, const uint32x4_p x, const uint8x16_p le_mask) +{ +#if defined(CRYPTOPP_BIG_ENDIAN) + const uint32x4_p v = VecPermute(x, x, le_mask); + VecStore(v, p); +#else + CRYPTOPP_UNUSED(le_mask); + VecStore(x, p); +#endif +} + +template +inline uint32x4_p VectorSet32(const uint32x4_p a, const uint32x4_p b) +{ + // Re-index. I'd like to use something like Z=Y*4 and then + // VecShiftLeftOctet(b) but it crashes early Red Hat + // GCC compilers. + enum {X=E1&3, Y=E2&3}; + + // Don't care element + const unsigned int DC = 31; + + // Element 0 combinations + if (X == 0 && Y == 0) + { + const uint8x16_p mask = {0,1,2,3, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, b, mask); + } + else if (X == 0 && Y == 1) + { + const uint8x16_p mask = {0,1,2,3, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<4>(b), mask); + } + else if (X == 0 && Y == 2) + { + const uint8x16_p mask = {0,1,2,3, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<8>(b), mask); + } + else if (X == 0 && Y == 3) + { + const uint8x16_p mask = {0,1,2,3, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<12>(b), mask); + } + + // Element 1 combinations + else if (X == 1 && Y == 0) + { + const uint8x16_p mask = {4,5,6,7, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, b, mask); + } + else if (X == 1 && Y == 1) + { + const uint8x16_p mask = {4,5,6,7, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<4>(b), mask); + } + else if (X == 1 && Y == 2) + { + const uint8x16_p mask = {4,5,6,7, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<8>(b), mask); + } + else if (X == 1 && Y == 3) + { + const uint8x16_p mask = {4,5,6,7, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<12>(b), mask); + } + + // Element 2 combinations + else if (X == 2 && Y == 0) + { + const uint8x16_p mask = {8,9,10,11, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, b, mask); + } + else if (X == 2 && Y == 1) + { + const uint8x16_p mask = {8,9,10,11, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<4>(b), mask); + } + else if (X == 2 && Y == 2) + { + const uint8x16_p mask = {8,9,10,11, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<8>(b), mask); + } + else if (X == 2 && Y == 3) + { + const uint8x16_p mask = {8,9,10,11, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<12>(b), mask); + } + + // Element 3 combinations + else if (X == 3 && Y == 0) + { + const uint8x16_p mask = {12,13,14,15, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, b, mask); + } + else if (X == 3 && Y == 1) + { + const uint8x16_p mask = {12,13,14,15, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<4>(b), mask); + } + else if (X == 3 && Y == 2) + { + const uint8x16_p mask = {12,13,14,15, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<8>(b), mask); + } + else if (X == 3 && Y == 3) + { + const uint8x16_p mask = {12,13,14,15, 16,17,18,19, DC,DC,DC,DC, DC,DC,DC,DC}; + return VecPermute(a, VecShiftLeftOctet<12>(b), mask); + } + + // Quiet IBM XLC warning + return VecXor(a, a); +} + +template +inline uint32x4_p VectorSet32(const uint32x4_p a, const uint32x4_p b, + const uint32x4_p c, const uint32x4_p d) +{ + // Re-index + enum {W=E1&3, X=E2&3, Y=E3&3, Z=E4&3}; + + const uint32x4_p t0 = VectorSet32(a, b); + const uint32x4_p t1 = VectorSet32(c, d); + + // PowerPC follows SSE2's implementation, and this is _mm_set_epi32. + const uint8x16_p mask = {20,21,22,23, 16,17,18,19, 4,5,6,7, 0,1,2,3}; + return VecPermute(t0, t1, mask); +} + +template<> +uint32x4_p VectorSet32<2,0,2,0>(const uint32x4_p a, const uint32x4_p b, + const uint32x4_p c, const uint32x4_p d) +{ + // a=b, c=d, mask is {2,0, 2,0} + CRYPTOPP_UNUSED(b); CRYPTOPP_UNUSED(d); + const uint8x16_p mask = {16,17,18,19, 24,25,26,27, 0,1,2,3, 8,9,10,11}; + return VecPermute(a, c, mask); +} + +template<> +uint32x4_p VectorSet32<3,1,3,1>(const uint32x4_p a, const uint32x4_p b, + const uint32x4_p c, const uint32x4_p d) +{ + // a=b, c=d, mask is {3,1, 3,1} + CRYPTOPP_UNUSED(b); CRYPTOPP_UNUSED(d); + const uint8x16_p mask = {20,21,22,23, 28,29,30,31, 4,5,6,7, 12,13,14,15}; + return VecPermute(a, c, mask); +} + +void BLAKE2_Compress32_ALTIVEC(const byte* input, BLAKE2s_State& state) +{ + # define m1 m0 + # define m2 m0 + # define m3 m0 + + # define m5 m4 + # define m6 m4 + # define m7 m4 + + # define m9 m8 + # define m10 m8 + # define m11 m8 + + # define m13 m12 + # define m14 m12 + # define m15 m12 + + // #define BLAKE2S_LOAD_MSG_0_1(buf) buf = VectorSet32<6,4,2,0>(m6,m4,m2,m0); + #define BLAKE2S_LOAD_MSG_0_1(buf) buf = VectorSet32<2,0,2,0>(m6,m4,m2,m0); + // #define BLAKE2S_LOAD_MSG_0_2(buf) buf = VectorSet32<7,5,3,1>(m7,m5,m3,m1); + #define BLAKE2S_LOAD_MSG_0_2(buf) buf = VectorSet32<3,1,3,1>(m7,m5,m3,m1); + // #define BLAKE2S_LOAD_MSG_0_3(buf) buf = VectorSet32<14,12,10,8>(m14,m12,m10,m8); + #define BLAKE2S_LOAD_MSG_0_3(buf) buf = VectorSet32<2,0,2,0>(m14,m12,m10,m8); + // #define BLAKE2S_LOAD_MSG_0_4(buf) buf = VectorSet32<15,13,11,9>(m15,m13,m11,m9); + #define BLAKE2S_LOAD_MSG_0_4(buf) buf = VectorSet32<3,1,3,1>(m15,m13,m11,m9); + + #define BLAKE2S_LOAD_MSG_1_1(buf) buf = VectorSet32<13,9,4,14>(m13,m9,m4,m14); + #define BLAKE2S_LOAD_MSG_1_2(buf) buf = VectorSet32<6,15,8,10>(m6,m15,m8,m10) + #define BLAKE2S_LOAD_MSG_1_3(buf) buf = VectorSet32<5,11,0,1>(m5,m11,m0,m1) + #define BLAKE2S_LOAD_MSG_1_4(buf) buf = VectorSet32<3,7,2,12>(m3,m7,m2,m12) + + #define BLAKE2S_LOAD_MSG_2_1(buf) buf = VectorSet32<15,5,12,11>(m15,m5,m12,m11) + #define BLAKE2S_LOAD_MSG_2_2(buf) buf = VectorSet32<13,2,0,8>(m13,m2,m0,m8) + #define BLAKE2S_LOAD_MSG_2_3(buf) buf = VectorSet32<9,7,3,10>(m9,m7,m3,m10) + #define BLAKE2S_LOAD_MSG_2_4(buf) buf = VectorSet32<4,1,6,14>(m4,m1,m6,m14) + + #define BLAKE2S_LOAD_MSG_3_1(buf) buf = VectorSet32<11,13,3,7>(m11,m13,m3,m7) + #define BLAKE2S_LOAD_MSG_3_2(buf) buf = VectorSet32<14,12,1,9>(m14,m12,m1,m9) + #define BLAKE2S_LOAD_MSG_3_3(buf) buf = VectorSet32<15,4,5,2>(m15,m4,m5,m2) + #define BLAKE2S_LOAD_MSG_3_4(buf) buf = VectorSet32<8,0,10,6>(m8,m0,m10,m6) + + #define BLAKE2S_LOAD_MSG_4_1(buf) buf = VectorSet32<10,2,5,9>(m10,m2,m5,m9) + #define BLAKE2S_LOAD_MSG_4_2(buf) buf = VectorSet32<15,4,7,0>(m15,m4,m7,m0) + #define BLAKE2S_LOAD_MSG_4_3(buf) buf = VectorSet32<3,6,11,14>(m3,m6,m11,m14) + #define BLAKE2S_LOAD_MSG_4_4(buf) buf = VectorSet32<13,8,12,1>(m13,m8,m12,m1) + + #define BLAKE2S_LOAD_MSG_5_1(buf) buf = VectorSet32<8,0,6,2>(m8,m0,m6,m2) + #define BLAKE2S_LOAD_MSG_5_2(buf) buf = VectorSet32<3,11,10,12>(m3,m11,m10,m12) + #define BLAKE2S_LOAD_MSG_5_3(buf) buf = VectorSet32<1,15,7,4>(m1,m15,m7,m4) + #define BLAKE2S_LOAD_MSG_5_4(buf) buf = VectorSet32<9,14,5,13>(m9,m14,m5,m13) + + #define BLAKE2S_LOAD_MSG_6_1(buf) buf = VectorSet32<4,14,1,12>(m4,m14,m1,m12) + #define BLAKE2S_LOAD_MSG_6_2(buf) buf = VectorSet32<10,13,15,5>(m10,m13,m15,m5) + #define BLAKE2S_LOAD_MSG_6_3(buf) buf = VectorSet32<8,9,6,0>(m8,m9,m6,m0) + #define BLAKE2S_LOAD_MSG_6_4(buf) buf = VectorSet32<11,2,3,7>(m11,m2,m3,m7) + + #define BLAKE2S_LOAD_MSG_7_1(buf) buf = VectorSet32<3,12,7,13>(m3,m12,m7,m13) + #define BLAKE2S_LOAD_MSG_7_2(buf) buf = VectorSet32<9,1,14,11>(m9,m1,m14,m11) + #define BLAKE2S_LOAD_MSG_7_3(buf) buf = VectorSet32<2,8,15,5>(m2,m8,m15,m5) + #define BLAKE2S_LOAD_MSG_7_4(buf) buf = VectorSet32<10,6,4,0>(m10,m6,m4,m0) + + #define BLAKE2S_LOAD_MSG_8_1(buf) buf = VectorSet32<0,11,14,6>(m0,m11,m14,m6) + #define BLAKE2S_LOAD_MSG_8_2(buf) buf = VectorSet32<8,3,9,15>(m8,m3,m9,m15) + #define BLAKE2S_LOAD_MSG_8_3(buf) buf = VectorSet32<10,1,13,12>(m10,m1,m13,m12) + #define BLAKE2S_LOAD_MSG_8_4(buf) buf = VectorSet32<5,4,7,2>(m5,m4,m7,m2) + + #define BLAKE2S_LOAD_MSG_9_1(buf) buf = VectorSet32<1,7,8,10>(m1,m7,m8,m10) + #define BLAKE2S_LOAD_MSG_9_2(buf) buf = VectorSet32<5,6,4,2>(m5,m6,m4,m2) + #define BLAKE2S_LOAD_MSG_9_3(buf) buf = VectorSet32<13,3,9,15>(m13,m3,m9,m15) + #define BLAKE2S_LOAD_MSG_9_4(buf) buf = VectorSet32<0,12,14,11>(m0,m12,m14,m11) + + #define vec_ror_16(x) VecRotateRight<16>(x) + #define vec_ror_12(x) VecRotateRight<12>(x) + #define vec_ror_8(x) VecRotateRight<8>(x) + #define vec_ror_7(x) VecRotateRight<7>(x) + + #define BLAKE2S_G1(row1,row2,row3,row4,buf) \ + row1 = VecAdd(VecAdd(row1, buf), row2); \ + row4 = VecXor(row4, row1); \ + row4 = vec_ror_16(row4); \ + row3 = VecAdd(row3, row4); \ + row2 = VecXor(row2, row3); \ + row2 = vec_ror_12(row2); + + #define BLAKE2S_G2(row1,row2,row3,row4,buf) \ + row1 = VecAdd(VecAdd(row1, buf), row2); \ + row4 = VecXor(row4, row1); \ + row4 = vec_ror_8(row4); \ + row3 = VecAdd(row3, row4); \ + row2 = VecXor(row2, row3); \ + row2 = vec_ror_7(row2); + + const uint8x16_p D2103_MASK = {12,13,14,15, 0,1,2,3, 4,5,6,7, 8,9,10,11}; + const uint8x16_p D1032_MASK = {8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7}; + const uint8x16_p D0321_MASK = {4,5,6,7, 8,9,10,11, 12,13,14,15, 0,1,2,3}; + + #define BLAKE2S_DIAGONALIZE(row1,row2,row3,row4) \ + row4 = VecPermute(row4, row4, D2103_MASK); \ + row3 = VecPermute(row3, row3, D1032_MASK); \ + row2 = VecPermute(row2, row2, D0321_MASK); + + #define BLAKE2S_UNDIAGONALIZE(row1,row2,row3,row4) \ + row4 = VecPermute(row4, row4, D0321_MASK); \ + row3 = VecPermute(row3, row3, D1032_MASK); \ + row2 = VecPermute(row2, row2, D2103_MASK); + + #define BLAKE2S_ROUND(r) \ + BLAKE2S_LOAD_MSG_ ##r ##_1(buf1); \ + BLAKE2S_G1(row1,row2,row3,row4,buf1); \ + BLAKE2S_LOAD_MSG_ ##r ##_2(buf2); \ + BLAKE2S_G2(row1,row2,row3,row4,buf2); \ + BLAKE2S_DIAGONALIZE(row1,row2,row3,row4); \ + BLAKE2S_LOAD_MSG_ ##r ##_3(buf3); \ + BLAKE2S_G1(row1,row2,row3,row4,buf3); \ + BLAKE2S_LOAD_MSG_ ##r ##_4(buf4); \ + BLAKE2S_G2(row1,row2,row3,row4,buf4); \ + BLAKE2S_UNDIAGONALIZE(row1,row2,row3,row4); + + // Possibly unaligned user messages + uint32x4_p m0, m4, m8, m12; + // Endian conversion mask + const uint8x16_p le_mask = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12}; + +#if defined(_ARCH_PWR9) + // POWER9 provides loads for char's and short's + m0 = (uint32x4_p) vec_xl( 0, CONST_V8_CAST( input )); + m4 = (uint32x4_p) vec_xl( 16, CONST_V8_CAST( input )); + m8 = (uint32x4_p) vec_xl( 32, CONST_V8_CAST( input )); + m12 = (uint32x4_p) vec_xl( 48, CONST_V8_CAST( input )); + +# if defined(CRYPTOPP_BIG_ENDIAN) + m0 = vec_perm(m0, m0, le_mask); + m4 = vec_perm(m4, m4, le_mask); + m8 = vec_perm(m8, m8, le_mask); + m12 = vec_perm(m12, m12, le_mask); +# endif +#else + // Altivec only provides 16-byte aligned loads + // http://www.nxp.com/docs/en/reference-manual/ALTIVECPEM.pdf + m0 = (uint32x4_p) vec_ld( 0, CONST_V8_CAST( input )); + m4 = (uint32x4_p) vec_ld( 16, CONST_V8_CAST( input )); + m8 = (uint32x4_p) vec_ld( 32, CONST_V8_CAST( input )); + m12 = (uint32x4_p) vec_ld( 48, CONST_V8_CAST( input )); + + // Alignment check for load of the message buffer + const uintptr_t addr = (uintptr_t)input; + if (addr%16 == 0) + { + // Already aligned. Perform a little-endian swap as required +# if defined(CRYPTOPP_BIG_ENDIAN) + m0 = vec_perm(m0, m0, le_mask); + m4 = vec_perm(m4, m4, le_mask); + m8 = vec_perm(m8, m8, le_mask); + m12 = vec_perm(m12, m12, le_mask); +# endif + } + else + { + // Not aligned. Fix vectors and perform a little-endian swap as required + // http://mirror.informatimago.com/next/developer.apple.com/ + // hardwaredrivers/ve/code_optimization.html + uint32x4_p ex; uint8x16_p perm; + ex = (uint32x4_p) vec_ld(48+15, CONST_V8_CAST( input )); + perm = vec_lvsl(0, CONST_V8_CAST( addr )); + +# if defined(CRYPTOPP_BIG_ENDIAN) + // Combine the vector permute with the little-endian swap + perm = vec_perm(perm, perm, le_mask); +# endif + + m0 = vec_perm(m0, m4, perm); + m4 = vec_perm(m4, m8, perm); + m8 = vec_perm(m8, m12, perm); + m12 = vec_perm(m12, ex, perm); + } +#endif + + uint32x4_p row1, row2, row3, row4; + uint32x4_p buf1, buf2, buf3, buf4; + uint32x4_p ff0, ff1; + + row1 = ff0 = VecLoad32LE(state.h()+0, le_mask); + row2 = ff1 = VecLoad32LE(state.h()+4, le_mask); + row3 = VecLoad32(BLAKE2S_IV+0); + row4 = VecXor(VecLoad32(BLAKE2S_IV+4), VecLoad32(state.t()+0)); + + BLAKE2S_ROUND(0); + BLAKE2S_ROUND(1); + BLAKE2S_ROUND(2); + BLAKE2S_ROUND(3); + BLAKE2S_ROUND(4); + BLAKE2S_ROUND(5); + BLAKE2S_ROUND(6); + BLAKE2S_ROUND(7); + BLAKE2S_ROUND(8); + BLAKE2S_ROUND(9); + + VecStore32LE(state.h()+0, VecXor(ff0, VecXor(row1, row3)), le_mask); + VecStore32LE(state.h()+4, VecXor(ff1, VecXor(row2, row4)), le_mask); +} +#endif // CRYPTOPP_ALTIVEC_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/blowfish.cpp b/external/ours/library/crypto/src/shared/original/blowfish.cpp new file mode 100755 index 000000000..e615da3b6 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/blowfish.cpp @@ -0,0 +1,99 @@ +// blowfish.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "blowfish.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +void Blowfish::Base::UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs &) +{ + AssertValidKeyLength(keylength); + + unsigned i, j=0, k; + word32 data, dspace[2] = {0, 0}; + + memcpy(pbox, p_init, sizeof(p_init)); + memcpy(sbox, s_init, sizeof(s_init)); + + // Xor key string into encryption key vector + for (i=0 ; i Block; + + word32 left, right; + Block::Get(inBlock)(left)(right); + + const word32 *const s=sbox; + const word32 *p=pbox; + + left ^= p[0]; + + for (unsigned i=0; i, 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/external/ours/library/crypto/src/shared/original/blumshub.cpp b/external/ours/library/crypto/src/shared/original/blumshub.cpp new file mode 100755 index 000000000..7465d8da4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/blumshub.cpp @@ -0,0 +1,64 @@ +// blumshub.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "blumshub.h" +#include "integer.h" + +NAMESPACE_BEGIN(CryptoPP) + +PublicBlumBlumShub::PublicBlumBlumShub(const Integer &n, const Integer &seed) + : modn(n), + current(modn.Square(modn.Square(seed))), + maxBits(BitPrecision(n.BitCount())-1), + bitsLeft(maxBits) +{ +} + +unsigned int PublicBlumBlumShub::GenerateBit() +{ + if (bitsLeft==0) + { + current = modn.Square(current); + bitsLeft = maxBits; + } + + return static_cast(current.GetBit(--bitsLeft)); +} + +byte PublicBlumBlumShub::GenerateByte() +{ + byte b=0; + for (int i=0; i<8; i++) + b = byte((b << 1) | PublicBlumBlumShub::GenerateBit()); + return b; +} + +void PublicBlumBlumShub::GenerateBlock(byte *output, size_t size) +{ + while (size--) + *output++ = PublicBlumBlumShub::GenerateByte(); +} + +void PublicBlumBlumShub::ProcessData(byte *outString, const byte *inString, size_t length) +{ + while (length--) + *outString++ = *inString++ ^ PublicBlumBlumShub::GenerateByte(); +} + +BlumBlumShub::BlumBlumShub(const Integer &p, const Integer &q, const Integer &seed) + : PublicBlumBlumShub(p*q, seed), + p(p), q(q), + x0(modn.Square(seed)) +{ +} + +void BlumBlumShub::Seek(lword index) +{ + Integer i(Integer::POSITIVE, index); + i *= 8; + Integer e = a_exp_b_mod_c (2, i / maxBits + 1, (p-1)*(q-1)); + current = modn.Exponentiate(x0, e); + bitsLeft = maxBits - i % maxBits; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/blumshub.h b/external/ours/library/crypto/src/shared/original/blumshub.h new file mode 100755 index 000000000..8c1c981fd --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/camellia.cpp b/external/ours/library/crypto/src/shared/original/camellia.cpp new file mode 100755 index 000000000..30b8bc99c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/camellia.cpp @@ -0,0 +1,539 @@ +// camellia.cpp - by Kevin Springle, 2003 +// This code is hereby placed in the public domain. + +/* +Optimisations and defense against timing attacks added in Jan 2007 by Wei Dai. + +The first 2 rounds and the last round seem especially vulnerable to timing +attacks. The protection is similar to what was implemented for Rijndael. +See comments at top of rijndael.cpp for more details. +*/ + +#include "pch.h" +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4456) +# if (CRYPTOPP_MSC_VERSION >= 1400) +# pragma warning(disable: 6246) +# endif +#endif + +#include "camellia.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +// round implementation that uses a small table for protection against timing attacks +#define SLOW_ROUND(lh, ll, rh, rl, kh, kl) { \ + word32 zr = ll ^ kl; \ + word32 zl = lh ^ kh; \ + zr= rotlConstant<1>(s1[GETBYTE(zr, 3)]) | \ + (rotrConstant<1>(s1[GETBYTE(zr, 2)]) << 24) | \ + (s1[rotlConstant<1>(CRYPTOPP_GET_BYTE_AS_BYTE(zr, 1))] << 16) | \ + (s1[GETBYTE(zr, 0)] << 8); \ + zl= (s1[GETBYTE(zl, 3)] << 24) | \ + (rotlConstant<1>(s1[GETBYTE(zl, 2)]) << 16) | \ + (rotrConstant<1>(s1[GETBYTE(zl, 1)]) << 8) | \ + s1[rotlConstant<1>(CRYPTOPP_GET_BYTE_AS_BYTE(zl, 0))]; \ + zl ^= zr; \ + zr = zl ^ rotlConstant<8>(zr); \ + zl = zr ^ rotrConstant<8>(zl); \ + rh ^= rotlConstant<16>(zr); \ + rh ^= zl; \ + rl ^= rotlConstant<8>(zl); \ + } + +// normal round - same output as above but using larger tables for faster speed +#define ROUND(lh, ll, rh, rl, kh, kl) { \ + word32 th = lh ^ kh; \ + word32 tl = ll ^ kl; \ + word32 d = SP[0][GETBYTE(tl,0)] ^ SP[1][GETBYTE(tl,3)] ^ SP[2][GETBYTE(tl,2)] ^ SP[3][GETBYTE(tl,1)]; \ + word32 u = SP[0][GETBYTE(th,3)] ^ SP[1][GETBYTE(th,2)] ^ SP[2][GETBYTE(th,1)] ^ SP[3][GETBYTE(th,0)]; \ + d ^= u; \ + rh ^= d; \ + rl ^= d; \ + rl ^= rotrConstant<8>(u);} + +#define DOUBLE_ROUND(lh, ll, rh, rl, k0, k1, k2, k3) \ + ROUND(lh, ll, rh, rl, k0, k1) \ + ROUND(rh, rl, lh, ll, k2, k3) + +#if (CRYPTOPP_LITTLE_ENDIAN) +#define EFI(i) (1-(i)) +#else +#define EFI(i) (i) +#endif + +void Camellia::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs &) +{ + m_rounds = (keylen >= 24) ? 4 : 3; + unsigned int kslen = (8 * m_rounds + 2); + m_key.New(kslen*2); + word32 *ks32 = m_key.data(); + int m=0, a=0; + if (!IsForwardTransformation()) + m = -1, a = kslen-1; + + word32 kl0, kl1, kl2, kl3; + GetBlock getBlock(key); + getBlock(kl0)(kl1)(kl2)(kl3); + word32 k0=kl0, k1=kl1, k2=kl2, k3=kl3; + +#define CALC_ADDR2(base, i, j) ((byte *)(base)+8*(i)+4*(j)+((-16*(i))&m)) +#define CALC_ADDR(base, i) CALC_ADDR2(base, i, 0) + +#if 1 + word64 kwl, kwr; + ks32 += 2*a; +#define PREPARE_KS_ROUNDS \ + kwl = (word64(k0) << 32) | k1; \ + kwr = (word64(k2) << 32) | k3 +#define KS_ROUND_0(i) \ + CRYPTOPP_ASSERT(IsAlignedOn(CALC_ADDR(ks32, i+EFI(0)),GetAlignmentOf())); \ + CRYPTOPP_ASSERT(IsAlignedOn(CALC_ADDR(ks32, i+EFI(1)),GetAlignmentOf())); \ + *(word64*)(void*)CALC_ADDR(ks32, i+EFI(0)) = kwl; \ + *(word64*)(void*)CALC_ADDR(ks32, i+EFI(1)) = kwr +#define KS_ROUND(i, r, which) \ + CRYPTOPP_ASSERT(IsAlignedOn(CALC_ADDR(ks32, i+EFI(r<64)),GetAlignmentOf())); \ + CRYPTOPP_ASSERT(IsAlignedOn(CALC_ADDR(ks32, i+EFI(r>64)),GetAlignmentOf())); \ + if (which & (1<> (64 - (r%64))); \ + if (which & (1<64))) *(word64*)(void*)CALC_ADDR(ks32, i+EFI(r>64)) = (kwl << (r%64)) | (kwr >> (64 - (r%64))) +#else + // SSE2 version is 30% faster on Intel Core 2. Doesn't seem worth the hassle of maintenance, but left here + // #if'd out in case someone needs it. + __m128i kw, kw2; + __m128i *ks128 = (__m128i *)ks32+a/2; + ks32 += 2*a; +#define PREPARE_KS_ROUNDS \ + kw = _mm_set_epi32(k0, k1, k2, k3); \ + if (m) kw2 = kw, kw = _mm_shuffle_epi32(kw, _MM_SHUFFLE(1, 0, 3, 2)); \ + else kw2 = _mm_shuffle_epi32(kw, _MM_SHUFFLE(1, 0, 3, 2)) +#define KS_ROUND_0(i) \ + _mm_store_si128((__m128i *)CALC_ADDR(ks128, i), kw) +#define KS_ROUND(i, r, which) { \ + __m128i temp; \ + if (r<64 && (which!=1 || m)) temp = _mm_or_si128(_mm_slli_epi64(kw, r%64), _mm_srli_epi64(kw2, 64-r%64)); \ + else temp = _mm_or_si128(_mm_slli_epi64(kw2, r%64), _mm_srli_epi64(kw, 64-r%64)); \ + if (which & 2) _mm_store_si128((__m128i *)CALC_ADDR(ks128, i), temp); \ + else _mm_storel_epi64((__m128i*)CALC_ADDR(ks32, i+EFI(0)), temp); \ + } +#endif + + if (keylen == 16) + { + // KL + PREPARE_KS_ROUNDS; + KS_ROUND_0(0); + KS_ROUND(4, 15, 3); + KS_ROUND(10, 45, 3); + KS_ROUND(12, 60, 2); + KS_ROUND(16, 77, 3); + KS_ROUND(18, 94, 3); + KS_ROUND(22, 111, 3); + + // KA + k0=kl0, k1=kl1, k2=kl2, k3=kl3; + DOUBLE_ROUND(k0, k1, k2, k3, 0xA09E667Ful, 0x3BCC908Bul, 0xB67AE858ul, 0x4CAA73B2ul); + k0^=kl0, k1^=kl1, k2^=kl2, k3^=kl3; + DOUBLE_ROUND(k0, k1, k2, k3, 0xC6EF372Ful, 0xE94F82BEul, 0x54FF53A5ul, 0xF1D36F1Cul); + + PREPARE_KS_ROUNDS; + KS_ROUND_0(2); + KS_ROUND(6, 15, 3); + KS_ROUND(8, 30, 3); + KS_ROUND(12, 45, 1); + KS_ROUND(14, 60, 3); + KS_ROUND(20, 94, 3); + KS_ROUND(24, 47, 3); + } + else + { + // KL + PREPARE_KS_ROUNDS; + KS_ROUND_0(0); + KS_ROUND(12, 45, 3); + KS_ROUND(16, 60, 3); + KS_ROUND(22, 77, 3); + KS_ROUND(30, 111, 3); + + // KR + word32 kr0, kr1, kr2, kr3; + GetBlock(key+16)(kr0)(kr1); + if (keylen == 24) + kr2 = ~kr0, kr3 = ~kr1; + else + GetBlock(key+24)(kr2)(kr3); + k0=kr0, k1=kr1, k2=kr2, k3=kr3; + + PREPARE_KS_ROUNDS; + KS_ROUND(4, 15, 3); + KS_ROUND(8, 30, 3); + KS_ROUND(18, 60, 3); + KS_ROUND(26, 94, 3); + + // KA + k0^=kl0, k1^=kl1, k2^=kl2, k3^=kl3; + DOUBLE_ROUND(k0, k1, k2, k3, 0xA09E667Ful, 0x3BCC908Bul, 0xB67AE858ul, 0x4CAA73B2ul); + k0^=kl0, k1^=kl1, k2^=kl2, k3^=kl3; + DOUBLE_ROUND(k0, k1, k2, k3, 0xC6EF372Ful, 0xE94F82BEul, 0x54FF53A5ul, 0xF1D36F1Cul); + + PREPARE_KS_ROUNDS; + KS_ROUND(6, 15, 3); + KS_ROUND(14, 45, 3); + KS_ROUND(24, 77, 3); + KS_ROUND(28, 94, 3); + + // KB + k0^=kr0, k1^=kr1, k2^=kr2, k3^=kr3; + DOUBLE_ROUND(k0, k1, k2, k3, 0x10E527FAul, 0xDE682D1Dul, 0xB05688C2ul, 0xB3E6C1FDul); + + PREPARE_KS_ROUNDS; + KS_ROUND_0(2); + KS_ROUND(10, 30, 3); + KS_ROUND(20, 60, 3); + KS_ROUND(32, 47, 3); + } +} + +void Camellia::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ +#define KS(i, j) ks[i*4 + EFI(j/2)*2 + EFI(j%2)] + +#define FL(klh, kll, krh, krl) \ + ll ^= rotlConstant<1>(lh & klh);\ + lh ^= (ll | kll); \ + rh ^= (rl | krl); \ + rl ^= rotlConstant<1>(rh & krh); + + word32 lh, ll, rh, rl; + typedef BlockGetAndPut Block; + Block::Get(inBlock)(lh)(ll)(rh)(rl); + const word32 *ks = m_key.data(); + lh ^= KS(0,0); + ll ^= KS(0,1); + rh ^= KS(0,2); + rl ^= KS(0,3); + + // Timing attack countermeasure. see comments in Rijndael for more details + const int cacheLineSize = GetCacheLineSize(); + unsigned int i; + volatile word32 _u = 0; + word32 u = _u; + + for (i=0; i<256; i+=cacheLineSize) + u &= *(const word32 *)(void*)(s1+i); + u &= *(const word32 *)(void*)(s1+252); + lh |= u; ll |= u; + + SLOW_ROUND(lh, ll, rh, rl, KS(1,0), KS(1,1)) + SLOW_ROUND(rh, rl, lh, ll, KS(1,2), KS(1,3)) + for (i = m_rounds-1; i > 0; --i) + { + DOUBLE_ROUND(lh, ll, rh, rl, KS(2,0), KS(2,1), KS(2,2), KS(2,3)) + DOUBLE_ROUND(lh, ll, rh, rl, KS(3,0), KS(3,1), KS(3,2), KS(3,3)) + FL(KS(4,0), KS(4,1), KS(4,2), KS(4,3)); + DOUBLE_ROUND(lh, ll, rh, rl, KS(5,0), KS(5,1), KS(5,2), KS(5,3)) + ks += 16; + } + DOUBLE_ROUND(lh, ll, rh, rl, KS(2,0), KS(2,1), KS(2,2), KS(2,3)) + ROUND(lh, ll, rh, rl, KS(3,0), KS(3,1)) + SLOW_ROUND(rh, rl, lh, ll, KS(3,2), KS(3,3)) + lh ^= KS(4,0); + ll ^= KS(4,1); + rh ^= KS(4,2); + rl ^= KS(4,3); + Block::Put(xorBlock, outBlock)(rh)(rl)(lh)(ll); +} + +// The Camellia s-boxes + +CRYPTOPP_ALIGN_DATA(4) +const byte Camellia::Base::s1[256] = +{ + 112,130,44,236,179,39,192,229,228,133,87,53,234,12,174,65, + 35,239,107,147,69,25,165,33,237,14,79,78,29,101,146,189, + 134,184,175,143,124,235,31,206,62,48,220,95,94,197,11,26, + 166,225,57,202,213,71,93,61,217,1,90,214,81,86,108,77, + 139,13,154,102,251,204,176,45,116,18,43,32,240,177,132,153, + 223,76,203,194,52,126,118,5,109,183,169,49,209,23,4,215, + 20,88,58,97,222,27,17,28,50,15,156,22,83,24,242,34, + 254,68,207,178,195,181,122,145,36,8,232,168,96,252,105,80, + 170,208,160,125,161,137,98,151,84,91,30,149,224,255,100,210, + 16,196,0,72,163,247,117,219,138,3,230,218,9,63,221,148, + 135,92,131,2,205,74,144,51,115,103,246,243,157,127,191,226, + 82,155,216,38,200,55,198,59,129,150,111,75,19,190,99,46, + 233,121,167,140,159,110,188,142,41,245,249,182,47,253,180,89, + 120,152,6,106,231,70,113,186,212,37,171,66,136,162,141,250, + 114,7,185,85,248,238,172,10,54,73,42,104,60,56,241,164, + 64,40,211,123,187,201,67,193,21,227,173,244,119,199,128,158 +}; + +const word32 Camellia::Base::SP[4][256] = { + { + 0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, + 0xb3b3b300, 0x27272700, 0xc0c0c000, 0xe5e5e500, + 0xe4e4e400, 0x85858500, 0x57575700, 0x35353500, + 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, + 0x23232300, 0xefefef00, 0x6b6b6b00, 0x93939300, + 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100, + 0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, + 0x1d1d1d00, 0x65656500, 0x92929200, 0xbdbdbd00, + 0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00, + 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, + 0x3e3e3e00, 0x30303000, 0xdcdcdc00, 0x5f5f5f00, + 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00, + 0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, + 0xd5d5d500, 0x47474700, 0x5d5d5d00, 0x3d3d3d00, + 0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600, + 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, + 0x8b8b8b00, 0x0d0d0d00, 0x9a9a9a00, 0x66666600, + 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00, + 0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, + 0xf0f0f000, 0xb1b1b100, 0x84848400, 0x99999900, + 0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200, + 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, + 0x6d6d6d00, 0xb7b7b700, 0xa9a9a900, 0x31313100, + 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700, + 0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, + 0xdedede00, 0x1b1b1b00, 0x11111100, 0x1c1c1c00, + 0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600, + 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, + 0xfefefe00, 0x44444400, 0xcfcfcf00, 0xb2b2b200, + 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100, + 0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, + 0x60606000, 0xfcfcfc00, 0x69696900, 0x50505000, + 0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00, + 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, + 0x54545400, 0x5b5b5b00, 0x1e1e1e00, 0x95959500, + 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200, + 0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, + 0xa3a3a300, 0xf7f7f700, 0x75757500, 0xdbdbdb00, + 0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00, + 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, + 0x87878700, 0x5c5c5c00, 0x83838300, 0x02020200, + 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300, + 0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, + 0x9d9d9d00, 0x7f7f7f00, 0xbfbfbf00, 0xe2e2e200, + 0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600, + 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, + 0x81818100, 0x96969600, 0x6f6f6f00, 0x4b4b4b00, + 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00, + 0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, + 0x9f9f9f00, 0x6e6e6e00, 0xbcbcbc00, 0x8e8e8e00, + 0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600, + 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, + 0x78787800, 0x98989800, 0x06060600, 0x6a6a6a00, + 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00, + 0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, + 0x88888800, 0xa2a2a200, 0x8d8d8d00, 0xfafafa00, + 0x72727200, 0x07070700, 0xb9b9b900, 0x55555500, + 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, + 0x36363600, 0x49494900, 0x2a2a2a00, 0x68686800, + 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400, + 0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, + 0xbbbbbb00, 0xc9c9c900, 0x43434300, 0xc1c1c100, + 0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400, + 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00 + }, + { + 0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, + 0x00676767, 0x004e4e4e, 0x00818181, 0x00cbcbcb, + 0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a, + 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, + 0x00464646, 0x00dfdfdf, 0x00d6d6d6, 0x00272727, + 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242, + 0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, + 0x003a3a3a, 0x00cacaca, 0x00252525, 0x007b7b7b, + 0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f, + 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, + 0x007c7c7c, 0x00606060, 0x00b9b9b9, 0x00bebebe, + 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434, + 0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, + 0x00ababab, 0x008e8e8e, 0x00bababa, 0x007a7a7a, + 0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad, + 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, + 0x00171717, 0x001a1a1a, 0x00353535, 0x00cccccc, + 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a, + 0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, + 0x00e1e1e1, 0x00636363, 0x00090909, 0x00333333, + 0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585, + 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, + 0x00dadada, 0x006f6f6f, 0x00535353, 0x00626262, + 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf, + 0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, + 0x00bdbdbd, 0x00363636, 0x00222222, 0x00383838, + 0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c, + 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, + 0x00fdfdfd, 0x00888888, 0x009f9f9f, 0x00656565, + 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323, + 0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, + 0x00c0c0c0, 0x00f9f9f9, 0x00d2d2d2, 0x00a0a0a0, + 0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa, + 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, + 0x00a8a8a8, 0x00b6b6b6, 0x003c3c3c, 0x002b2b2b, + 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5, + 0x00202020, 0x00898989, 0x00000000, 0x00909090, + 0x00474747, 0x00efefef, 0x00eaeaea, 0x00b7b7b7, + 0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5, + 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, + 0x000f0f0f, 0x00b8b8b8, 0x00070707, 0x00040404, + 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666, + 0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, + 0x003b3b3b, 0x00fefefe, 0x007f7f7f, 0x00c5c5c5, + 0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c, + 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, + 0x00030303, 0x002d2d2d, 0x00dedede, 0x00969696, + 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c, + 0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, + 0x003f3f3f, 0x00dcdcdc, 0x00797979, 0x001d1d1d, + 0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d, + 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, + 0x00f0f0f0, 0x00313131, 0x000c0c0c, 0x00d4d4d4, + 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575, + 0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, + 0x00111111, 0x00454545, 0x001b1b1b, 0x00f5f5f5, + 0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa, + 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, + 0x006c6c6c, 0x00929292, 0x00545454, 0x00d0d0d0, + 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949, + 0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, + 0x00777777, 0x00939393, 0x00868686, 0x00838383, + 0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9, + 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d + }, + { + 0x38003838, 0x41004141, 0x16001616, 0x76007676, + 0xd900d9d9, 0x93009393, 0x60006060, 0xf200f2f2, + 0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a, + 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, + 0x91009191, 0xf700f7f7, 0xb500b5b5, 0xc900c9c9, + 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090, + 0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, + 0x8e008e8e, 0xb200b2b2, 0x49004949, 0xde00dede, + 0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7, + 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, + 0x1f001f1f, 0x18001818, 0x6e006e6e, 0xaf00afaf, + 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d, + 0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, + 0xea00eaea, 0xa300a3a3, 0xae00aeae, 0x9e009e9e, + 0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b, + 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, + 0xc500c5c5, 0x86008686, 0x4d004d4d, 0x33003333, + 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696, + 0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, + 0x78007878, 0xd800d8d8, 0x42004242, 0xcc00cccc, + 0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161, + 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, + 0xb600b6b6, 0xdb00dbdb, 0xd400d4d4, 0x98009898, + 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb, + 0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, + 0x6f006f6f, 0x8d008d8d, 0x88008888, 0x0e000e0e, + 0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b, + 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, + 0x7f007f7f, 0x22002222, 0xe700e7e7, 0x59005959, + 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8, + 0x12001212, 0x04000404, 0x74007474, 0x54005454, + 0x30003030, 0x7e007e7e, 0xb400b4b4, 0x28002828, + 0x55005555, 0x68006868, 0x50005050, 0xbe00bebe, + 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, + 0x2a002a2a, 0xad00adad, 0x0f000f0f, 0xca00caca, + 0x70007070, 0xff00ffff, 0x32003232, 0x69006969, + 0x08000808, 0x62006262, 0x00000000, 0x24002424, + 0xd100d1d1, 0xfb00fbfb, 0xba00baba, 0xed00eded, + 0x45004545, 0x81008181, 0x73007373, 0x6d006d6d, + 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, + 0xc300c3c3, 0x2e002e2e, 0xc100c1c1, 0x01000101, + 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999, + 0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, + 0xce00cece, 0xbf00bfbf, 0xdf00dfdf, 0x71007171, + 0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313, + 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, + 0xc000c0c0, 0x4b004b4b, 0xb700b7b7, 0xa500a5a5, + 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717, + 0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, + 0xcf00cfcf, 0x37003737, 0x5e005e5e, 0x47004747, + 0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b, + 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, + 0x3c003c3c, 0x4c004c4c, 0x03000303, 0x35003535, + 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d, + 0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, + 0x44004444, 0x51005151, 0xc600c6c6, 0x7d007d7d, + 0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa, + 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, + 0x1b001b1b, 0xa400a4a4, 0x15001515, 0x34003434, + 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252, + 0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, + 0xdd00dddd, 0xe400e4e4, 0xa100a1a1, 0xe000e0e0, + 0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a, + 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f + }, + { + 0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, + 0xe4e400e4, 0x57570057, 0xeaea00ea, 0xaeae00ae, + 0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5, + 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, + 0x86860086, 0xafaf00af, 0x7c7c007c, 0x1f1f001f, + 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b, + 0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, + 0xd9d900d9, 0x5a5a005a, 0x51510051, 0x6c6c006c, + 0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0, + 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, + 0xdfdf00df, 0xcbcb00cb, 0x34340034, 0x76760076, + 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004, + 0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, + 0x32320032, 0x9c9c009c, 0x53530053, 0xf2f200f2, + 0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a, + 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, + 0xaaaa00aa, 0xa0a000a0, 0xa1a100a1, 0x62620062, + 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064, + 0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, + 0x8a8a008a, 0xe6e600e6, 0x09090009, 0xdddd00dd, + 0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090, + 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, + 0x52520052, 0xd8d800d8, 0xc8c800c8, 0xc6c600c6, + 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063, + 0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, + 0x29290029, 0xf9f900f9, 0x2f2f002f, 0xb4b400b4, + 0x78780078, 0x06060006, 0xe7e700e7, 0x71710071, + 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, + 0x72720072, 0xb9b900b9, 0xf8f800f8, 0xacac00ac, + 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1, + 0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, + 0x15150015, 0xadad00ad, 0x77770077, 0x80800080, + 0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5, + 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, + 0xefef00ef, 0x93930093, 0x19190019, 0x21210021, + 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd, + 0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, + 0x30300030, 0x5f5f005f, 0xc5c500c5, 0x1a1a001a, + 0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d, + 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, + 0x0d0d000d, 0x66660066, 0xcccc00cc, 0x2d2d002d, + 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099, + 0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, + 0xb7b700b7, 0x31310031, 0x17170017, 0xd7d700d7, + 0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c, + 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, + 0x44440044, 0xb2b200b2, 0xb5b500b5, 0x91910091, + 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050, + 0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, + 0x5b5b005b, 0x95950095, 0xffff00ff, 0xd2d200d2, + 0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db, + 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, + 0x5c5c005c, 0x02020002, 0x4a4a004a, 0x33330033, + 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2, + 0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, + 0x96960096, 0x4b4b004b, 0xbebe00be, 0x2e2e002e, + 0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e, + 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, + 0x98980098, 0x6a6a006a, 0x46460046, 0xbaba00ba, + 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa, + 0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, + 0x49490049, 0x68680068, 0x38380038, 0xa4a400a4, + 0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1, + 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e + }}; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/camellia.h b/external/ours/library/crypto/src/shared/original/camellia.h new file mode 100755 index 000000000..e83a20608 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/cast.cpp b/external/ours/library/crypto/src/shared/original/cast.cpp new file mode 100755 index 000000000..a63e3f8b9 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/cast.cpp @@ -0,0 +1,292 @@ +// cast.cpp - originally written and placed in the public domain by Wei Dai and Leonard Janke +// based on Steve Reid's public domain cast.c + +#include "pch.h" +#include "cast.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/* Macros to access 8-bit bytes out of a 32-bit word */ +#define U8a(x) GETBYTE(x,3) +#define U8b(x) GETBYTE(x,2) +#define U8c(x) GETBYTE(x,1) +#define U8d(x) GETBYTE(x,0) + +/* CAST uses three different round functions */ +#define f1(l, r, km, kr) \ + t = rotlVariable(km + r, kr); \ + l ^= ((S[0][U8a(t)] ^ S[1][U8b(t)]) - \ + S[2][U8c(t)]) + S[3][U8d(t)]; +#define f2(l, r, km, kr) \ + t = rotlVariable(km ^ r, kr); \ + l ^= ((S[0][U8a(t)] - S[1][U8b(t)]) + \ + S[2][U8c(t)]) ^ S[3][U8d(t)]; +#define f3(l, r, km, kr) \ + t = rotlVariable(km - r, kr); \ + l ^= ((S[0][U8a(t)] + S[1][U8b(t)]) ^ \ + S[2][U8c(t)]) - S[3][U8d(t)]; + +#define F1(l, r, i, j) f1(l, r, K[i], K[i+j]) +#define F2(l, r, i, j) f2(l, r, K[i], K[i+j]) +#define F3(l, r, i, j) f3(l, r, K[i], K[i+j]) + +typedef BlockGetAndPut Block; + +void CAST128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 &t=m_t[0], &l=m_t[1], &r=m_t[2]; + + /* Get inblock into l,r */ + Block::Get(inBlock)(l)(r); + /* Do the work */ + F1(l, r, 0, 16); + F2(r, l, 1, 16); + F3(l, r, 2, 16); + F1(r, l, 3, 16); + F2(l, r, 4, 16); + F3(r, l, 5, 16); + F1(l, r, 6, 16); + F2(r, l, 7, 16); + F3(l, r, 8, 16); + F1(r, l, 9, 16); + F2(l, r, 10, 16); + F3(r, l, 11, 16); + /* Only do full 16 rounds if key length > 80 bits */ + if (!reduced) { + F1(l, r, 12, 16); + F2(r, l, 13, 16); + F3(l, r, 14, 16); + F1(r, l, 15, 16); + } + /* Put l,r into outblock */ + Block::Put(xorBlock, outBlock)(r)(l); +} + +void CAST128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 &t=m_t[0], &l=m_t[1], &r=m_t[2]; + + /* Get inblock into l,r */ + Block::Get(inBlock)(r)(l); + /* Only do full 16 rounds if key length > 80 bits */ + if (!reduced) { + F1(r, l, 15, 16); + F3(l, r, 14, 16); + F2(r, l, 13, 16); + F1(l, r, 12, 16); + } + F3(r, l, 11, 16); + F2(l, r, 10, 16); + F1(r, l, 9, 16); + F3(l, r, 8, 16); + F2(r, l, 7, 16); + F1(l, r, 6, 16); + F3(r, l, 5, 16); + F2(l, r, 4, 16); + F1(r, l, 3, 16); + F3(l, r, 2, 16); + F2(r, l, 1, 16); + F1(l, r, 0, 16); + /* Put l,r into outblock */ + Block::Put(xorBlock, outBlock)(l)(r); +} + +void CAST128::Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &) +{ + AssertValidKeyLength(keylength); + + reduced = (keylength <= 10); + + word32 X[4], Z[4]={0}; + GetUserKey(BIG_ENDIAN_ORDER, X, 4, userKey, keylength); + +#define x(i) GETBYTE(X[i/4], 3-i%4) +#define z(i) GETBYTE(Z[i/4], 3-i%4) + + unsigned int i; + for (i=0; i<=16; i+=16) + { + // this part is copied directly from RFC 2144 (with some search and replace) by Wei Dai + Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)]; + Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)]; + Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)]; + Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)]; + K[i+0] = S[4][z(0x8)] ^ S[5][z(0x9)] ^ S[6][z(0x7)] ^ S[7][z(0x6)] ^ S[4][z(0x2)]; + K[i+1] = S[4][z(0xA)] ^ S[5][z(0xB)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[5][z(0x6)]; + K[i+2] = S[4][z(0xC)] ^ S[5][z(0xD)] ^ S[6][z(0x3)] ^ S[7][z(0x2)] ^ S[6][z(0x9)]; + K[i+3] = S[4][z(0xE)] ^ S[5][z(0xF)] ^ S[6][z(0x1)] ^ S[7][z(0x0)] ^ S[7][z(0xC)]; + X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)]; + X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)]; + X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)]; + X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)]; + K[i+4] = S[4][x(0x3)] ^ S[5][x(0x2)] ^ S[6][x(0xC)] ^ S[7][x(0xD)] ^ S[4][x(0x8)]; + K[i+5] = S[4][x(0x1)] ^ S[5][x(0x0)] ^ S[6][x(0xE)] ^ S[7][x(0xF)] ^ S[5][x(0xD)]; + K[i+6] = S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x8)] ^ S[7][x(0x9)] ^ S[6][x(0x3)]; + K[i+7] = S[4][x(0x5)] ^ S[5][x(0x4)] ^ S[6][x(0xA)] ^ S[7][x(0xB)] ^ S[7][x(0x7)]; + Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)]; + Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)]; + Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)]; + Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)]; + K[i+8] = S[4][z(0x3)] ^ S[5][z(0x2)] ^ S[6][z(0xC)] ^ S[7][z(0xD)] ^ S[4][z(0x9)]; + K[i+9] = S[4][z(0x1)] ^ S[5][z(0x0)] ^ S[6][z(0xE)] ^ S[7][z(0xF)] ^ S[5][z(0xC)]; + K[i+10] = S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x8)] ^ S[7][z(0x9)] ^ S[6][z(0x2)]; + K[i+11] = S[4][z(0x5)] ^ S[5][z(0x4)] ^ S[6][z(0xA)] ^ S[7][z(0xB)] ^ S[7][z(0x6)]; + X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)]; + X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)]; + X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)]; + X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)]; + K[i+12] = S[4][x(0x8)] ^ S[5][x(0x9)] ^ S[6][x(0x7)] ^ S[7][x(0x6)] ^ S[4][x(0x3)]; + K[i+13] = S[4][x(0xA)] ^ S[5][x(0xB)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[5][x(0x7)]; + K[i+14] = S[4][x(0xC)] ^ S[5][x(0xD)] ^ S[6][x(0x3)] ^ S[7][x(0x2)] ^ S[6][x(0x8)]; + K[i+15] = S[4][x(0xE)] ^ S[5][x(0xF)] ^ S[6][x(0x1)] ^ S[7][x(0x0)] ^ S[7][x(0xD)]; + } + + for (i=16; i<32; i++) + K[i] &= 0x1f; +} + +// The following CAST-256 implementation was contributed by Leonard Janke + +const word32 CAST256::Base::t_m[8][24]={ +{ 0x5a827999, 0xd151d6a1, 0x482133a9, 0xbef090b1, 0x35bfedb9, 0xac8f4ac1, + 0x235ea7c9, 0x9a2e04d1, 0x10fd61d9, 0x87ccbee1, 0xfe9c1be9, 0x756b78f1, + 0xec3ad5f9, 0x630a3301, 0xd9d99009, 0x50a8ed11, 0xc7784a19, 0x3e47a721, + 0xb5170429, 0x2be66131, 0xa2b5be39, 0x19851b41, 0x90547849, 0x0723d551}, +{ 0xc95c653a, 0x402bc242, 0xb6fb1f4a, 0x2dca7c52, 0xa499d95a, 0x1b693662, + 0x9238936a, 0x0907f072, 0x7fd74d7a, 0xf6a6aa82, 0x6d76078a, 0xe4456492, + 0x5b14c19a, 0xd1e41ea2, 0x48b37baa, 0xbf82d8b2, 0x365235ba, 0xad2192c2, + 0x23f0efca, 0x9ac04cd2, 0x118fa9da, 0x885f06e2, 0xff2e63ea, 0x75fdc0f2}, +{ 0x383650db, 0xaf05ade3, 0x25d50aeb, 0x9ca467f3, 0x1373c4fb, 0x8a432203, + 0x01127f0b, 0x77e1dc13, 0xeeb1391b, 0x65809623, 0xdc4ff32b, 0x531f5033, + 0xc9eead3b, 0x40be0a43, 0xb78d674b, 0x2e5cc453, 0xa52c215b, 0x1bfb7e63, + 0x92cadb6b, 0x099a3873, 0x8069957b, 0xf738f283, 0x6e084f8b, 0xe4d7ac93}, +{ 0xa7103c7c, 0x1ddf9984, 0x94aef68c, 0x0b7e5394, 0x824db09c, 0xf91d0da4, + 0x6fec6aac, 0xe6bbc7b4, 0x5d8b24bc, 0xd45a81c4, 0x4b29decc, 0xc1f93bd4, + 0x38c898dc, 0xaf97f5e4, 0x266752ec, 0x9d36aff4, 0x14060cfc, 0x8ad56a04, + 0x01a4c70c, 0x78742414, 0xef43811c, 0x6612de24, 0xdce23b2c, 0x53b19834}, +{ 0x15ea281d, 0x8cb98525, 0x0388e22d, 0x7a583f35, 0xf1279c3d, 0x67f6f945, + 0xdec6564d, 0x5595b355, 0xcc65105d, 0x43346d65, 0xba03ca6d, 0x30d32775, + 0xa7a2847d, 0x1e71e185, 0x95413e8d, 0x0c109b95, 0x82dff89d, 0xf9af55a5, + 0x707eb2ad, 0xe74e0fb5, 0x5e1d6cbd, 0xd4ecc9c5, 0x4bbc26cd, 0xc28b83d5}, +{ 0x84c413be, 0xfb9370c6, 0x7262cdce, 0xe9322ad6, 0x600187de, 0xd6d0e4e6, + 0x4da041ee, 0xc46f9ef6, 0x3b3efbfe, 0xb20e5906, 0x28ddb60e, 0x9fad1316, + 0x167c701e, 0x8d4bcd26, 0x041b2a2e, 0x7aea8736, 0xf1b9e43e, 0x68894146, + 0xdf589e4e, 0x5627fb56, 0xccf7585e, 0x43c6b566, 0xba96126e, 0x31656f76}, +{ 0xf39dff5f, 0x6a6d5c67, 0xe13cb96f, 0x580c1677, 0xcedb737f, 0x45aad087, + 0xbc7a2d8f, 0x33498a97, 0xaa18e79f, 0x20e844a7, 0x97b7a1af, 0x0e86feb7, + 0x85565bbf, 0xfc25b8c7, 0x72f515cf, 0xe9c472d7, 0x6093cfdf, 0xd7632ce7, + 0x4e3289ef, 0xc501e6f7, 0x3bd143ff, 0xb2a0a107, 0x296ffe0f, 0xa03f5b17}, +{ 0x6277eb00, 0xd9474808, 0x5016a510, 0xc6e60218, 0x3db55f20, 0xb484bc28, + 0x2b541930, 0xa2237638, 0x18f2d340, 0x8fc23048, 0x06918d50, 0x7d60ea58, + 0xf4304760, 0x6affa468, 0xe1cf0170, 0x589e5e78, 0xcf6dbb80, 0x463d1888, + 0xbd0c7590, 0x33dbd298, 0xaaab2fa0, 0x217a8ca8, 0x9849e9b0, 0x0f1946b8} +}; + +const unsigned int CAST256::Base::t_r[8][24]={ + {19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11}, + {4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28}, + {21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13}, + {6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30}, + {23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15}, + {8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0}, + {25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17}, + {10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2} +}; + +#define Q(i) \ + F1(block[2],block[3],8*i+4,-4); \ + F2(block[1],block[2],8*i+5,-4); \ + F3(block[0],block[1],8*i+6,-4); \ + F1(block[3],block[0],8*i+7,-4); + +#define QBar(i) \ + F1(block[3],block[0],8*i+7,-4); \ + F3(block[0],block[1],8*i+6,-4); \ + F2(block[1],block[2],8*i+5,-4); \ + F1(block[2],block[3],8*i+4,-4); + +/* CAST256's encrypt/decrypt functions are identical except for the order that +the keys are used */ + +void CAST256::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // TODO: add a SecBlock workspace to the class when the ABI can change + word32 t, block[4]; + Block::Get(inBlock)(block[0])(block[1])(block[2])(block[3]); + + // Perform 6 forward quad rounds + Q(0); + Q(1); + Q(2); + Q(3); + Q(4); + Q(5); + + // Perform 6 reverse quad rounds + QBar(6); + QBar(7); + QBar(8); + QBar(9); + QBar(10); + QBar(11); + + Block::Put(xorBlock, outBlock)(block[0])(block[1])(block[2])(block[3]); +} + +/* Set up a CAST-256 key */ + +void CAST256::Base::Omega(int i, word32 kappa[8]) +{ + word32 t; + + f1(kappa[6],kappa[7],t_m[0][i],t_r[0][i]); + f2(kappa[5],kappa[6],t_m[1][i],t_r[1][i]); + f3(kappa[4],kappa[5],t_m[2][i],t_r[2][i]); + f1(kappa[3],kappa[4],t_m[3][i],t_r[3][i]); + f2(kappa[2],kappa[3],t_m[4][i],t_r[4][i]); + f3(kappa[1],kappa[2],t_m[5][i],t_r[5][i]); + f1(kappa[0],kappa[1],t_m[6][i],t_r[6][i]); + f2(kappa[7],kappa[0],t_m[7][i],t_r[7][i]); +} + +void CAST256::Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &) +{ + AssertValidKeyLength(keylength); + + GetUserKey(BIG_ENDIAN_ORDER, kappa.begin(), 8, userKey, keylength); + + for(int i=0; i<12; ++i) + { + Omega(2*i,kappa); + Omega(2*i+1,kappa); + + K[8*i]=kappa[0] & 31; + K[8*i+1]=kappa[2] & 31; + K[8*i+2]=kappa[4] & 31; + K[8*i+3]=kappa[6] & 31; + K[8*i+4]=kappa[7]; + K[8*i+5]=kappa[5]; + K[8*i+6]=kappa[3]; + K[8*i+7]=kappa[1]; + } + + if (!IsForwardTransformation()) + { + for(int j=0; j<6; ++j) + { + for(int i=0; i<4; ++i) + { + int i1=8*j+i; + int i2=8*(11-j)+i; + + CRYPTOPP_ASSERT(i1, 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/external/ours/library/crypto/src/shared/original/casts.cpp b/external/ours/library/crypto/src/shared/original/casts.cpp new file mode 100755 index 000000000..d823d725c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/casts.cpp @@ -0,0 +1,545 @@ +#include "pch.h" +#include "cast.h" + +NAMESPACE_BEGIN(CryptoPP) + +// CAST S-boxes + +const word32 CAST::S[8][256] = { +{ + 0x30FB40D4UL, 0x9FA0FF0BUL, 0x6BECCD2FUL, 0x3F258C7AUL, + 0x1E213F2FUL, 0x9C004DD3UL, 0x6003E540UL, 0xCF9FC949UL, + 0xBFD4AF27UL, 0x88BBBDB5UL, 0xE2034090UL, 0x98D09675UL, + 0x6E63A0E0UL, 0x15C361D2UL, 0xC2E7661DUL, 0x22D4FF8EUL, + 0x28683B6FUL, 0xC07FD059UL, 0xFF2379C8UL, 0x775F50E2UL, + 0x43C340D3UL, 0xDF2F8656UL, 0x887CA41AUL, 0xA2D2BD2DUL, + 0xA1C9E0D6UL, 0x346C4819UL, 0x61B76D87UL, 0x22540F2FUL, + 0x2ABE32E1UL, 0xAA54166BUL, 0x22568E3AUL, 0xA2D341D0UL, + 0x66DB40C8UL, 0xA784392FUL, 0x004DFF2FUL, 0x2DB9D2DEUL, + 0x97943FACUL, 0x4A97C1D8UL, 0x527644B7UL, 0xB5F437A7UL, + 0xB82CBAEFUL, 0xD751D159UL, 0x6FF7F0EDUL, 0x5A097A1FUL, + 0x827B68D0UL, 0x90ECF52EUL, 0x22B0C054UL, 0xBC8E5935UL, + 0x4B6D2F7FUL, 0x50BB64A2UL, 0xD2664910UL, 0xBEE5812DUL, + 0xB7332290UL, 0xE93B159FUL, 0xB48EE411UL, 0x4BFF345DUL, + 0xFD45C240UL, 0xAD31973FUL, 0xC4F6D02EUL, 0x55FC8165UL, + 0xD5B1CAADUL, 0xA1AC2DAEUL, 0xA2D4B76DUL, 0xC19B0C50UL, + 0x882240F2UL, 0x0C6E4F38UL, 0xA4E4BFD7UL, 0x4F5BA272UL, + 0x564C1D2FUL, 0xC59C5319UL, 0xB949E354UL, 0xB04669FEUL, + 0xB1B6AB8AUL, 0xC71358DDUL, 0x6385C545UL, 0x110F935DUL, + 0x57538AD5UL, 0x6A390493UL, 0xE63D37E0UL, 0x2A54F6B3UL, + 0x3A787D5FUL, 0x6276A0B5UL, 0x19A6FCDFUL, 0x7A42206AUL, + 0x29F9D4D5UL, 0xF61B1891UL, 0xBB72275EUL, 0xAA508167UL, + 0x38901091UL, 0xC6B505EBUL, 0x84C7CB8CUL, 0x2AD75A0FUL, + 0x874A1427UL, 0xA2D1936BUL, 0x2AD286AFUL, 0xAA56D291UL, + 0xD7894360UL, 0x425C750DUL, 0x93B39E26UL, 0x187184C9UL, + 0x6C00B32DUL, 0x73E2BB14UL, 0xA0BEBC3CUL, 0x54623779UL, + 0x64459EABUL, 0x3F328B82UL, 0x7718CF82UL, 0x59A2CEA6UL, + 0x04EE002EUL, 0x89FE78E6UL, 0x3FAB0950UL, 0x325FF6C2UL, + 0x81383F05UL, 0x6963C5C8UL, 0x76CB5AD6UL, 0xD49974C9UL, + 0xCA180DCFUL, 0x380782D5UL, 0xC7FA5CF6UL, 0x8AC31511UL, + 0x35E79E13UL, 0x47DA91D0UL, 0xF40F9086UL, 0xA7E2419EUL, + 0x31366241UL, 0x051EF495UL, 0xAA573B04UL, 0x4A805D8DUL, + 0x548300D0UL, 0x00322A3CUL, 0xBF64CDDFUL, 0xBA57A68EUL, + 0x75C6372BUL, 0x50AFD341UL, 0xA7C13275UL, 0x915A0BF5UL, + 0x6B54BFABUL, 0x2B0B1426UL, 0xAB4CC9D7UL, 0x449CCD82UL, + 0xF7FBF265UL, 0xAB85C5F3UL, 0x1B55DB94UL, 0xAAD4E324UL, + 0xCFA4BD3FUL, 0x2DEAA3E2UL, 0x9E204D02UL, 0xC8BD25ACUL, + 0xEADF55B3UL, 0xD5BD9E98UL, 0xE31231B2UL, 0x2AD5AD6CUL, + 0x954329DEUL, 0xADBE4528UL, 0xD8710F69UL, 0xAA51C90FUL, + 0xAA786BF6UL, 0x22513F1EUL, 0xAA51A79BUL, 0x2AD344CCUL, + 0x7B5A41F0UL, 0xD37CFBADUL, 0x1B069505UL, 0x41ECE491UL, + 0xB4C332E6UL, 0x032268D4UL, 0xC9600ACCUL, 0xCE387E6DUL, + 0xBF6BB16CUL, 0x6A70FB78UL, 0x0D03D9C9UL, 0xD4DF39DEUL, + 0xE01063DAUL, 0x4736F464UL, 0x5AD328D8UL, 0xB347CC96UL, + 0x75BB0FC3UL, 0x98511BFBUL, 0x4FFBCC35UL, 0xB58BCF6AUL, + 0xE11F0ABCUL, 0xBFC5FE4AUL, 0xA70AEC10UL, 0xAC39570AUL, + 0x3F04442FUL, 0x6188B153UL, 0xE0397A2EUL, 0x5727CB79UL, + 0x9CEB418FUL, 0x1CACD68DUL, 0x2AD37C96UL, 0x0175CB9DUL, + 0xC69DFF09UL, 0xC75B65F0UL, 0xD9DB40D8UL, 0xEC0E7779UL, + 0x4744EAD4UL, 0xB11C3274UL, 0xDD24CB9EUL, 0x7E1C54BDUL, + 0xF01144F9UL, 0xD2240EB1UL, 0x9675B3FDUL, 0xA3AC3755UL, + 0xD47C27AFUL, 0x51C85F4DUL, 0x56907596UL, 0xA5BB15E6UL, + 0x580304F0UL, 0xCA042CF1UL, 0x011A37EAUL, 0x8DBFAADBUL, + 0x35BA3E4AUL, 0x3526FFA0UL, 0xC37B4D09UL, 0xBC306ED9UL, + 0x98A52666UL, 0x5648F725UL, 0xFF5E569DUL, 0x0CED63D0UL, + 0x7C63B2CFUL, 0x700B45E1UL, 0xD5EA50F1UL, 0x85A92872UL, + 0xAF1FBDA7UL, 0xD4234870UL, 0xA7870BF3UL, 0x2D3B4D79UL, + 0x42E04198UL, 0x0CD0EDE7UL, 0x26470DB8UL, 0xF881814CUL, + 0x474D6AD7UL, 0x7C0C5E5CUL, 0xD1231959UL, 0x381B7298UL, + 0xF5D2F4DBUL, 0xAB838653UL, 0x6E2F1E23UL, 0x83719C9EUL, + 0xBD91E046UL, 0x9A56456EUL, 0xDC39200CUL, 0x20C8C571UL, + 0x962BDA1CUL, 0xE1E696FFUL, 0xB141AB08UL, 0x7CCA89B9UL, + 0x1A69E783UL, 0x02CC4843UL, 0xA2F7C579UL, 0x429EF47DUL, + 0x427B169CUL, 0x5AC9F049UL, 0xDD8F0F00UL, 0x5C8165BFUL +}, + +{ + 0x1F201094UL, 0xEF0BA75BUL, 0x69E3CF7EUL, 0x393F4380UL, + 0xFE61CF7AUL, 0xEEC5207AUL, 0x55889C94UL, 0x72FC0651UL, + 0xADA7EF79UL, 0x4E1D7235UL, 0xD55A63CEUL, 0xDE0436BAUL, + 0x99C430EFUL, 0x5F0C0794UL, 0x18DCDB7DUL, 0xA1D6EFF3UL, + 0xA0B52F7BUL, 0x59E83605UL, 0xEE15B094UL, 0xE9FFD909UL, + 0xDC440086UL, 0xEF944459UL, 0xBA83CCB3UL, 0xE0C3CDFBUL, + 0xD1DA4181UL, 0x3B092AB1UL, 0xF997F1C1UL, 0xA5E6CF7BUL, + 0x01420DDBUL, 0xE4E7EF5BUL, 0x25A1FF41UL, 0xE180F806UL, + 0x1FC41080UL, 0x179BEE7AUL, 0xD37AC6A9UL, 0xFE5830A4UL, + 0x98DE8B7FUL, 0x77E83F4EUL, 0x79929269UL, 0x24FA9F7BUL, + 0xE113C85BUL, 0xACC40083UL, 0xD7503525UL, 0xF7EA615FUL, + 0x62143154UL, 0x0D554B63UL, 0x5D681121UL, 0xC866C359UL, + 0x3D63CF73UL, 0xCEE234C0UL, 0xD4D87E87UL, 0x5C672B21UL, + 0x071F6181UL, 0x39F7627FUL, 0x361E3084UL, 0xE4EB573BUL, + 0x602F64A4UL, 0xD63ACD9CUL, 0x1BBC4635UL, 0x9E81032DUL, + 0x2701F50CUL, 0x99847AB4UL, 0xA0E3DF79UL, 0xBA6CF38CUL, + 0x10843094UL, 0x2537A95EUL, 0xF46F6FFEUL, 0xA1FF3B1FUL, + 0x208CFB6AUL, 0x8F458C74UL, 0xD9E0A227UL, 0x4EC73A34UL, + 0xFC884F69UL, 0x3E4DE8DFUL, 0xEF0E0088UL, 0x3559648DUL, + 0x8A45388CUL, 0x1D804366UL, 0x721D9BFDUL, 0xA58684BBUL, + 0xE8256333UL, 0x844E8212UL, 0x128D8098UL, 0xFED33FB4UL, + 0xCE280AE1UL, 0x27E19BA5UL, 0xD5A6C252UL, 0xE49754BDUL, + 0xC5D655DDUL, 0xEB667064UL, 0x77840B4DUL, 0xA1B6A801UL, + 0x84DB26A9UL, 0xE0B56714UL, 0x21F043B7UL, 0xE5D05860UL, + 0x54F03084UL, 0x066FF472UL, 0xA31AA153UL, 0xDADC4755UL, + 0xB5625DBFUL, 0x68561BE6UL, 0x83CA6B94UL, 0x2D6ED23BUL, + 0xECCF01DBUL, 0xA6D3D0BAUL, 0xB6803D5CUL, 0xAF77A709UL, + 0x33B4A34CUL, 0x397BC8D6UL, 0x5EE22B95UL, 0x5F0E5304UL, + 0x81ED6F61UL, 0x20E74364UL, 0xB45E1378UL, 0xDE18639BUL, + 0x881CA122UL, 0xB96726D1UL, 0x8049A7E8UL, 0x22B7DA7BUL, + 0x5E552D25UL, 0x5272D237UL, 0x79D2951CUL, 0xC60D894CUL, + 0x488CB402UL, 0x1BA4FE5BUL, 0xA4B09F6BUL, 0x1CA815CFUL, + 0xA20C3005UL, 0x8871DF63UL, 0xB9DE2FCBUL, 0x0CC6C9E9UL, + 0x0BEEFF53UL, 0xE3214517UL, 0xB4542835UL, 0x9F63293CUL, + 0xEE41E729UL, 0x6E1D2D7CUL, 0x50045286UL, 0x1E6685F3UL, + 0xF33401C6UL, 0x30A22C95UL, 0x31A70850UL, 0x60930F13UL, + 0x73F98417UL, 0xA1269859UL, 0xEC645C44UL, 0x52C877A9UL, + 0xCDFF33A6UL, 0xA02B1741UL, 0x7CBAD9A2UL, 0x2180036FUL, + 0x50D99C08UL, 0xCB3F4861UL, 0xC26BD765UL, 0x64A3F6ABUL, + 0x80342676UL, 0x25A75E7BUL, 0xE4E6D1FCUL, 0x20C710E6UL, + 0xCDF0B680UL, 0x17844D3BUL, 0x31EEF84DUL, 0x7E0824E4UL, + 0x2CCB49EBUL, 0x846A3BAEUL, 0x8FF77888UL, 0xEE5D60F6UL, + 0x7AF75673UL, 0x2FDD5CDBUL, 0xA11631C1UL, 0x30F66F43UL, + 0xB3FAEC54UL, 0x157FD7FAUL, 0xEF8579CCUL, 0xD152DE58UL, + 0xDB2FFD5EUL, 0x8F32CE19UL, 0x306AF97AUL, 0x02F03EF8UL, + 0x99319AD5UL, 0xC242FA0FUL, 0xA7E3EBB0UL, 0xC68E4906UL, + 0xB8DA230CUL, 0x80823028UL, 0xDCDEF3C8UL, 0xD35FB171UL, + 0x088A1BC8UL, 0xBEC0C560UL, 0x61A3C9E8UL, 0xBCA8F54DUL, + 0xC72FEFFAUL, 0x22822E99UL, 0x82C570B4UL, 0xD8D94E89UL, + 0x8B1C34BCUL, 0x301E16E6UL, 0x273BE979UL, 0xB0FFEAA6UL, + 0x61D9B8C6UL, 0x00B24869UL, 0xB7FFCE3FUL, 0x08DC283BUL, + 0x43DAF65AUL, 0xF7E19798UL, 0x7619B72FUL, 0x8F1C9BA4UL, + 0xDC8637A0UL, 0x16A7D3B1UL, 0x9FC393B7UL, 0xA7136EEBUL, + 0xC6BCC63EUL, 0x1A513742UL, 0xEF6828BCUL, 0x520365D6UL, + 0x2D6A77ABUL, 0x3527ED4BUL, 0x821FD216UL, 0x095C6E2EUL, + 0xDB92F2FBUL, 0x5EEA29CBUL, 0x145892F5UL, 0x91584F7FUL, + 0x5483697BUL, 0x2667A8CCUL, 0x85196048UL, 0x8C4BACEAUL, + 0x833860D4UL, 0x0D23E0F9UL, 0x6C387E8AUL, 0x0AE6D249UL, + 0xB284600CUL, 0xD835731DUL, 0xDCB1C647UL, 0xAC4C56EAUL, + 0x3EBD81B3UL, 0x230EABB0UL, 0x6438BC87UL, 0xF0B5B1FAUL, + 0x8F5EA2B3UL, 0xFC184642UL, 0x0A036B7AUL, 0x4FB089BDUL, + 0x649DA589UL, 0xA345415EUL, 0x5C038323UL, 0x3E5D3BB9UL, + 0x43D79572UL, 0x7E6DD07CUL, 0x06DFDF1EUL, 0x6C6CC4EFUL, + 0x7160A539UL, 0x73BFBE70UL, 0x83877605UL, 0x4523ECF1UL +}, + +{ + 0x8DEFC240UL, 0x25FA5D9FUL, 0xEB903DBFUL, 0xE810C907UL, + 0x47607FFFUL, 0x369FE44BUL, 0x8C1FC644UL, 0xAECECA90UL, + 0xBEB1F9BFUL, 0xEEFBCAEAUL, 0xE8CF1950UL, 0x51DF07AEUL, + 0x920E8806UL, 0xF0AD0548UL, 0xE13C8D83UL, 0x927010D5UL, + 0x11107D9FUL, 0x07647DB9UL, 0xB2E3E4D4UL, 0x3D4F285EUL, + 0xB9AFA820UL, 0xFADE82E0UL, 0xA067268BUL, 0x8272792EUL, + 0x553FB2C0UL, 0x489AE22BUL, 0xD4EF9794UL, 0x125E3FBCUL, + 0x21FFFCEEUL, 0x825B1BFDUL, 0x9255C5EDUL, 0x1257A240UL, + 0x4E1A8302UL, 0xBAE07FFFUL, 0x528246E7UL, 0x8E57140EUL, + 0x3373F7BFUL, 0x8C9F8188UL, 0xA6FC4EE8UL, 0xC982B5A5UL, + 0xA8C01DB7UL, 0x579FC264UL, 0x67094F31UL, 0xF2BD3F5FUL, + 0x40FFF7C1UL, 0x1FB78DFCUL, 0x8E6BD2C1UL, 0x437BE59BUL, + 0x99B03DBFUL, 0xB5DBC64BUL, 0x638DC0E6UL, 0x55819D99UL, + 0xA197C81CUL, 0x4A012D6EUL, 0xC5884A28UL, 0xCCC36F71UL, + 0xB843C213UL, 0x6C0743F1UL, 0x8309893CUL, 0x0FEDDD5FUL, + 0x2F7FE850UL, 0xD7C07F7EUL, 0x02507FBFUL, 0x5AFB9A04UL, + 0xA747D2D0UL, 0x1651192EUL, 0xAF70BF3EUL, 0x58C31380UL, + 0x5F98302EUL, 0x727CC3C4UL, 0x0A0FB402UL, 0x0F7FEF82UL, + 0x8C96FDADUL, 0x5D2C2AAEUL, 0x8EE99A49UL, 0x50DA88B8UL, + 0x8427F4A0UL, 0x1EAC5790UL, 0x796FB449UL, 0x8252DC15UL, + 0xEFBD7D9BUL, 0xA672597DUL, 0xADA840D8UL, 0x45F54504UL, + 0xFA5D7403UL, 0xE83EC305UL, 0x4F91751AUL, 0x925669C2UL, + 0x23EFE941UL, 0xA903F12EUL, 0x60270DF2UL, 0x0276E4B6UL, + 0x94FD6574UL, 0x927985B2UL, 0x8276DBCBUL, 0x02778176UL, + 0xF8AF918DUL, 0x4E48F79EUL, 0x8F616DDFUL, 0xE29D840EUL, + 0x842F7D83UL, 0x340CE5C8UL, 0x96BBB682UL, 0x93B4B148UL, + 0xEF303CABUL, 0x984FAF28UL, 0x779FAF9BUL, 0x92DC560DUL, + 0x224D1E20UL, 0x8437AA88UL, 0x7D29DC96UL, 0x2756D3DCUL, + 0x8B907CEEUL, 0xB51FD240UL, 0xE7C07CE3UL, 0xE566B4A1UL, + 0xC3E9615EUL, 0x3CF8209DUL, 0x6094D1E3UL, 0xCD9CA341UL, + 0x5C76460EUL, 0x00EA983BUL, 0xD4D67881UL, 0xFD47572CUL, + 0xF76CEDD9UL, 0xBDA8229CUL, 0x127DADAAUL, 0x438A074EUL, + 0x1F97C090UL, 0x081BDB8AUL, 0x93A07EBEUL, 0xB938CA15UL, + 0x97B03CFFUL, 0x3DC2C0F8UL, 0x8D1AB2ECUL, 0x64380E51UL, + 0x68CC7BFBUL, 0xD90F2788UL, 0x12490181UL, 0x5DE5FFD4UL, + 0xDD7EF86AUL, 0x76A2E214UL, 0xB9A40368UL, 0x925D958FUL, + 0x4B39FFFAUL, 0xBA39AEE9UL, 0xA4FFD30BUL, 0xFAF7933BUL, + 0x6D498623UL, 0x193CBCFAUL, 0x27627545UL, 0x825CF47AUL, + 0x61BD8BA0UL, 0xD11E42D1UL, 0xCEAD04F4UL, 0x127EA392UL, + 0x10428DB7UL, 0x8272A972UL, 0x9270C4A8UL, 0x127DE50BUL, + 0x285BA1C8UL, 0x3C62F44FUL, 0x35C0EAA5UL, 0xE805D231UL, + 0x428929FBUL, 0xB4FCDF82UL, 0x4FB66A53UL, 0x0E7DC15BUL, + 0x1F081FABUL, 0x108618AEUL, 0xFCFD086DUL, 0xF9FF2889UL, + 0x694BCC11UL, 0x236A5CAEUL, 0x12DECA4DUL, 0x2C3F8CC5UL, + 0xD2D02DFEUL, 0xF8EF5896UL, 0xE4CF52DAUL, 0x95155B67UL, + 0x494A488CUL, 0xB9B6A80CUL, 0x5C8F82BCUL, 0x89D36B45UL, + 0x3A609437UL, 0xEC00C9A9UL, 0x44715253UL, 0x0A874B49UL, + 0xD773BC40UL, 0x7C34671CUL, 0x02717EF6UL, 0x4FEB5536UL, + 0xA2D02FFFUL, 0xD2BF60C4UL, 0xD43F03C0UL, 0x50B4EF6DUL, + 0x07478CD1UL, 0x006E1888UL, 0xA2E53F55UL, 0xB9E6D4BCUL, + 0xA2048016UL, 0x97573833UL, 0xD7207D67UL, 0xDE0F8F3DUL, + 0x72F87B33UL, 0xABCC4F33UL, 0x7688C55DUL, 0x7B00A6B0UL, + 0x947B0001UL, 0x570075D2UL, 0xF9BB88F8UL, 0x8942019EUL, + 0x4264A5FFUL, 0x856302E0UL, 0x72DBD92BUL, 0xEE971B69UL, + 0x6EA22FDEUL, 0x5F08AE2BUL, 0xAF7A616DUL, 0xE5C98767UL, + 0xCF1FEBD2UL, 0x61EFC8C2UL, 0xF1AC2571UL, 0xCC8239C2UL, + 0x67214CB8UL, 0xB1E583D1UL, 0xB7DC3E62UL, 0x7F10BDCEUL, + 0xF90A5C38UL, 0x0FF0443DUL, 0x606E6DC6UL, 0x60543A49UL, + 0x5727C148UL, 0x2BE98A1DUL, 0x8AB41738UL, 0x20E1BE24UL, + 0xAF96DA0FUL, 0x68458425UL, 0x99833BE5UL, 0x600D457DUL, + 0x282F9350UL, 0x8334B362UL, 0xD91D1120UL, 0x2B6D8DA0UL, + 0x642B1E31UL, 0x9C305A00UL, 0x52BCE688UL, 0x1B03588AUL, + 0xF7BAEFD5UL, 0x4142ED9CUL, 0xA4315C11UL, 0x83323EC5UL, + 0xDFEF4636UL, 0xA133C501UL, 0xE9D3531CUL, 0xEE353783UL +}, + +{ + 0x9DB30420UL, 0x1FB6E9DEUL, 0xA7BE7BEFUL, 0xD273A298UL, + 0x4A4F7BDBUL, 0x64AD8C57UL, 0x85510443UL, 0xFA020ED1UL, + 0x7E287AFFUL, 0xE60FB663UL, 0x095F35A1UL, 0x79EBF120UL, + 0xFD059D43UL, 0x6497B7B1UL, 0xF3641F63UL, 0x241E4ADFUL, + 0x28147F5FUL, 0x4FA2B8CDUL, 0xC9430040UL, 0x0CC32220UL, + 0xFDD30B30UL, 0xC0A5374FUL, 0x1D2D00D9UL, 0x24147B15UL, + 0xEE4D111AUL, 0x0FCA5167UL, 0x71FF904CUL, 0x2D195FFEUL, + 0x1A05645FUL, 0x0C13FEFEUL, 0x081B08CAUL, 0x05170121UL, + 0x80530100UL, 0xE83E5EFEUL, 0xAC9AF4F8UL, 0x7FE72701UL, + 0xD2B8EE5FUL, 0x06DF4261UL, 0xBB9E9B8AUL, 0x7293EA25UL, + 0xCE84FFDFUL, 0xF5718801UL, 0x3DD64B04UL, 0xA26F263BUL, + 0x7ED48400UL, 0x547EEBE6UL, 0x446D4CA0UL, 0x6CF3D6F5UL, + 0x2649ABDFUL, 0xAEA0C7F5UL, 0x36338CC1UL, 0x503F7E93UL, + 0xD3772061UL, 0x11B638E1UL, 0x72500E03UL, 0xF80EB2BBUL, + 0xABE0502EUL, 0xEC8D77DEUL, 0x57971E81UL, 0xE14F6746UL, + 0xC9335400UL, 0x6920318FUL, 0x081DBB99UL, 0xFFC304A5UL, + 0x4D351805UL, 0x7F3D5CE3UL, 0xA6C866C6UL, 0x5D5BCCA9UL, + 0xDAEC6FEAUL, 0x9F926F91UL, 0x9F46222FUL, 0x3991467DUL, + 0xA5BF6D8EUL, 0x1143C44FUL, 0x43958302UL, 0xD0214EEBUL, + 0x022083B8UL, 0x3FB6180CUL, 0x18F8931EUL, 0x281658E6UL, + 0x26486E3EUL, 0x8BD78A70UL, 0x7477E4C1UL, 0xB506E07CUL, + 0xF32D0A25UL, 0x79098B02UL, 0xE4EABB81UL, 0x28123B23UL, + 0x69DEAD38UL, 0x1574CA16UL, 0xDF871B62UL, 0x211C40B7UL, + 0xA51A9EF9UL, 0x0014377BUL, 0x041E8AC8UL, 0x09114003UL, + 0xBD59E4D2UL, 0xE3D156D5UL, 0x4FE876D5UL, 0x2F91A340UL, + 0x557BE8DEUL, 0x00EAE4A7UL, 0x0CE5C2ECUL, 0x4DB4BBA6UL, + 0xE756BDFFUL, 0xDD3369ACUL, 0xEC17B035UL, 0x06572327UL, + 0x99AFC8B0UL, 0x56C8C391UL, 0x6B65811CUL, 0x5E146119UL, + 0x6E85CB75UL, 0xBE07C002UL, 0xC2325577UL, 0x893FF4ECUL, + 0x5BBFC92DUL, 0xD0EC3B25UL, 0xB7801AB7UL, 0x8D6D3B24UL, + 0x20C763EFUL, 0xC366A5FCUL, 0x9C382880UL, 0x0ACE3205UL, + 0xAAC9548AUL, 0xECA1D7C7UL, 0x041AFA32UL, 0x1D16625AUL, + 0x6701902CUL, 0x9B757A54UL, 0x31D477F7UL, 0x9126B031UL, + 0x36CC6FDBUL, 0xC70B8B46UL, 0xD9E66A48UL, 0x56E55A79UL, + 0x026A4CEBUL, 0x52437EFFUL, 0x2F8F76B4UL, 0x0DF980A5UL, + 0x8674CDE3UL, 0xEDDA04EBUL, 0x17A9BE04UL, 0x2C18F4DFUL, + 0xB7747F9DUL, 0xAB2AF7B4UL, 0xEFC34D20UL, 0x2E096B7CUL, + 0x1741A254UL, 0xE5B6A035UL, 0x213D42F6UL, 0x2C1C7C26UL, + 0x61C2F50FUL, 0x6552DAF9UL, 0xD2C231F8UL, 0x25130F69UL, + 0xD8167FA2UL, 0x0418F2C8UL, 0x001A96A6UL, 0x0D1526ABUL, + 0x63315C21UL, 0x5E0A72ECUL, 0x49BAFEFDUL, 0x187908D9UL, + 0x8D0DBD86UL, 0x311170A7UL, 0x3E9B640CUL, 0xCC3E10D7UL, + 0xD5CAD3B6UL, 0x0CAEC388UL, 0xF73001E1UL, 0x6C728AFFUL, + 0x71EAE2A1UL, 0x1F9AF36EUL, 0xCFCBD12FUL, 0xC1DE8417UL, + 0xAC07BE6BUL, 0xCB44A1D8UL, 0x8B9B0F56UL, 0x013988C3UL, + 0xB1C52FCAUL, 0xB4BE31CDUL, 0xD8782806UL, 0x12A3A4E2UL, + 0x6F7DE532UL, 0x58FD7EB6UL, 0xD01EE900UL, 0x24ADFFC2UL, + 0xF4990FC5UL, 0x9711AAC5UL, 0x001D7B95UL, 0x82E5E7D2UL, + 0x109873F6UL, 0x00613096UL, 0xC32D9521UL, 0xADA121FFUL, + 0x29908415UL, 0x7FBB977FUL, 0xAF9EB3DBUL, 0x29C9ED2AUL, + 0x5CE2A465UL, 0xA730F32CUL, 0xD0AA3FE8UL, 0x8A5CC091UL, + 0xD49E2CE7UL, 0x0CE454A9UL, 0xD60ACD86UL, 0x015F1919UL, + 0x77079103UL, 0xDEA03AF6UL, 0x78A8565EUL, 0xDEE356DFUL, + 0x21F05CBEUL, 0x8B75E387UL, 0xB3C50651UL, 0xB8A5C3EFUL, + 0xD8EEB6D2UL, 0xE523BE77UL, 0xC2154529UL, 0x2F69EFDFUL, + 0xAFE67AFBUL, 0xF470C4B2UL, 0xF3E0EB5BUL, 0xD6CC9876UL, + 0x39E4460CUL, 0x1FDA8538UL, 0x1987832FUL, 0xCA007367UL, + 0xA99144F8UL, 0x296B299EUL, 0x492FC295UL, 0x9266BEABUL, + 0xB5676E69UL, 0x9BD3DDDAUL, 0xDF7E052FUL, 0xDB25701CUL, + 0x1B5E51EEUL, 0xF65324E6UL, 0x6AFCE36CUL, 0x0316CC04UL, + 0x8644213EUL, 0xB7DC59D0UL, 0x7965291FUL, 0xCCD6FD43UL, + 0x41823979UL, 0x932BCDF6UL, 0xB657C34DUL, 0x4EDFD282UL, + 0x7AE5290CUL, 0x3CB9536BUL, 0x851E20FEUL, 0x9833557EUL, + 0x13ECF0B0UL, 0xD3FFB372UL, 0x3F85C5C1UL, 0x0AEF7ED2UL +}, + +{ + 0x7EC90C04UL, 0x2C6E74B9UL, 0x9B0E66DFUL, 0xA6337911UL, + 0xB86A7FFFUL, 0x1DD358F5UL, 0x44DD9D44UL, 0x1731167FUL, + 0x08FBF1FAUL, 0xE7F511CCUL, 0xD2051B00UL, 0x735ABA00UL, + 0x2AB722D8UL, 0x386381CBUL, 0xACF6243AUL, 0x69BEFD7AUL, + 0xE6A2E77FUL, 0xF0C720CDUL, 0xC4494816UL, 0xCCF5C180UL, + 0x38851640UL, 0x15B0A848UL, 0xE68B18CBUL, 0x4CAADEFFUL, + 0x5F480A01UL, 0x0412B2AAUL, 0x259814FCUL, 0x41D0EFE2UL, + 0x4E40B48DUL, 0x248EB6FBUL, 0x8DBA1CFEUL, 0x41A99B02UL, + 0x1A550A04UL, 0xBA8F65CBUL, 0x7251F4E7UL, 0x95A51725UL, + 0xC106ECD7UL, 0x97A5980AUL, 0xC539B9AAUL, 0x4D79FE6AUL, + 0xF2F3F763UL, 0x68AF8040UL, 0xED0C9E56UL, 0x11B4958BUL, + 0xE1EB5A88UL, 0x8709E6B0UL, 0xD7E07156UL, 0x4E29FEA7UL, + 0x6366E52DUL, 0x02D1C000UL, 0xC4AC8E05UL, 0x9377F571UL, + 0x0C05372AUL, 0x578535F2UL, 0x2261BE02UL, 0xD642A0C9UL, + 0xDF13A280UL, 0x74B55BD2UL, 0x682199C0UL, 0xD421E5ECUL, + 0x53FB3CE8UL, 0xC8ADEDB3UL, 0x28A87FC9UL, 0x3D959981UL, + 0x5C1FF900UL, 0xFE38D399UL, 0x0C4EFF0BUL, 0x062407EAUL, + 0xAA2F4FB1UL, 0x4FB96976UL, 0x90C79505UL, 0xB0A8A774UL, + 0xEF55A1FFUL, 0xE59CA2C2UL, 0xA6B62D27UL, 0xE66A4263UL, + 0xDF65001FUL, 0x0EC50966UL, 0xDFDD55BCUL, 0x29DE0655UL, + 0x911E739AUL, 0x17AF8975UL, 0x32C7911CUL, 0x89F89468UL, + 0x0D01E980UL, 0x524755F4UL, 0x03B63CC9UL, 0x0CC844B2UL, + 0xBCF3F0AAUL, 0x87AC36E9UL, 0xE53A7426UL, 0x01B3D82BUL, + 0x1A9E7449UL, 0x64EE2D7EUL, 0xCDDBB1DAUL, 0x01C94910UL, + 0xB868BF80UL, 0x0D26F3FDUL, 0x9342EDE7UL, 0x04A5C284UL, + 0x636737B6UL, 0x50F5B616UL, 0xF24766E3UL, 0x8ECA36C1UL, + 0x136E05DBUL, 0xFEF18391UL, 0xFB887A37UL, 0xD6E7F7D4UL, + 0xC7FB7DC9UL, 0x3063FCDFUL, 0xB6F589DEUL, 0xEC2941DAUL, + 0x26E46695UL, 0xB7566419UL, 0xF654EFC5UL, 0xD08D58B7UL, + 0x48925401UL, 0xC1BACB7FUL, 0xE5FF550FUL, 0xB6083049UL, + 0x5BB5D0E8UL, 0x87D72E5AUL, 0xAB6A6EE1UL, 0x223A66CEUL, + 0xC62BF3CDUL, 0x9E0885F9UL, 0x68CB3E47UL, 0x086C010FUL, + 0xA21DE820UL, 0xD18B69DEUL, 0xF3F65777UL, 0xFA02C3F6UL, + 0x407EDAC3UL, 0xCBB3D550UL, 0x1793084DUL, 0xB0D70EBAUL, + 0x0AB378D5UL, 0xD951FB0CUL, 0xDED7DA56UL, 0x4124BBE4UL, + 0x94CA0B56UL, 0x0F5755D1UL, 0xE0E1E56EUL, 0x6184B5BEUL, + 0x580A249FUL, 0x94F74BC0UL, 0xE327888EUL, 0x9F7B5561UL, + 0xC3DC0280UL, 0x05687715UL, 0x646C6BD7UL, 0x44904DB3UL, + 0x66B4F0A3UL, 0xC0F1648AUL, 0x697ED5AFUL, 0x49E92FF6UL, + 0x309E374FUL, 0x2CB6356AUL, 0x85808573UL, 0x4991F840UL, + 0x76F0AE02UL, 0x083BE84DUL, 0x28421C9AUL, 0x44489406UL, + 0x736E4CB8UL, 0xC1092910UL, 0x8BC95FC6UL, 0x7D869CF4UL, + 0x134F616FUL, 0x2E77118DUL, 0xB31B2BE1UL, 0xAA90B472UL, + 0x3CA5D717UL, 0x7D161BBAUL, 0x9CAD9010UL, 0xAF462BA2UL, + 0x9FE459D2UL, 0x45D34559UL, 0xD9F2DA13UL, 0xDBC65487UL, + 0xF3E4F94EUL, 0x176D486FUL, 0x097C13EAUL, 0x631DA5C7UL, + 0x445F7382UL, 0x175683F4UL, 0xCDC66A97UL, 0x70BE0288UL, + 0xB3CDCF72UL, 0x6E5DD2F3UL, 0x20936079UL, 0x459B80A5UL, + 0xBE60E2DBUL, 0xA9C23101UL, 0xEBA5315CUL, 0x224E42F2UL, + 0x1C5C1572UL, 0xF6721B2CUL, 0x1AD2FFF3UL, 0x8C25404EUL, + 0x324ED72FUL, 0x4067B7FDUL, 0x0523138EUL, 0x5CA3BC78UL, + 0xDC0FD66EUL, 0x75922283UL, 0x784D6B17UL, 0x58EBB16EUL, + 0x44094F85UL, 0x3F481D87UL, 0xFCFEAE7BUL, 0x77B5FF76UL, + 0x8C2302BFUL, 0xAAF47556UL, 0x5F46B02AUL, 0x2B092801UL, + 0x3D38F5F7UL, 0x0CA81F36UL, 0x52AF4A8AUL, 0x66D5E7C0UL, + 0xDF3B0874UL, 0x95055110UL, 0x1B5AD7A8UL, 0xF61ED5ADUL, + 0x6CF6E479UL, 0x20758184UL, 0xD0CEFA65UL, 0x88F7BE58UL, + 0x4A046826UL, 0x0FF6F8F3UL, 0xA09C7F70UL, 0x5346ABA0UL, + 0x5CE96C28UL, 0xE176EDA3UL, 0x6BAC307FUL, 0x376829D2UL, + 0x85360FA9UL, 0x17E3FE2AUL, 0x24B79767UL, 0xF5A96B20UL, + 0xD6CD2595UL, 0x68FF1EBFUL, 0x7555442CUL, 0xF19F06BEUL, + 0xF9E0659AUL, 0xEEB9491DUL, 0x34010718UL, 0xBB30CAB8UL, + 0xE822FE15UL, 0x88570983UL, 0x750E6249UL, 0xDA627E55UL, + 0x5E76FFA8UL, 0xB1534546UL, 0x6D47DE08UL, 0xEFE9E7D4UL +}, + +{ + 0xF6FA8F9DUL, 0x2CAC6CE1UL, 0x4CA34867UL, 0xE2337F7CUL, + 0x95DB08E7UL, 0x016843B4UL, 0xECED5CBCUL, 0x325553ACUL, + 0xBF9F0960UL, 0xDFA1E2EDUL, 0x83F0579DUL, 0x63ED86B9UL, + 0x1AB6A6B8UL, 0xDE5EBE39UL, 0xF38FF732UL, 0x8989B138UL, + 0x33F14961UL, 0xC01937BDUL, 0xF506C6DAUL, 0xE4625E7EUL, + 0xA308EA99UL, 0x4E23E33CUL, 0x79CBD7CCUL, 0x48A14367UL, + 0xA3149619UL, 0xFEC94BD5UL, 0xA114174AUL, 0xEAA01866UL, + 0xA084DB2DUL, 0x09A8486FUL, 0xA888614AUL, 0x2900AF98UL, + 0x01665991UL, 0xE1992863UL, 0xC8F30C60UL, 0x2E78EF3CUL, + 0xD0D51932UL, 0xCF0FEC14UL, 0xF7CA07D2UL, 0xD0A82072UL, + 0xFD41197EUL, 0x9305A6B0UL, 0xE86BE3DAUL, 0x74BED3CDUL, + 0x372DA53CUL, 0x4C7F4448UL, 0xDAB5D440UL, 0x6DBA0EC3UL, + 0x083919A7UL, 0x9FBAEED9UL, 0x49DBCFB0UL, 0x4E670C53UL, + 0x5C3D9C01UL, 0x64BDB941UL, 0x2C0E636AUL, 0xBA7DD9CDUL, + 0xEA6F7388UL, 0xE70BC762UL, 0x35F29ADBUL, 0x5C4CDD8DUL, + 0xF0D48D8CUL, 0xB88153E2UL, 0x08A19866UL, 0x1AE2EAC8UL, + 0x284CAF89UL, 0xAA928223UL, 0x9334BE53UL, 0x3B3A21BFUL, + 0x16434BE3UL, 0x9AEA3906UL, 0xEFE8C36EUL, 0xF890CDD9UL, + 0x80226DAEUL, 0xC340A4A3UL, 0xDF7E9C09UL, 0xA694A807UL, + 0x5B7C5ECCUL, 0x221DB3A6UL, 0x9A69A02FUL, 0x68818A54UL, + 0xCEB2296FUL, 0x53C0843AUL, 0xFE893655UL, 0x25BFE68AUL, + 0xB4628ABCUL, 0xCF222EBFUL, 0x25AC6F48UL, 0xA9A99387UL, + 0x53BDDB65UL, 0xE76FFBE7UL, 0xE967FD78UL, 0x0BA93563UL, + 0x8E342BC1UL, 0xE8A11BE9UL, 0x4980740DUL, 0xC8087DFCUL, + 0x8DE4BF99UL, 0xA11101A0UL, 0x7FD37975UL, 0xDA5A26C0UL, + 0xE81F994FUL, 0x9528CD89UL, 0xFD339FEDUL, 0xB87834BFUL, + 0x5F04456DUL, 0x22258698UL, 0xC9C4C83BUL, 0x2DC156BEUL, + 0x4F628DAAUL, 0x57F55EC5UL, 0xE2220ABEUL, 0xD2916EBFUL, + 0x4EC75B95UL, 0x24F2C3C0UL, 0x42D15D99UL, 0xCD0D7FA0UL, + 0x7B6E27FFUL, 0xA8DC8AF0UL, 0x7345C106UL, 0xF41E232FUL, + 0x35162386UL, 0xE6EA8926UL, 0x3333B094UL, 0x157EC6F2UL, + 0x372B74AFUL, 0x692573E4UL, 0xE9A9D848UL, 0xF3160289UL, + 0x3A62EF1DUL, 0xA787E238UL, 0xF3A5F676UL, 0x74364853UL, + 0x20951063UL, 0x4576698DUL, 0xB6FAD407UL, 0x592AF950UL, + 0x36F73523UL, 0x4CFB6E87UL, 0x7DA4CEC0UL, 0x6C152DAAUL, + 0xCB0396A8UL, 0xC50DFE5DUL, 0xFCD707ABUL, 0x0921C42FUL, + 0x89DFF0BBUL, 0x5FE2BE78UL, 0x448F4F33UL, 0x754613C9UL, + 0x2B05D08DUL, 0x48B9D585UL, 0xDC049441UL, 0xC8098F9BUL, + 0x7DEDE786UL, 0xC39A3373UL, 0x42410005UL, 0x6A091751UL, + 0x0EF3C8A6UL, 0x890072D6UL, 0x28207682UL, 0xA9A9F7BEUL, + 0xBF32679DUL, 0xD45B5B75UL, 0xB353FD00UL, 0xCBB0E358UL, + 0x830F220AUL, 0x1F8FB214UL, 0xD372CF08UL, 0xCC3C4A13UL, + 0x8CF63166UL, 0x061C87BEUL, 0x88C98F88UL, 0x6062E397UL, + 0x47CF8E7AUL, 0xB6C85283UL, 0x3CC2ACFBUL, 0x3FC06976UL, + 0x4E8F0252UL, 0x64D8314DUL, 0xDA3870E3UL, 0x1E665459UL, + 0xC10908F0UL, 0x513021A5UL, 0x6C5B68B7UL, 0x822F8AA0UL, + 0x3007CD3EUL, 0x74719EEFUL, 0xDC872681UL, 0x073340D4UL, + 0x7E432FD9UL, 0x0C5EC241UL, 0x8809286CUL, 0xF592D891UL, + 0x08A930F6UL, 0x957EF305UL, 0xB7FBFFBDUL, 0xC266E96FUL, + 0x6FE4AC98UL, 0xB173ECC0UL, 0xBC60B42AUL, 0x953498DAUL, + 0xFBA1AE12UL, 0x2D4BD736UL, 0x0F25FAABUL, 0xA4F3FCEBUL, + 0xE2969123UL, 0x257F0C3DUL, 0x9348AF49UL, 0x361400BCUL, + 0xE8816F4AUL, 0x3814F200UL, 0xA3F94043UL, 0x9C7A54C2UL, + 0xBC704F57UL, 0xDA41E7F9UL, 0xC25AD33AUL, 0x54F4A084UL, + 0xB17F5505UL, 0x59357CBEUL, 0xEDBD15C8UL, 0x7F97C5ABUL, + 0xBA5AC7B5UL, 0xB6F6DEAFUL, 0x3A479C3AUL, 0x5302DA25UL, + 0x653D7E6AUL, 0x54268D49UL, 0x51A477EAUL, 0x5017D55BUL, + 0xD7D25D88UL, 0x44136C76UL, 0x0404A8C8UL, 0xB8E5A121UL, + 0xB81A928AUL, 0x60ED5869UL, 0x97C55B96UL, 0xEAEC991BUL, + 0x29935913UL, 0x01FDB7F1UL, 0x088E8DFAUL, 0x9AB6F6F5UL, + 0x3B4CBF9FUL, 0x4A5DE3ABUL, 0xE6051D35UL, 0xA0E1D855UL, + 0xD36B4CF1UL, 0xF544EDEBUL, 0xB0E93524UL, 0xBEBB8FBDUL, + 0xA2D762CFUL, 0x49C92F54UL, 0x38B5F331UL, 0x7128A454UL, + 0x48392905UL, 0xA65B1DB8UL, 0x851C97BDUL, 0xD675CF2FUL +}, + +{ + 0x85E04019UL, 0x332BF567UL, 0x662DBFFFUL, 0xCFC65693UL, + 0x2A8D7F6FUL, 0xAB9BC912UL, 0xDE6008A1UL, 0x2028DA1FUL, + 0x0227BCE7UL, 0x4D642916UL, 0x18FAC300UL, 0x50F18B82UL, + 0x2CB2CB11UL, 0xB232E75CUL, 0x4B3695F2UL, 0xB28707DEUL, + 0xA05FBCF6UL, 0xCD4181E9UL, 0xE150210CUL, 0xE24EF1BDUL, + 0xB168C381UL, 0xFDE4E789UL, 0x5C79B0D8UL, 0x1E8BFD43UL, + 0x4D495001UL, 0x38BE4341UL, 0x913CEE1DUL, 0x92A79C3FUL, + 0x089766BEUL, 0xBAEEADF4UL, 0x1286BECFUL, 0xB6EACB19UL, + 0x2660C200UL, 0x7565BDE4UL, 0x64241F7AUL, 0x8248DCA9UL, + 0xC3B3AD66UL, 0x28136086UL, 0x0BD8DFA8UL, 0x356D1CF2UL, + 0x107789BEUL, 0xB3B2E9CEUL, 0x0502AA8FUL, 0x0BC0351EUL, + 0x166BF52AUL, 0xEB12FF82UL, 0xE3486911UL, 0xD34D7516UL, + 0x4E7B3AFFUL, 0x5F43671BUL, 0x9CF6E037UL, 0x4981AC83UL, + 0x334266CEUL, 0x8C9341B7UL, 0xD0D854C0UL, 0xCB3A6C88UL, + 0x47BC2829UL, 0x4725BA37UL, 0xA66AD22BUL, 0x7AD61F1EUL, + 0x0C5CBAFAUL, 0x4437F107UL, 0xB6E79962UL, 0x42D2D816UL, + 0x0A961288UL, 0xE1A5C06EUL, 0x13749E67UL, 0x72FC081AUL, + 0xB1D139F7UL, 0xF9583745UL, 0xCF19DF58UL, 0xBEC3F756UL, + 0xC06EBA30UL, 0x07211B24UL, 0x45C28829UL, 0xC95E317FUL, + 0xBC8EC511UL, 0x38BC46E9UL, 0xC6E6FA14UL, 0xBAE8584AUL, + 0xAD4EBC46UL, 0x468F508BUL, 0x7829435FUL, 0xF124183BUL, + 0x821DBA9FUL, 0xAFF60FF4UL, 0xEA2C4E6DUL, 0x16E39264UL, + 0x92544A8BUL, 0x009B4FC3UL, 0xABA68CEDUL, 0x9AC96F78UL, + 0x06A5B79AUL, 0xB2856E6EUL, 0x1AEC3CA9UL, 0xBE838688UL, + 0x0E0804E9UL, 0x55F1BE56UL, 0xE7E5363BUL, 0xB3A1F25DUL, + 0xF7DEBB85UL, 0x61FE033CUL, 0x16746233UL, 0x3C034C28UL, + 0xDA6D0C74UL, 0x79AAC56CUL, 0x3CE4E1ADUL, 0x51F0C802UL, + 0x98F8F35AUL, 0x1626A49FUL, 0xEED82B29UL, 0x1D382FE3UL, + 0x0C4FB99AUL, 0xBB325778UL, 0x3EC6D97BUL, 0x6E77A6A9UL, + 0xCB658B5CUL, 0xD45230C7UL, 0x2BD1408BUL, 0x60C03EB7UL, + 0xB9068D78UL, 0xA33754F4UL, 0xF430C87DUL, 0xC8A71302UL, + 0xB96D8C32UL, 0xEBD4E7BEUL, 0xBE8B9D2DUL, 0x7979FB06UL, + 0xE7225308UL, 0x8B75CF77UL, 0x11EF8DA4UL, 0xE083C858UL, + 0x8D6B786FUL, 0x5A6317A6UL, 0xFA5CF7A0UL, 0x5DDA0033UL, + 0xF28EBFB0UL, 0xF5B9C310UL, 0xA0EAC280UL, 0x08B9767AUL, + 0xA3D9D2B0UL, 0x79D34217UL, 0x021A718DUL, 0x9AC6336AUL, + 0x2711FD60UL, 0x438050E3UL, 0x069908A8UL, 0x3D7FEDC4UL, + 0x826D2BEFUL, 0x4EEB8476UL, 0x488DCF25UL, 0x36C9D566UL, + 0x28E74E41UL, 0xC2610ACAUL, 0x3D49A9CFUL, 0xBAE3B9DFUL, + 0xB65F8DE6UL, 0x92AEAF64UL, 0x3AC7D5E6UL, 0x9EA80509UL, + 0xF22B017DUL, 0xA4173F70UL, 0xDD1E16C3UL, 0x15E0D7F9UL, + 0x50B1B887UL, 0x2B9F4FD5UL, 0x625ABA82UL, 0x6A017962UL, + 0x2EC01B9CUL, 0x15488AA9UL, 0xD716E740UL, 0x40055A2CUL, + 0x93D29A22UL, 0xE32DBF9AUL, 0x058745B9UL, 0x3453DC1EUL, + 0xD699296EUL, 0x496CFF6FUL, 0x1C9F4986UL, 0xDFE2ED07UL, + 0xB87242D1UL, 0x19DE7EAEUL, 0x053E561AUL, 0x15AD6F8CUL, + 0x66626C1CUL, 0x7154C24CUL, 0xEA082B2AUL, 0x93EB2939UL, + 0x17DCB0F0UL, 0x58D4F2AEUL, 0x9EA294FBUL, 0x52CF564CUL, + 0x9883FE66UL, 0x2EC40581UL, 0x763953C3UL, 0x01D6692EUL, + 0xD3A0C108UL, 0xA1E7160EUL, 0xE4F2DFA6UL, 0x693ED285UL, + 0x74904698UL, 0x4C2B0EDDUL, 0x4F757656UL, 0x5D393378UL, + 0xA132234FUL, 0x3D321C5DUL, 0xC3F5E194UL, 0x4B269301UL, + 0xC79F022FUL, 0x3C997E7EUL, 0x5E4F9504UL, 0x3FFAFBBDUL, + 0x76F7AD0EUL, 0x296693F4UL, 0x3D1FCE6FUL, 0xC61E45BEUL, + 0xD3B5AB34UL, 0xF72BF9B7UL, 0x1B0434C0UL, 0x4E72B567UL, + 0x5592A33DUL, 0xB5229301UL, 0xCFD2A87FUL, 0x60AEB767UL, + 0x1814386BUL, 0x30BCC33DUL, 0x38A0C07DUL, 0xFD1606F2UL, + 0xC363519BUL, 0x589DD390UL, 0x5479F8E6UL, 0x1CB8D647UL, + 0x97FD61A9UL, 0xEA7759F4UL, 0x2D57539DUL, 0x569A58CFUL, + 0xE84E63ADUL, 0x462E1B78UL, 0x6580F87EUL, 0xF3817914UL, + 0x91DA55F4UL, 0x40A230F3UL, 0xD1988F35UL, 0xB6E318D2UL, + 0x3FFA50BCUL, 0x3D40F021UL, 0xC3C0BDAEUL, 0x4958C24CUL, + 0x518F36B2UL, 0x84B1D370UL, 0x0FEDCE83UL, 0x878DDADAUL, + 0xF2A279C7UL, 0x94E01BE8UL, 0x90716F4BUL, 0x954B8AA3UL +}, + +{ + 0xE216300DUL, 0xBBDDFFFCUL, 0xA7EBDABDUL, 0x35648095UL, + 0x7789F8B7UL, 0xE6C1121BUL, 0x0E241600UL, 0x052CE8B5UL, + 0x11A9CFB0UL, 0xE5952F11UL, 0xECE7990AUL, 0x9386D174UL, + 0x2A42931CUL, 0x76E38111UL, 0xB12DEF3AUL, 0x37DDDDFCUL, + 0xDE9ADEB1UL, 0x0A0CC32CUL, 0xBE197029UL, 0x84A00940UL, + 0xBB243A0FUL, 0xB4D137CFUL, 0xB44E79F0UL, 0x049EEDFDUL, + 0x0B15A15DUL, 0x480D3168UL, 0x8BBBDE5AUL, 0x669DED42UL, + 0xC7ECE831UL, 0x3F8F95E7UL, 0x72DF191BUL, 0x7580330DUL, + 0x94074251UL, 0x5C7DCDFAUL, 0xABBE6D63UL, 0xAA402164UL, + 0xB301D40AUL, 0x02E7D1CAUL, 0x53571DAEUL, 0x7A3182A2UL, + 0x12A8DDECUL, 0xFDAA335DUL, 0x176F43E8UL, 0x71FB46D4UL, + 0x38129022UL, 0xCE949AD4UL, 0xB84769ADUL, 0x965BD862UL, + 0x82F3D055UL, 0x66FB9767UL, 0x15B80B4EUL, 0x1D5B47A0UL, + 0x4CFDE06FUL, 0xC28EC4B8UL, 0x57E8726EUL, 0x647A78FCUL, + 0x99865D44UL, 0x608BD593UL, 0x6C200E03UL, 0x39DC5FF6UL, + 0x5D0B00A3UL, 0xAE63AFF2UL, 0x7E8BD632UL, 0x70108C0CUL, + 0xBBD35049UL, 0x2998DF04UL, 0x980CF42AUL, 0x9B6DF491UL, + 0x9E7EDD53UL, 0x06918548UL, 0x58CB7E07UL, 0x3B74EF2EUL, + 0x522FFFB1UL, 0xD24708CCUL, 0x1C7E27CDUL, 0xA4EB215BUL, + 0x3CF1D2E2UL, 0x19B47A38UL, 0x424F7618UL, 0x35856039UL, + 0x9D17DEE7UL, 0x27EB35E6UL, 0xC9AFF67BUL, 0x36BAF5B8UL, + 0x09C467CDUL, 0xC18910B1UL, 0xE11DBF7BUL, 0x06CD1AF8UL, + 0x7170C608UL, 0x2D5E3354UL, 0xD4DE495AUL, 0x64C6D006UL, + 0xBCC0C62CUL, 0x3DD00DB3UL, 0x708F8F34UL, 0x77D51B42UL, + 0x264F620FUL, 0x24B8D2BFUL, 0x15C1B79EUL, 0x46A52564UL, + 0xF8D7E54EUL, 0x3E378160UL, 0x7895CDA5UL, 0x859C15A5UL, + 0xE6459788UL, 0xC37BC75FUL, 0xDB07BA0CUL, 0x0676A3ABUL, + 0x7F229B1EUL, 0x31842E7BUL, 0x24259FD7UL, 0xF8BEF472UL, + 0x835FFCB8UL, 0x6DF4C1F2UL, 0x96F5B195UL, 0xFD0AF0FCUL, + 0xB0FE134CUL, 0xE2506D3DUL, 0x4F9B12EAUL, 0xF215F225UL, + 0xA223736FUL, 0x9FB4C428UL, 0x25D04979UL, 0x34C713F8UL, + 0xC4618187UL, 0xEA7A6E98UL, 0x7CD16EFCUL, 0x1436876CUL, + 0xF1544107UL, 0xBEDEEE14UL, 0x56E9AF27UL, 0xA04AA441UL, + 0x3CF7C899UL, 0x92ECBAE6UL, 0xDD67016DUL, 0x151682EBUL, + 0xA842EEDFUL, 0xFDBA60B4UL, 0xF1907B75UL, 0x20E3030FUL, + 0x24D8C29EUL, 0xE139673BUL, 0xEFA63FB8UL, 0x71873054UL, + 0xB6F2CF3BUL, 0x9F326442UL, 0xCB15A4CCUL, 0xB01A4504UL, + 0xF1E47D8DUL, 0x844A1BE5UL, 0xBAE7DFDCUL, 0x42CBDA70UL, + 0xCD7DAE0AUL, 0x57E85B7AUL, 0xD53F5AF6UL, 0x20CF4D8CUL, + 0xCEA4D428UL, 0x79D130A4UL, 0x3486EBFBUL, 0x33D3CDDCUL, + 0x77853B53UL, 0x37EFFCB5UL, 0xC5068778UL, 0xE580B3E6UL, + 0x4E68B8F4UL, 0xC5C8B37EUL, 0x0D809EA2UL, 0x398FEB7CUL, + 0x132A4F94UL, 0x43B7950EUL, 0x2FEE7D1CUL, 0x223613BDUL, + 0xDD06CAA2UL, 0x37DF932BUL, 0xC4248289UL, 0xACF3EBC3UL, + 0x5715F6B7UL, 0xEF3478DDUL, 0xF267616FUL, 0xC148CBE4UL, + 0x9052815EUL, 0x5E410FABUL, 0xB48A2465UL, 0x2EDA7FA4UL, + 0xE87B40E4UL, 0xE98EA084UL, 0x5889E9E1UL, 0xEFD390FCUL, + 0xDD07D35BUL, 0xDB485694UL, 0x38D7E5B2UL, 0x57720101UL, + 0x730EDEBCUL, 0x5B643113UL, 0x94917E4FUL, 0x503C2FBAUL, + 0x646F1282UL, 0x7523D24AUL, 0xE0779695UL, 0xF9C17A8FUL, + 0x7A5B2121UL, 0xD187B896UL, 0x29263A4DUL, 0xBA510CDFUL, + 0x81F47C9FUL, 0xAD1163EDUL, 0xEA7B5965UL, 0x1A00726EUL, + 0x11403092UL, 0x00DA6D77UL, 0x4A0CDD61UL, 0xAD1F4603UL, + 0x605BDFB0UL, 0x9EEDC364UL, 0x22EBE6A8UL, 0xCEE7D28AUL, + 0xA0E736A0UL, 0x5564A6B9UL, 0x10853209UL, 0xC7EB8F37UL, + 0x2DE705CAUL, 0x8951570FUL, 0xDF09822BUL, 0xBD691A6CUL, + 0xAA12E4F2UL, 0x87451C0FUL, 0xE0F6A27AUL, 0x3ADA4819UL, + 0x4CF1764FUL, 0x0D771C2BUL, 0x67CDB156UL, 0x350D8384UL, + 0x5938FA0FUL, 0x42399EF3UL, 0x36997B07UL, 0x0E84093DUL, + 0x4AA93E61UL, 0x8360D87BUL, 0x1FA98B0CUL, 0x1149382CUL, + 0xE97625A5UL, 0x0614D1B7UL, 0x0E25244BUL, 0x0C768347UL, + 0x589E8D82UL, 0x0D2059D1UL, 0xA466BB1EUL, 0xF8DA0A82UL, + 0x04F19130UL, 0xBA6E4EC0UL, 0x99265164UL, 0x1EE7230DUL, + 0x50B2AD80UL, 0xEAEE6801UL, 0x8DB2A283UL, 0xEA8BF59EUL +}}; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/cbcmac.cpp b/external/ours/library/crypto/src/shared/original/cbcmac.cpp new file mode 100755 index 000000000..b0c46de22 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/cbcmac.cpp @@ -0,0 +1,62 @@ +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "cbcmac.h" + +NAMESPACE_BEGIN(CryptoPP) + +void CBC_MAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + AccessCipher().SetKey(key, length, params); + m_reg.CleanNew(AccessCipher().BlockSize()); + m_counter = 0; +} + +void CBC_MAC_Base::Update(const byte *input, size_t length) +{ + unsigned int blockSize = AccessCipher().BlockSize(); + + while (m_counter && length) + { + m_reg[m_counter++] ^= *input++; + if (m_counter == blockSize) + ProcessBuf(); + length--; + } + + if (length >= blockSize) + { + size_t leftOver = AccessCipher().AdvancedProcessBlocks(m_reg, input, m_reg, length, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput); + input += (length - leftOver); + length = leftOver; + } + + while (length--) + { + m_reg[m_counter++] ^= *input++; + if (m_counter == blockSize) + ProcessBuf(); + } +} + +void CBC_MAC_Base::TruncatedFinal(byte *mac, size_t size) +{ + ThrowIfInvalidTruncatedSize(size); + + if (m_counter) + ProcessBuf(); + + memcpy(mac, m_reg, size); + memset(m_reg, 0, AccessCipher().BlockSize()); +} + +void CBC_MAC_Base::ProcessBuf() +{ + AccessCipher().ProcessBlock(m_reg); + m_counter = 0; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/cbcmac.h b/external/ours/library/crypto/src/shared/original/cbcmac.h new file mode 100755 index 000000000..ca3ff689a --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/ccm.cpp b/external/ours/library/crypto/src/shared/original/ccm.cpp new file mode 100755 index 000000000..c0c2c3523 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ccm.cpp @@ -0,0 +1,139 @@ +// ccm.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "ccm.h" + +NAMESPACE_BEGIN(CryptoPP) + +void CCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) +{ + BlockCipher &blockCipher = AccessBlockCipher(); + blockCipher.SetKey(userKey, keylength, params); + + if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE) + throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16"); + + m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize()); + if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16) + throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16"); + + m_buffer.Grow(2*REQUIRED_BLOCKSIZE); + m_L = 8; +} + +void CCM_Base::Resync(const byte *iv, size_t len) +{ + BlockCipher &cipher = AccessBlockCipher(); + + m_L = REQUIRED_BLOCKSIZE-1-(int)len; + CRYPTOPP_ASSERT(m_L >= 2); + if (m_L > 8) + m_L = 8; + + m_buffer[0] = byte(m_L-1); // flag + memcpy(m_buffer+1, iv, len); + memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len); + + if (m_state >= State_IVSet) + m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE); + else + m_ctr.SetCipherWithIV(cipher, m_buffer); + + m_ctr.Seek(REQUIRED_BLOCKSIZE); + m_aadLength = 0; + m_messageLength = 0; +} + +void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword /*footerLength*/) +{ + if (m_state != State_IVSet) + throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet"); + + m_aadLength = headerLength; + m_messageLength = messageLength; + + byte *cbcBuffer = CBC_Buffer(); + const BlockCipher &cipher = GetBlockCipher(); + + cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1)); // flag + PutWord(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength); + memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L); + cipher.ProcessBlock(cbcBuffer); + + if (headerLength>0) + { + CRYPTOPP_ASSERT(m_bufferedDataLength == 0); + + if (headerLength < ((1<<16) - (1<<8))) + { + PutWord(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength); + m_bufferedDataLength = 2; + } + else if (headerLength < (W64LIT(1)<<32)) + { + m_buffer[0] = 0xff; + m_buffer[1] = 0xfe; + PutWord(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength); + m_bufferedDataLength = 6; + } + else + { + m_buffer[0] = 0xff; + m_buffer[1] = 0xff; + PutWord(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength); + m_bufferedDataLength = 10; + } + } +} + +size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len) +{ + byte *cbcBuffer = CBC_Buffer(); + const BlockCipher &cipher = GetBlockCipher(); + return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput); +} + +void CCM_Base::AuthenticateLastHeaderBlock() +{ + byte *cbcBuffer = CBC_Buffer(); + const BlockCipher &cipher = GetBlockCipher(); + + if (m_aadLength != m_totalHeaderLength) + throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths"); + + if (m_bufferedDataLength > 0) + { + xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength); + cipher.ProcessBlock(cbcBuffer); + m_bufferedDataLength = 0; + } +} + +void CCM_Base::AuthenticateLastConfidentialBlock() +{ + byte *cbcBuffer = CBC_Buffer(); + const BlockCipher &cipher = GetBlockCipher(); + + if (m_messageLength != m_totalMessageLength) + throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths"); + + if (m_bufferedDataLength > 0) + { + xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength); + cipher.ProcessBlock(cbcBuffer); + m_bufferedDataLength = 0; + } +} + +void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize) +{ + m_ctr.Seek(0); + m_ctr.ProcessData(mac, CBC_Buffer(), macSize); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/ccm.h b/external/ours/library/crypto/src/shared/original/ccm.h new file mode 100755 index 000000000..5207a2fdf --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/chacha.cpp b/external/ours/library/crypto/src/shared/original/chacha.cpp new file mode 100755 index 000000000..5c50d52c1 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/chacha.cpp @@ -0,0 +1,568 @@ +// chacha.cpp - 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. + +#include "pch.h" +#include "config.h" +#include "chacha.h" +#include "argnames.h" +#include "misc.h" +#include "cpu.h" + +// Internal compiler error in GCC 3.3 and below +#if defined(__GNUC__) && (__GNUC__ < 4) +# undef CRYPTOPP_SSE2_INTRIN_AVAILABLE +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) +extern void ChaCha_OperateKeystream_NEON(const word32 *state, const byte* input, byte *output, unsigned int rounds); +#endif + +#if (CRYPTOPP_AVX2_AVAILABLE) +extern void ChaCha_OperateKeystream_AVX2(const word32 *state, const byte* input, byte *output, unsigned int rounds); +#endif +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +extern void ChaCha_OperateKeystream_SSE2(const word32 *state, const byte* input, byte *output, unsigned int rounds); +#endif + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) +extern void ChaCha_OperateKeystream_ALTIVEC(const word32 *state, const byte* input, byte *output, unsigned int rounds); +#endif + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void ChaCha_TestInstantiations() +{ + ChaCha::Encryption x; + ChaChaTLS::Encryption y; + XChaCha20::Encryption z; +} +#endif + +NAMESPACE_END // CryptoPP + +////////////////////////////// ChaCha Core ////////////////////////////// + +#define CHACHA_QUARTER_ROUND(a,b,c,d) \ + a += b; d ^= a; d = rotlConstant<16,word32>(d); \ + c += d; b ^= c; b = rotlConstant<12,word32>(b); \ + a += b; d ^= a; d = rotlConstant<8,word32>(d); \ + c += d; b ^= c; b = rotlConstant<7,word32>(b); + +#define CHACHA_OUTPUT(x){\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, x0 + state[0]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x1 + state[1]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x2 + state[2]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x3 + state[3]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + state[4]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x5 + state[5]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x6 + state[6]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x7 + state[7]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + state[8]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x9 + state[9]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x10 + state[10]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x11 + state[11]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + state[12]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x13 + state[13]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x14 + state[14]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x15 + state[15]);} + +ANONYMOUS_NAMESPACE_BEGIN + +// Hacks... Bring in all symbols, and supply +// the stuff the templates normally provide. +using namespace CryptoPP; +typedef word32 WordType; +enum {BYTES_PER_ITERATION=64}; + +// MultiBlockSafe detects a condition that can arise in the SIMD +// implementations where we overflow one of the 32-bit state words during +// addition in an intermediate result. Preconditions for the issue include +// a user seeks to around 2^32 blocks (256 GB of data) for ChaCha; or a +// user specifies an arbitrarily large initial counter block for ChaChaTLS. +// Also see https://github.com/weidai11/cryptopp/issues/732. +inline bool MultiBlockSafe(unsigned int ctrLow, unsigned int blocks) +{ + return 0xffffffff - ctrLow > blocks; +} + +// OperateKeystream always produces a key stream. The key stream is written +// to output. Optionally a message may be supplied to xor with the key stream. +// The message is input, and output = output ^ input. +void ChaCha_OperateKeystream(KeystreamOperation operation, + word32 state[16], word32& ctrLow, word32& ctrHigh, word32 rounds, + byte *output, const byte *input, size_t iterationCount) +{ + do + { +#if (CRYPTOPP_AVX2_AVAILABLE) + if (HasAVX2()) + { + while (iterationCount >= 8 && MultiBlockSafe(state[12], 8)) + { + const bool xorInput = (operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL); + ChaCha_OperateKeystream_AVX2(state, xorInput ? input : NULLPTR, output, rounds); + + // MultiBlockSafe avoids overflow on the counter words + state[12] += 8; + + input += (!!xorInput) * 8 * BYTES_PER_ITERATION; + output += 8 * BYTES_PER_ITERATION; + iterationCount -= 8; + } + } +#endif + +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) + if (HasSSE2()) + { + while (iterationCount >= 4 && MultiBlockSafe(state[12], 4)) + { + const bool xorInput = (operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL); + ChaCha_OperateKeystream_SSE2(state, xorInput ? input : NULLPTR, output, rounds); + + // MultiBlockSafe avoids overflow on the counter words + state[12] += 4; + + input += (!!xorInput)*4*BYTES_PER_ITERATION; + output += 4*BYTES_PER_ITERATION; + iterationCount -= 4; + } + } +#endif + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + { + while (iterationCount >= 4 && MultiBlockSafe(state[12], 4)) + { + const bool xorInput = (operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL); + ChaCha_OperateKeystream_NEON(state, xorInput ? input : NULLPTR, output, rounds); + + // MultiBlockSafe avoids overflow on the counter words + state[12] += 4; + + input += (!!xorInput)*4*BYTES_PER_ITERATION; + output += 4*BYTES_PER_ITERATION; + iterationCount -= 4; + } + } +#endif + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + { + while (iterationCount >= 4 && MultiBlockSafe(state[12], 4)) + { + const bool xorInput = (operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL); + ChaCha_OperateKeystream_ALTIVEC(state, xorInput ? input : NULLPTR, output, rounds); + + // MultiBlockSafe avoids overflow on the counter words + state[12] += 4; + + input += (!!xorInput)*4*BYTES_PER_ITERATION; + output += 4*BYTES_PER_ITERATION; + iterationCount -= 4; + } + } +#endif + + if (iterationCount) + { + word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + + x0 = state[0]; x1 = state[1]; x2 = state[2]; x3 = state[3]; + x4 = state[4]; x5 = state[5]; x6 = state[6]; x7 = state[7]; + x8 = state[8]; x9 = state[9]; x10 = state[10]; x11 = state[11]; + x12 = state[12]; x13 = state[13]; x14 = state[14]; x15 = state[15]; + + for (int i = static_cast(rounds); i > 0; i -= 2) + { + CHACHA_QUARTER_ROUND(x0, x4, x8, x12); + CHACHA_QUARTER_ROUND(x1, x5, x9, x13); + CHACHA_QUARTER_ROUND(x2, x6, x10, x14); + CHACHA_QUARTER_ROUND(x3, x7, x11, x15); + + CHACHA_QUARTER_ROUND(x0, x5, x10, x15); + CHACHA_QUARTER_ROUND(x1, x6, x11, x12); + CHACHA_QUARTER_ROUND(x2, x7, x8, x13); + CHACHA_QUARTER_ROUND(x3, x4, x9, x14); + } + + CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(CHACHA_OUTPUT, BYTES_PER_ITERATION); + + // This is state[12] and state[13] from ChaCha. In the case of + // ChaChaTLS ctrHigh is a reference to a discard value. + if (++ctrLow == 0) + ctrHigh++; + } + + // We may re-enter a SIMD keystream operation from here. + } while (iterationCount--); +} + +// XChaCha key derivation +void HChaCha_OperateKeystream(const word32 state[16], word32 output[8]) +{ + word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + + x0 = state[0]; x1 = state[1]; x2 = state[2]; x3 = state[3]; + x4 = state[4]; x5 = state[5]; x6 = state[6]; x7 = state[7]; + x8 = state[8]; x9 = state[9]; x10 = state[10]; x11 = state[11]; + x12 = state[12]; x13 = state[13]; x14 = state[14]; x15 = state[15]; + + for (int i = 20; i > 0; i -= 2) + { + CHACHA_QUARTER_ROUND(x0, x4, x8, x12); + CHACHA_QUARTER_ROUND(x1, x5, x9, x13); + CHACHA_QUARTER_ROUND(x2, x6, x10, x14); + CHACHA_QUARTER_ROUND(x3, x7, x11, x15); + + CHACHA_QUARTER_ROUND(x0, x5, x10, x15); + CHACHA_QUARTER_ROUND(x1, x6, x11, x12); + CHACHA_QUARTER_ROUND(x2, x7, x8, x13); + CHACHA_QUARTER_ROUND(x3, x4, x9, x14); + } + + output[0] = x0; output[1] = x1; + output[2] = x2; output[3] = x3; + output[4] = x12; output[5] = x13; + output[6] = x14; output[7] = x15; +} + +std::string ChaCha_AlgorithmProvider() +{ +#if (CRYPTOPP_AVX2_AVAILABLE) + if (HasAVX2()) + return "AVX2"; + else +#endif +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) + if (HasSSE2()) + return "SSE2"; + else +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return "NEON"; + else +#endif +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return "Altivec"; + else +#endif + return "C++"; +} + +unsigned int ChaCha_GetAlignment() +{ +#if (CRYPTOPP_AVX2_AVAILABLE) + if (HasAVX2()) + return 16; + else +#endif +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) + if (HasSSE2()) + return 16; + else +#endif +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return 16; + else +#endif + return GetAlignmentOf(); +} + +unsigned int ChaCha_GetOptimalBlockSize() +{ +#if (CRYPTOPP_AVX2_AVAILABLE) + if (HasAVX2()) + return 8 * BYTES_PER_ITERATION; + else +#endif +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) + if (HasSSE2()) + return 4*BYTES_PER_ITERATION; + else +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return 4*BYTES_PER_ITERATION; + else +#endif +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return 4*BYTES_PER_ITERATION; + else +#endif + return BYTES_PER_ITERATION; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +////////////////////////////// Bernstein ChaCha ////////////////////////////// + +std::string ChaCha_Policy::AlgorithmName() const +{ + return std::string("ChaCha")+IntToString(m_rounds); +} + +std::string ChaCha_Policy::AlgorithmProvider() const +{ + return ChaCha_AlgorithmProvider(); +} + +void ChaCha_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32); + CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length); + + // Use previous rounds as the default value + int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds); + if (rounds != 20 && rounds != 12 && rounds != 8) + throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds); + + // Latch a good value + m_rounds = rounds; + + // "expand 16-byte k" or "expand 32-byte k" + m_state[0] = 0x61707865; + m_state[1] = (length == 16) ? 0x3120646e : 0x3320646e; + m_state[2] = (length == 16) ? 0x79622d36 : 0x79622d32; + m_state[3] = 0x6b206574; + + GetBlock get1(key); + get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]); + + GetBlock get2(key + ((length == 32) ? 16 : 0)); + get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]); +} + +void ChaCha_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length==8); CRYPTOPP_UNUSED(length); + + GetBlock get(IV); + m_state[12] = m_state[13] = 0; + get(m_state[14])(m_state[15]); +} + +void ChaCha_Policy::SeekToIteration(lword iterationCount) +{ + m_state[12] = (word32)iterationCount; // low word + m_state[13] = (word32)SafeRightShift<32>(iterationCount); +} + +unsigned int ChaCha_Policy::GetAlignment() const +{ + return ChaCha_GetAlignment(); +} + +unsigned int ChaCha_Policy::GetOptimalBlockSize() const +{ + return ChaCha_GetOptimalBlockSize(); +} + +void ChaCha_Policy::OperateKeystream(KeystreamOperation operation, + byte *output, const byte *input, size_t iterationCount) +{ + ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13], + m_rounds, output, input, iterationCount); +} + +////////////////////////////// IETF ChaChaTLS ////////////////////////////// + +std::string ChaChaTLS_Policy::AlgorithmName() const +{ + return std::string("ChaChaTLS"); +} + +std::string ChaChaTLS_Policy::AlgorithmProvider() const +{ + return ChaCha_AlgorithmProvider(); +} + +void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32); + CRYPTOPP_UNUSED(length); + + // ChaChaTLS is always 20 rounds. Fetch Rounds() to avoid a spurious failure. + int rounds = params.GetIntValueWithDefault(Name::Rounds(), ROUNDS); + if (rounds != 20) + throw InvalidRounds(ChaChaTLS::StaticAlgorithmName(), rounds); + + // RFC 8439 test vectors use an initial block counter. However, the counter + // can be an arbitrary value per RFC 8439 Section 2.4. We stash the counter + // away in state[16] and use it for a Resynchronize() operation. I think + // the initial counter is used more like a Tweak when non-0, and it should + // be provided in Resynchronize() (light-weight re-keying). However, + // Resynchronize() does not have an overload that allows us to pass it into + // the function, so we have to use the heavier-weight SetKey to change it. + word64 block; + if (params.GetValue("InitialBlock", block)) + m_counter = static_cast(block); + else + m_counter = 0; + + // State words are defined in RFC 8439, Section 2.3. Key is 32-bytes. + GetBlock get(key); + get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3]) + (m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]); +} + +void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length==12); + + // State words are defined in RFC 8439, Section 2.3. + m_state[0] = 0x61707865; m_state[1] = 0x3320646e; + m_state[2] = 0x79622d32; m_state[3] = 0x6b206574; + + // Copy saved key into state + std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32)); + + // State words are defined in RFC 8439, Section 2.3 + GetBlock get(IV); + m_state[12] = m_counter; + get(m_state[13])(m_state[14])(m_state[15]); +} + +void ChaChaTLS_Policy::SeekToIteration(lword iterationCount) +{ + // Should we throw here??? If the initial block counter is + // large then we can wrap and process more data as long as + // data processed in the security context does not exceed + // 2^32 blocks or approximately 256 GB of data. + CRYPTOPP_ASSERT(iterationCount <= std::numeric_limits::max()); + m_state[12] = (word32)iterationCount; // low word +} + +unsigned int ChaChaTLS_Policy::GetAlignment() const +{ + return ChaCha_GetAlignment(); +} + +unsigned int ChaChaTLS_Policy::GetOptimalBlockSize() const +{ + return ChaCha_GetOptimalBlockSize(); +} + +void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation, + byte *output, const byte *input, size_t iterationCount) +{ + word32 discard=0; + ChaCha_OperateKeystream(operation, m_state, m_state[12], discard, + ROUNDS, output, input, iterationCount); + + // If this fires it means ChaCha_OperateKeystream generated a counter + // block carry that was discarded. The problem is, the RFC does not + // specify what should happen when the counter block wraps. All we can + // do is inform the user that something bad may happen because we don't + // know what we should do. + // Also see https://github.com/weidai11/cryptopp/issues/790 and + // https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU + // CRYPTOPP_ASSERT(discard==0); +} + +////////////////////////////// IETF XChaCha20 ////////////////////////////// + +std::string XChaCha20_Policy::AlgorithmName() const +{ + return std::string("XChaCha20"); +} + +std::string XChaCha20_Policy::AlgorithmProvider() const +{ + return ChaCha_AlgorithmProvider(); +} + +void XChaCha20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32); + CRYPTOPP_UNUSED(length); + + // Use previous rounds as the default value + int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds); + if (rounds != 20 && rounds != 12) + throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds); + + // Latch a good value + m_rounds = rounds; + + word64 block; + if (params.GetValue("InitialBlock", block)) + m_counter = static_cast(block); + else + m_counter = 1; + + // Stash key away for use in CipherResynchronize + GetBlock get(key); + get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3]) + (m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]); +} + +void XChaCha20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length==24); + + // HChaCha derivation + m_state[0] = 0x61707865; m_state[1] = 0x3320646e; + m_state[2] = 0x79622d32; m_state[3] = 0x6b206574; + + // Copy saved key into state + std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32)); + + GetBlock get(iv); + get(m_state[12])(m_state[13])(m_state[14])(m_state[15]); + + // Operate the keystream without adding state back in. + // This function also gathers the key words into a + // contiguous 8-word block. + HChaCha_OperateKeystream(m_state, m_state+4); + + // XChaCha state + m_state[0] = 0x61707865; m_state[1] = 0x3320646e; + m_state[2] = 0x79622d32; m_state[3] = 0x6b206574; + + // Setup new IV + m_state[12] = m_counter; + m_state[13] = 0; + m_state[14] = GetWord(false, LITTLE_ENDIAN_ORDER, iv+16); + m_state[15] = GetWord(false, LITTLE_ENDIAN_ORDER, iv+20); +} + +void XChaCha20_Policy::SeekToIteration(lword iterationCount) +{ + // Should we throw here??? XChaCha does not have a block + // counter, so I'm not sure how to seek on it. + CRYPTOPP_ASSERT(0); CRYPTOPP_UNUSED(iterationCount); +} + +unsigned int XChaCha20_Policy::GetAlignment() const +{ + return ChaCha_GetAlignment(); +} + +unsigned int XChaCha20_Policy::GetOptimalBlockSize() const +{ + return ChaCha_GetOptimalBlockSize(); +} + +void XChaCha20_Policy::OperateKeystream(KeystreamOperation operation, + byte *output, const byte *input, size_t iterationCount) +{ + ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13], + m_rounds, output, input, iterationCount); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/chacha.h b/external/ours/library/crypto/src/shared/original/chacha.h new file mode 100755 index 000000000..8c6dfde5f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 classses 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/external/ours/library/crypto/src/shared/original/chacha_avx.cpp b/external/ours/library/crypto/src/shared/original/chacha_avx.cpp new file mode 100755 index 000000000..8bd8ddc2b --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/chacha_avx.cpp @@ -0,0 +1,422 @@ +// chacha_avx.cpp - written and placed in the public domain by +// Jack Lloyd and Jeffrey Walton +// +// This source file uses intrinsics and built-ins to gain access to +// AVX2 instructions. A separate source file is needed because +// additional CXXFLAGS are required to enable the appropriate +// instructions sets in some build configurations. +// +// AVX2 implementation based on Botan's chacha_avx.cpp. Many thanks +// to Jack Lloyd and the Botan team for allowing us to use it. +// +// Here are some relative numbers for ChaCha8: +// * Intel Skylake, 3.0 GHz: AVX2 at 4411 MB/s; 0.57 cpb. +// * Intel Broadwell, 2.3 GHz: AVX2 at 3828 MB/s; 0.58 cpb. +// * AMD Bulldozer, 3.3 GHz: AVX2 at 1680 MB/s; 1.47 cpb. + +#include "pch.h" +#include "config.h" + +#include "chacha.h" +#include "misc.h" + +#if defined(CRYPTOPP_AVX2_AVAILABLE) +# include +# include +# include +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char CHACHA_AVX_FNAME[] = __FILE__; + +// Sun Studio 12.4 OK, 12.5 and 12.6 compile error. +#if (__SUNPRO_CC >= 0x5140) && (__SUNPRO_CC <= 0x5150) +# define MAYBE_CONST +#else +# define MAYBE_CONST const +#endif + +// VS2017 and global optimization bug. TODO, figure out when +// we can re-enable full optimizations for VS2017. Also see +// https://github.com/weidai11/cryptopp/issues/649 and +// https://github.com/weidai11/cryptopp/issues/735. The +// 649 issue affects AES but it is the same here. The 735 +// issue is ChaCha AVX2 cut-in where it surfaced again. +#if (_MSC_VER >= 1910) +# ifndef CRYPTOPP_DEBUG +# pragma optimize("", off) +# pragma optimize("ts", on) +# endif +#endif + +// The data is aligned, but Clang issues warning based on type +// and not the actual alignment of the variable and data. +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wcast-align" +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +#if (CRYPTOPP_AVX2_AVAILABLE) + +template +inline __m256i RotateLeft(const __m256i val) +{ + return _mm256_or_si256(_mm256_slli_epi32(val, R), _mm256_srli_epi32(val, 32-R)); +} + +template <> +inline __m256i RotateLeft<8>(const __m256i val) +{ + const __m256i mask = _mm256_set_epi8(14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3, + 14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3); + return _mm256_shuffle_epi8(val, mask); +} + +template <> +inline __m256i RotateLeft<16>(const __m256i val) +{ + const __m256i mask = _mm256_set_epi8(13,12,15,14, 9,8,11,10, 5,4,7,6, 1,0,3,2, + 13,12,15,14, 9,8,11,10, 5,4,7,6, 1,0,3,2); + return _mm256_shuffle_epi8(val, mask); +} + +#endif // CRYPTOPP_AVX2_AVAILABLE + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if (CRYPTOPP_AVX2_AVAILABLE) + +void ChaCha_OperateKeystream_AVX2(const word32 *state, const byte* input, byte *output, unsigned int rounds) +{ + const __m256i state0 = _mm256_broadcastsi128_si256( + _mm_loadu_si128(reinterpret_cast(state+0*4))); + const __m256i state1 = _mm256_broadcastsi128_si256( + _mm_loadu_si128(reinterpret_cast(state+1*4))); + const __m256i state2 = _mm256_broadcastsi128_si256( + _mm_loadu_si128(reinterpret_cast(state+2*4))); + const __m256i state3 = _mm256_broadcastsi128_si256( + _mm_loadu_si128(reinterpret_cast(state+3*4))); + + const word32 C = 0xFFFFFFFFu - state[12]; + const __m256i CTR0 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, C < 4, 4); + const __m256i CTR1 = _mm256_set_epi32(0, 0, C < 1, 1, 0, 0, C < 5, 5); + const __m256i CTR2 = _mm256_set_epi32(0, 0, C < 2, 2, 0, 0, C < 6, 6); + const __m256i CTR3 = _mm256_set_epi32(0, 0, C < 3, 3, 0, 0, C < 7, 7); + + __m256i X0_0 = state0; + __m256i X0_1 = state1; + __m256i X0_2 = state2; + __m256i X0_3 = _mm256_add_epi32(state3, CTR0); + + __m256i X1_0 = state0; + __m256i X1_1 = state1; + __m256i X1_2 = state2; + __m256i X1_3 = _mm256_add_epi32(state3, CTR1); + + __m256i X2_0 = state0; + __m256i X2_1 = state1; + __m256i X2_2 = state2; + __m256i X2_3 = _mm256_add_epi32(state3, CTR2); + + __m256i X3_0 = state0; + __m256i X3_1 = state1; + __m256i X3_2 = state2; + __m256i X3_3 = _mm256_add_epi32(state3, CTR3); + + for (int i = static_cast(rounds); i > 0; i -= 2) + { + X0_0 = _mm256_add_epi32(X0_0, X0_1); + X1_0 = _mm256_add_epi32(X1_0, X1_1); + X2_0 = _mm256_add_epi32(X2_0, X2_1); + X3_0 = _mm256_add_epi32(X3_0, X3_1); + + X0_3 = _mm256_xor_si256(X0_3, X0_0); + X1_3 = _mm256_xor_si256(X1_3, X1_0); + X2_3 = _mm256_xor_si256(X2_3, X2_0); + X3_3 = _mm256_xor_si256(X3_3, X3_0); + + X0_3 = RotateLeft<16>(X0_3); + X1_3 = RotateLeft<16>(X1_3); + X2_3 = RotateLeft<16>(X2_3); + X3_3 = RotateLeft<16>(X3_3); + + X0_2 = _mm256_add_epi32(X0_2, X0_3); + X1_2 = _mm256_add_epi32(X1_2, X1_3); + X2_2 = _mm256_add_epi32(X2_2, X2_3); + X3_2 = _mm256_add_epi32(X3_2, X3_3); + + X0_1 = _mm256_xor_si256(X0_1, X0_2); + X1_1 = _mm256_xor_si256(X1_1, X1_2); + X2_1 = _mm256_xor_si256(X2_1, X2_2); + X3_1 = _mm256_xor_si256(X3_1, X3_2); + + X0_1 = RotateLeft<12>(X0_1); + X1_1 = RotateLeft<12>(X1_1); + X2_1 = RotateLeft<12>(X2_1); + X3_1 = RotateLeft<12>(X3_1); + + X0_0 = _mm256_add_epi32(X0_0, X0_1); + X1_0 = _mm256_add_epi32(X1_0, X1_1); + X2_0 = _mm256_add_epi32(X2_0, X2_1); + X3_0 = _mm256_add_epi32(X3_0, X3_1); + + X0_3 = _mm256_xor_si256(X0_3, X0_0); + X1_3 = _mm256_xor_si256(X1_3, X1_0); + X2_3 = _mm256_xor_si256(X2_3, X2_0); + X3_3 = _mm256_xor_si256(X3_3, X3_0); + + X0_3 = RotateLeft<8>(X0_3); + X1_3 = RotateLeft<8>(X1_3); + X2_3 = RotateLeft<8>(X2_3); + X3_3 = RotateLeft<8>(X3_3); + + X0_2 = _mm256_add_epi32(X0_2, X0_3); + X1_2 = _mm256_add_epi32(X1_2, X1_3); + X2_2 = _mm256_add_epi32(X2_2, X2_3); + X3_2 = _mm256_add_epi32(X3_2, X3_3); + + X0_1 = _mm256_xor_si256(X0_1, X0_2); + X1_1 = _mm256_xor_si256(X1_1, X1_2); + X2_1 = _mm256_xor_si256(X2_1, X2_2); + X3_1 = _mm256_xor_si256(X3_1, X3_2); + + X0_1 = RotateLeft<7>(X0_1); + X1_1 = RotateLeft<7>(X1_1); + X2_1 = RotateLeft<7>(X2_1); + X3_1 = RotateLeft<7>(X3_1); + + X0_1 = _mm256_shuffle_epi32(X0_1, _MM_SHUFFLE(0, 3, 2, 1)); + X0_2 = _mm256_shuffle_epi32(X0_2, _MM_SHUFFLE(1, 0, 3, 2)); + X0_3 = _mm256_shuffle_epi32(X0_3, _MM_SHUFFLE(2, 1, 0, 3)); + + X1_1 = _mm256_shuffle_epi32(X1_1, _MM_SHUFFLE(0, 3, 2, 1)); + X1_2 = _mm256_shuffle_epi32(X1_2, _MM_SHUFFLE(1, 0, 3, 2)); + X1_3 = _mm256_shuffle_epi32(X1_3, _MM_SHUFFLE(2, 1, 0, 3)); + + X2_1 = _mm256_shuffle_epi32(X2_1, _MM_SHUFFLE(0, 3, 2, 1)); + X2_2 = _mm256_shuffle_epi32(X2_2, _MM_SHUFFLE(1, 0, 3, 2)); + X2_3 = _mm256_shuffle_epi32(X2_3, _MM_SHUFFLE(2, 1, 0, 3)); + + X3_1 = _mm256_shuffle_epi32(X3_1, _MM_SHUFFLE(0, 3, 2, 1)); + X3_2 = _mm256_shuffle_epi32(X3_2, _MM_SHUFFLE(1, 0, 3, 2)); + X3_3 = _mm256_shuffle_epi32(X3_3, _MM_SHUFFLE(2, 1, 0, 3)); + + X0_0 = _mm256_add_epi32(X0_0, X0_1); + X1_0 = _mm256_add_epi32(X1_0, X1_1); + X2_0 = _mm256_add_epi32(X2_0, X2_1); + X3_0 = _mm256_add_epi32(X3_0, X3_1); + + X0_3 = _mm256_xor_si256(X0_3, X0_0); + X1_3 = _mm256_xor_si256(X1_3, X1_0); + X2_3 = _mm256_xor_si256(X2_3, X2_0); + X3_3 = _mm256_xor_si256(X3_3, X3_0); + + X0_3 = RotateLeft<16>(X0_3); + X1_3 = RotateLeft<16>(X1_3); + X2_3 = RotateLeft<16>(X2_3); + X3_3 = RotateLeft<16>(X3_3); + + X0_2 = _mm256_add_epi32(X0_2, X0_3); + X1_2 = _mm256_add_epi32(X1_2, X1_3); + X2_2 = _mm256_add_epi32(X2_2, X2_3); + X3_2 = _mm256_add_epi32(X3_2, X3_3); + + X0_1 = _mm256_xor_si256(X0_1, X0_2); + X1_1 = _mm256_xor_si256(X1_1, X1_2); + X2_1 = _mm256_xor_si256(X2_1, X2_2); + X3_1 = _mm256_xor_si256(X3_1, X3_2); + + X0_1 = RotateLeft<12>(X0_1); + X1_1 = RotateLeft<12>(X1_1); + X2_1 = RotateLeft<12>(X2_1); + X3_1 = RotateLeft<12>(X3_1); + + X0_0 = _mm256_add_epi32(X0_0, X0_1); + X1_0 = _mm256_add_epi32(X1_0, X1_1); + X2_0 = _mm256_add_epi32(X2_0, X2_1); + X3_0 = _mm256_add_epi32(X3_0, X3_1); + + X0_3 = _mm256_xor_si256(X0_3, X0_0); + X1_3 = _mm256_xor_si256(X1_3, X1_0); + X2_3 = _mm256_xor_si256(X2_3, X2_0); + X3_3 = _mm256_xor_si256(X3_3, X3_0); + + X0_3 = RotateLeft<8>(X0_3); + X1_3 = RotateLeft<8>(X1_3); + X2_3 = RotateLeft<8>(X2_3); + X3_3 = RotateLeft<8>(X3_3); + + X0_2 = _mm256_add_epi32(X0_2, X0_3); + X1_2 = _mm256_add_epi32(X1_2, X1_3); + X2_2 = _mm256_add_epi32(X2_2, X2_3); + X3_2 = _mm256_add_epi32(X3_2, X3_3); + + X0_1 = _mm256_xor_si256(X0_1, X0_2); + X1_1 = _mm256_xor_si256(X1_1, X1_2); + X2_1 = _mm256_xor_si256(X2_1, X2_2); + X3_1 = _mm256_xor_si256(X3_1, X3_2); + + X0_1 = RotateLeft<7>(X0_1); + X1_1 = RotateLeft<7>(X1_1); + X2_1 = RotateLeft<7>(X2_1); + X3_1 = RotateLeft<7>(X3_1); + + X0_1 = _mm256_shuffle_epi32(X0_1, _MM_SHUFFLE(2, 1, 0, 3)); + X0_2 = _mm256_shuffle_epi32(X0_2, _MM_SHUFFLE(1, 0, 3, 2)); + X0_3 = _mm256_shuffle_epi32(X0_3, _MM_SHUFFLE(0, 3, 2, 1)); + + X1_1 = _mm256_shuffle_epi32(X1_1, _MM_SHUFFLE(2, 1, 0, 3)); + X1_2 = _mm256_shuffle_epi32(X1_2, _MM_SHUFFLE(1, 0, 3, 2)); + X1_3 = _mm256_shuffle_epi32(X1_3, _MM_SHUFFLE(0, 3, 2, 1)); + + X2_1 = _mm256_shuffle_epi32(X2_1, _MM_SHUFFLE(2, 1, 0, 3)); + X2_2 = _mm256_shuffle_epi32(X2_2, _MM_SHUFFLE(1, 0, 3, 2)); + X2_3 = _mm256_shuffle_epi32(X2_3, _MM_SHUFFLE(0, 3, 2, 1)); + + X3_1 = _mm256_shuffle_epi32(X3_1, _MM_SHUFFLE(2, 1, 0, 3)); + X3_2 = _mm256_shuffle_epi32(X3_2, _MM_SHUFFLE(1, 0, 3, 2)); + X3_3 = _mm256_shuffle_epi32(X3_3, _MM_SHUFFLE(0, 3, 2, 1)); + } + + X0_0 = _mm256_add_epi32(X0_0, state0); + X0_1 = _mm256_add_epi32(X0_1, state1); + X0_2 = _mm256_add_epi32(X0_2, state2); + X0_3 = _mm256_add_epi32(X0_3, state3); + X0_3 = _mm256_add_epi32(X0_3, CTR0); + + X1_0 = _mm256_add_epi32(X1_0, state0); + X1_1 = _mm256_add_epi32(X1_1, state1); + X1_2 = _mm256_add_epi32(X1_2, state2); + X1_3 = _mm256_add_epi32(X1_3, state3); + X1_3 = _mm256_add_epi32(X1_3, CTR1); + + X2_0 = _mm256_add_epi32(X2_0, state0); + X2_1 = _mm256_add_epi32(X2_1, state1); + X2_2 = _mm256_add_epi32(X2_2, state2); + X2_3 = _mm256_add_epi32(X2_3, state3); + X2_3 = _mm256_add_epi32(X2_3, CTR2); + + X3_0 = _mm256_add_epi32(X3_0, state0); + X3_1 = _mm256_add_epi32(X3_1, state1); + X3_2 = _mm256_add_epi32(X3_2, state2); + X3_3 = _mm256_add_epi32(X3_3, state3); + X3_3 = _mm256_add_epi32(X3_3, CTR3); + + if (input) + { + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+0*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X0_0, X0_1, 1 + (3 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+0*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+1*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X0_2, X0_3, 1 + (3 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+1*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+2*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X1_0, X1_1, 1 + (3 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+2*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+3*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X1_2, X1_3, 1 + (3 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+3*32))))); + } + else + { + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+0*32), + _mm256_permute2x128_si256(X0_0, X0_1, 1 + (3 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+1*32), + _mm256_permute2x128_si256(X0_2, X0_3, 1 + (3 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+2*32), + _mm256_permute2x128_si256(X1_0, X1_1, 1 + (3 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+3*32), + _mm256_permute2x128_si256(X1_2, X1_3, 1 + (3 << 4))); + } + + if (input) + { + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+4*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X2_0, X2_1, 1 + (3 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+4*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+5*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X2_2, X2_3, 1 + (3 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+5*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+6*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X3_0, X3_1, 1 + (3 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+6*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+7*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X3_2, X3_3, 1 + (3 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+7*32))))); + } + else + { + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+4*32), + _mm256_permute2x128_si256(X2_0, X2_1, 1 + (3 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+5*32), + _mm256_permute2x128_si256(X2_2, X2_3, 1 + (3 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+6*32), + _mm256_permute2x128_si256(X3_0, X3_1, 1 + (3 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+7*32), + _mm256_permute2x128_si256(X3_2, X3_3, 1 + (3 << 4))); + } + + if (input) + { + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+ 8*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X0_0, X0_1, 0 + (2 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+8*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+ 9*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X0_2, X0_3, 0 + (2 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+9*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+10*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X1_0, X1_1, 0 + (2 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+10*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+11*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X1_2, X1_3, 0 + (2 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+11*32))))); + } + else + { + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+ 8*32), + _mm256_permute2x128_si256(X0_0, X0_1, 0 + (2 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+ 9*32), + _mm256_permute2x128_si256(X0_2, X0_3, 0 + (2 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+10*32), + _mm256_permute2x128_si256(X1_0, X1_1, 0 + (2 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+11*32), + _mm256_permute2x128_si256(X1_2, X1_3, 0 + (2 << 4))); + } + + if (input) + { + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+12*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X2_0, X2_1, 0 + (2 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+12*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+13*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X2_2, X2_3, 0 + (2 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+13*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+14*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X3_0, X3_1, 0 + (2 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+14*32))))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+15*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X3_2, X3_3, 0 + (2 << 4)), + _mm256_loadu_si256(const_cast(reinterpret_cast(input+15*32))))); + } + else + { + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+12*32), + _mm256_permute2x128_si256(X2_0, X2_1, 0 + (2 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+13*32), + _mm256_permute2x128_si256(X2_2, X2_3, 0 + (2 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+14*32), + _mm256_permute2x128_si256(X3_0, X3_1, 0 + (2 << 4))); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output+15*32), + _mm256_permute2x128_si256(X3_2, X3_3, 0 + (2 << 4))); + } + + // https://software.intel.com/en-us/articles/avoiding-avx-sse-transition-penalties + _mm256_zeroupper(); +} + +#endif // CRYPTOPP_AVX2_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/chacha_simd.cpp b/external/ours/library/crypto/src/shared/original/chacha_simd.cpp new file mode 100755 index 000000000..4e5a3cc37 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/chacha_simd.cpp @@ -0,0 +1,1109 @@ +// chacha_simd.cpp - written and placed in the public domain by +// Jack Lloyd and Jeffrey Walton +// +// This source file uses intrinsics and built-ins to gain access to +// SSE2, ARM NEON and ARMv8a, Power7 and Altivec instructions. A separate +// source file is needed because additional CXXFLAGS are required to enable +// the appropriate instructions sets in some build configurations. +// +// SSE2 implementation based on Botan's chacha_sse2.cpp. Many thanks +// to Jack Lloyd and the Botan team for allowing us to use it. +// +// The SSE2 implementation is kind of unusual among Crypto++ algorithms. +// We guard on CRYTPOPP_SSE2_AVAILABLE and use HasSSE2() at runtime. However, +// if the compiler says a target machine has SSSE3 or XOP available (say, by +// way of -march=native), then we can pull another 150 to 800 MB/s out of +// ChaCha. To capture SSSE3 and XOP we use the compiler defines __SSSE3__ and +// __XOP__ and forgo runtime tests. +// +// Runtime tests for HasSSSE3() and HasXop() are too expensive to make a +// sub-case of SSE2. The rotates are on a critical path and the runtime tests +// crush performance. +// +// Here are some relative numbers for ChaCha8: +// * Intel Skylake, 3.0 GHz: SSE2 at 2160 MB/s; SSSE3 at 2310 MB/s. +// * AMD Bulldozer, 3.3 GHz: SSE2 at 1680 MB/s; XOP at 2510 MB/s. + +#include "pch.h" +#include "config.h" + +#include "chacha.h" +#include "misc.h" + +// Internal compiler error in GCC 3.3 and below +#if defined(__GNUC__) && (__GNUC__ < 4) +# undef CRYPTOPP_SSE2_INTRIN_AVAILABLE +#endif + +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +# include +# include +#endif + +#if defined(__SSSE3__) +# include +#endif + +#if defined(__XOP__) +# include +# if defined(__GNUC__) +# include +# endif +#endif + +#if (CRYPTOPP_ARM_NEON_HEADER) +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +#if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +# include "ppc_simd.h" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char CHACHA_SIMD_FNAME[] = __FILE__; + +ANONYMOUS_NAMESPACE_BEGIN + +// ***************************** NEON ***************************** // + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + +template +inline uint32x4_t RotateLeft(const uint32x4_t& val) +{ + return vorrq_u32(vshlq_n_u32(val, R), vshrq_n_u32(val, 32 - R)); +} + +template +inline uint32x4_t RotateRight(const uint32x4_t& val) +{ + return vorrq_u32(vshlq_n_u32(val, 32 - R), vshrq_n_u32(val, R)); +} + +template <> +inline uint32x4_t RotateLeft<8>(const uint32x4_t& val) +{ +#if defined(__aarch32__) || defined(__aarch64__) + const uint8_t maskb[16] = { 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14 }; + const uint8x16_t mask = vld1q_u8(maskb); + + return vreinterpretq_u32_u8( + vqtbl1q_u8(vreinterpretq_u8_u32(val), mask)); +#else + // fallback to slower C++ rotation. + return vorrq_u32(vshlq_n_u32(val, 8), + vshrq_n_u32(val, 32 - 8)); +#endif +} + +template <> +inline uint32x4_t RotateLeft<16>(const uint32x4_t& val) +{ +#if defined(__aarch32__) || defined(__aarch64__) + return vreinterpretq_u32_u16( + vrev32q_u16(vreinterpretq_u16_u32(val))); +#else + // fallback to slower C++ rotation. + return vorrq_u32(vshlq_n_u32(val, 16), + vshrq_n_u32(val, 32 - 16)); +#endif +} + +template <> +inline uint32x4_t RotateRight<8>(const uint32x4_t& val) +{ +#if defined(__aarch32__) || defined(__aarch64__) + const uint8_t maskb[16] = { 1,2,3,0, 5,6,7,4, 9,10,11,8, 13,14,15,12 }; + const uint8x16_t mask = vld1q_u8(maskb); + + return vreinterpretq_u32_u8( + vqtbl1q_u8(vreinterpretq_u8_u32(val), mask)); +#else + // fallback to slower C++ rotation. + return vorrq_u32(vshrq_n_u32(val, 8), + vshlq_n_u32(val, 32 - 8)); +#endif +} + +template <> +inline uint32x4_t RotateRight<16>(const uint32x4_t& val) +{ +#if defined(__aarch32__) || defined(__aarch64__) + return vreinterpretq_u32_u16( + vrev32q_u16(vreinterpretq_u16_u32(val))); +#else + // fallback to slower C++ rotation. + return vorrq_u32(vshrq_n_u32(val, 16), + vshlq_n_u32(val, 32 - 16)); +#endif +} + +// ChaCha's use of x86 shuffle is really a 4, 8, or 12 byte +// rotation on the 128-bit vector word: +// * [3,2,1,0] => [0,3,2,1] is Extract<1>(x) +// * [3,2,1,0] => [1,0,3,2] is Extract<2>(x) +// * [3,2,1,0] => [2,1,0,3] is Extract<3>(x) +template +inline uint32x4_t Extract(const uint32x4_t& val) +{ + return vextq_u32(val, val, S); +} + +// Helper to perform 64-bit addition across two elements of 32-bit vectors +inline uint32x4_t Add64(const uint32x4_t& a, const uint32x4_t& b) +{ + return vreinterpretq_u32_u64( + vaddq_u64( + vreinterpretq_u64_u32(a), + vreinterpretq_u64_u32(b))); +} + +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +// ***************************** SSE2 ***************************** // + +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) + +template +inline __m128i RotateLeft(const __m128i val) +{ +#ifdef __XOP__ + return _mm_roti_epi32(val, R); +#else + return _mm_or_si128(_mm_slli_epi32(val, R), _mm_srli_epi32(val, 32-R)); +#endif +} + +template <> +inline __m128i RotateLeft<8>(const __m128i val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, 8); +#elif defined(__SSSE3__) + const __m128i mask = _mm_set_epi8(14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3); + return _mm_shuffle_epi8(val, mask); +#else + return _mm_or_si128(_mm_slli_epi32(val, 8), _mm_srli_epi32(val, 32-8)); +#endif +} + +template <> +inline __m128i RotateLeft<16>(const __m128i val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, 16); +#elif defined(__SSSE3__) + const __m128i mask = _mm_set_epi8(13,12,15,14, 9,8,11,10, 5,4,7,6, 1,0,3,2); + return _mm_shuffle_epi8(val, mask); +#else + return _mm_or_si128(_mm_slli_epi32(val, 16), _mm_srli_epi32(val, 32-16)); +#endif +} + +#endif // CRYPTOPP_SSE2_INTRIN_AVAILABLE + +// **************************** Altivec **************************** // + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + +// ChaCha_OperateKeystream is optimized for Altivec. However, Altivec +// is supported by using vec_ld and vec_st, and using a composite VecAdd +// that supports 64-bit element adds. vec_ld and vec_st add significant +// overhead when memory is not aligned. Despite the drawbacks Altivec +// is profitable. The numbers for ChaCha8 are: +// +// PowerMac, C++, 2.0 GHz: 205 MB/s, 9.29 cpb +// PowerMac, Altivec, 2.0 GHz: 471 MB/s, 4.09 cpb + +using CryptoPP::uint8x16_p; +using CryptoPP::uint32x4_p; +using CryptoPP::VecLoad; +using CryptoPP::VecLoadAligned; +using CryptoPP::VecStore; +using CryptoPP::VecPermute; + +// Permutes bytes in packed 32-bit words to little endian. +// State is already in proper endian order. Input and +// output must be permuted during load and save. +inline uint32x4_p VecLoad32LE(const uint8_t src[16]) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p mask = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12}; + const uint32x4_p val = VecLoad(src); + return VecPermute(val, val, mask); +#else + return VecLoad(src); +#endif +} + +// Permutes bytes in packed 32-bit words to little endian. +// State is already in proper endian order. Input and +// output must be permuted during load and save. +inline void VecStore32LE(uint8_t dest[16], const uint32x4_p& val) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p mask = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12}; + VecStore(VecPermute(val, val, mask), dest); +#else + return VecStore(val, dest); +#endif +} + +// ChaCha's use of x86 shuffle is really a 4, 8, or 12 byte +// rotation on the 128-bit vector word: +// * [3,2,1,0] => [0,3,2,1] is Shuffle<1>(x) +// * [3,2,1,0] => [1,0,3,2] is Shuffle<2>(x) +// * [3,2,1,0] => [2,1,0,3] is Shuffle<3>(x) +template +inline uint32x4_p Shuffle(const uint32x4_p& val) +{ + CRYPTOPP_ASSERT(0); + return val; +} + +template <> +inline uint32x4_p Shuffle<1>(const uint32x4_p& val) +{ + const uint8x16_p mask = {4,5,6,7, 8,9,10,11, 12,13,14,15, 0,1,2,3}; + return VecPermute(val, val, mask); +} + +template <> +inline uint32x4_p Shuffle<2>(const uint32x4_p& val) +{ + const uint8x16_p mask = {8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7}; + return VecPermute(val, val, mask); +} + +template <> +inline uint32x4_p Shuffle<3>(const uint32x4_p& val) +{ + const uint8x16_p mask = {12,13,14,15, 0,1,2,3, 4,5,6,7, 8,9,10,11}; + return VecPermute(val, val, mask); +} + +#endif // CRYPTOPP_ALTIVEC_AVAILABLE + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +// ***************************** NEON ***************************** // + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + +void ChaCha_OperateKeystream_NEON(const word32 *state, const byte* input, byte *output, unsigned int rounds) +{ + const uint32x4_t state0 = vld1q_u32(state + 0*4); + const uint32x4_t state1 = vld1q_u32(state + 1*4); + const uint32x4_t state2 = vld1q_u32(state + 2*4); + const uint32x4_t state3 = vld1q_u32(state + 3*4); + + const unsigned int w[] = {1,0,0,0, 2,0,0,0, 3,0,0,0}; + const uint32x4_t CTRS[3] = { + vld1q_u32(w+0), vld1q_u32(w+4), vld1q_u32(w+8) + }; + + uint32x4_t r0_0 = state0; + uint32x4_t r0_1 = state1; + uint32x4_t r0_2 = state2; + uint32x4_t r0_3 = state3; + + uint32x4_t r1_0 = state0; + uint32x4_t r1_1 = state1; + uint32x4_t r1_2 = state2; + uint32x4_t r1_3 = Add64(r0_3, CTRS[0]); + + uint32x4_t r2_0 = state0; + uint32x4_t r2_1 = state1; + uint32x4_t r2_2 = state2; + uint32x4_t r2_3 = Add64(r0_3, CTRS[1]); + + uint32x4_t r3_0 = state0; + uint32x4_t r3_1 = state1; + uint32x4_t r3_2 = state2; + uint32x4_t r3_3 = Add64(r0_3, CTRS[2]); + + for (int i = static_cast(rounds); i > 0; i -= 2) + { + r0_0 = vaddq_u32(r0_0, r0_1); + r1_0 = vaddq_u32(r1_0, r1_1); + r2_0 = vaddq_u32(r2_0, r2_1); + r3_0 = vaddq_u32(r3_0, r3_1); + + r0_3 = veorq_u32(r0_3, r0_0); + r1_3 = veorq_u32(r1_3, r1_0); + r2_3 = veorq_u32(r2_3, r2_0); + r3_3 = veorq_u32(r3_3, r3_0); + + r0_3 = RotateLeft<16>(r0_3); + r1_3 = RotateLeft<16>(r1_3); + r2_3 = RotateLeft<16>(r2_3); + r3_3 = RotateLeft<16>(r3_3); + + r0_2 = vaddq_u32(r0_2, r0_3); + r1_2 = vaddq_u32(r1_2, r1_3); + r2_2 = vaddq_u32(r2_2, r2_3); + r3_2 = vaddq_u32(r3_2, r3_3); + + r0_1 = veorq_u32(r0_1, r0_2); + r1_1 = veorq_u32(r1_1, r1_2); + r2_1 = veorq_u32(r2_1, r2_2); + r3_1 = veorq_u32(r3_1, r3_2); + + r0_1 = RotateLeft<12>(r0_1); + r1_1 = RotateLeft<12>(r1_1); + r2_1 = RotateLeft<12>(r2_1); + r3_1 = RotateLeft<12>(r3_1); + + r0_0 = vaddq_u32(r0_0, r0_1); + r1_0 = vaddq_u32(r1_0, r1_1); + r2_0 = vaddq_u32(r2_0, r2_1); + r3_0 = vaddq_u32(r3_0, r3_1); + + r0_3 = veorq_u32(r0_3, r0_0); + r1_3 = veorq_u32(r1_3, r1_0); + r2_3 = veorq_u32(r2_3, r2_0); + r3_3 = veorq_u32(r3_3, r3_0); + + r0_3 = RotateLeft<8>(r0_3); + r1_3 = RotateLeft<8>(r1_3); + r2_3 = RotateLeft<8>(r2_3); + r3_3 = RotateLeft<8>(r3_3); + + r0_2 = vaddq_u32(r0_2, r0_3); + r1_2 = vaddq_u32(r1_2, r1_3); + r2_2 = vaddq_u32(r2_2, r2_3); + r3_2 = vaddq_u32(r3_2, r3_3); + + r0_1 = veorq_u32(r0_1, r0_2); + r1_1 = veorq_u32(r1_1, r1_2); + r2_1 = veorq_u32(r2_1, r2_2); + r3_1 = veorq_u32(r3_1, r3_2); + + r0_1 = RotateLeft<7>(r0_1); + r1_1 = RotateLeft<7>(r1_1); + r2_1 = RotateLeft<7>(r2_1); + r3_1 = RotateLeft<7>(r3_1); + + r0_1 = Extract<1>(r0_1); + r0_2 = Extract<2>(r0_2); + r0_3 = Extract<3>(r0_3); + + r1_1 = Extract<1>(r1_1); + r1_2 = Extract<2>(r1_2); + r1_3 = Extract<3>(r1_3); + + r2_1 = Extract<1>(r2_1); + r2_2 = Extract<2>(r2_2); + r2_3 = Extract<3>(r2_3); + + r3_1 = Extract<1>(r3_1); + r3_2 = Extract<2>(r3_2); + r3_3 = Extract<3>(r3_3); + + r0_0 = vaddq_u32(r0_0, r0_1); + r1_0 = vaddq_u32(r1_0, r1_1); + r2_0 = vaddq_u32(r2_0, r2_1); + r3_0 = vaddq_u32(r3_0, r3_1); + + r0_3 = veorq_u32(r0_3, r0_0); + r1_3 = veorq_u32(r1_3, r1_0); + r2_3 = veorq_u32(r2_3, r2_0); + r3_3 = veorq_u32(r3_3, r3_0); + + r0_3 = RotateLeft<16>(r0_3); + r1_3 = RotateLeft<16>(r1_3); + r2_3 = RotateLeft<16>(r2_3); + r3_3 = RotateLeft<16>(r3_3); + + r0_2 = vaddq_u32(r0_2, r0_3); + r1_2 = vaddq_u32(r1_2, r1_3); + r2_2 = vaddq_u32(r2_2, r2_3); + r3_2 = vaddq_u32(r3_2, r3_3); + + r0_1 = veorq_u32(r0_1, r0_2); + r1_1 = veorq_u32(r1_1, r1_2); + r2_1 = veorq_u32(r2_1, r2_2); + r3_1 = veorq_u32(r3_1, r3_2); + + r0_1 = RotateLeft<12>(r0_1); + r1_1 = RotateLeft<12>(r1_1); + r2_1 = RotateLeft<12>(r2_1); + r3_1 = RotateLeft<12>(r3_1); + + r0_0 = vaddq_u32(r0_0, r0_1); + r1_0 = vaddq_u32(r1_0, r1_1); + r2_0 = vaddq_u32(r2_0, r2_1); + r3_0 = vaddq_u32(r3_0, r3_1); + + r0_3 = veorq_u32(r0_3, r0_0); + r1_3 = veorq_u32(r1_3, r1_0); + r2_3 = veorq_u32(r2_3, r2_0); + r3_3 = veorq_u32(r3_3, r3_0); + + r0_3 = RotateLeft<8>(r0_3); + r1_3 = RotateLeft<8>(r1_3); + r2_3 = RotateLeft<8>(r2_3); + r3_3 = RotateLeft<8>(r3_3); + + r0_2 = vaddq_u32(r0_2, r0_3); + r1_2 = vaddq_u32(r1_2, r1_3); + r2_2 = vaddq_u32(r2_2, r2_3); + r3_2 = vaddq_u32(r3_2, r3_3); + + r0_1 = veorq_u32(r0_1, r0_2); + r1_1 = veorq_u32(r1_1, r1_2); + r2_1 = veorq_u32(r2_1, r2_2); + r3_1 = veorq_u32(r3_1, r3_2); + + r0_1 = RotateLeft<7>(r0_1); + r1_1 = RotateLeft<7>(r1_1); + r2_1 = RotateLeft<7>(r2_1); + r3_1 = RotateLeft<7>(r3_1); + + r0_1 = Extract<3>(r0_1); + r0_2 = Extract<2>(r0_2); + r0_3 = Extract<1>(r0_3); + + r1_1 = Extract<3>(r1_1); + r1_2 = Extract<2>(r1_2); + r1_3 = Extract<1>(r1_3); + + r2_1 = Extract<3>(r2_1); + r2_2 = Extract<2>(r2_2); + r2_3 = Extract<1>(r2_3); + + r3_1 = Extract<3>(r3_1); + r3_2 = Extract<2>(r3_2); + r3_3 = Extract<1>(r3_3); + } + + r0_0 = vaddq_u32(r0_0, state0); + r0_1 = vaddq_u32(r0_1, state1); + r0_2 = vaddq_u32(r0_2, state2); + r0_3 = vaddq_u32(r0_3, state3); + + r1_0 = vaddq_u32(r1_0, state0); + r1_1 = vaddq_u32(r1_1, state1); + r1_2 = vaddq_u32(r1_2, state2); + r1_3 = vaddq_u32(r1_3, state3); + r1_3 = Add64(r1_3, CTRS[0]); + + r2_0 = vaddq_u32(r2_0, state0); + r2_1 = vaddq_u32(r2_1, state1); + r2_2 = vaddq_u32(r2_2, state2); + r2_3 = vaddq_u32(r2_3, state3); + r2_3 = Add64(r2_3, CTRS[1]); + + r3_0 = vaddq_u32(r3_0, state0); + r3_1 = vaddq_u32(r3_1, state1); + r3_2 = vaddq_u32(r3_2, state2); + r3_3 = vaddq_u32(r3_3, state3); + r3_3 = Add64(r3_3, CTRS[2]); + + if (input) + { + r0_0 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 0*16)), r0_0); + r0_1 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 1*16)), r0_1); + r0_2 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 2*16)), r0_2); + r0_3 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 3*16)), r0_3); + } + + vst1q_u8(output + 0*16, vreinterpretq_u8_u32(r0_0)); + vst1q_u8(output + 1*16, vreinterpretq_u8_u32(r0_1)); + vst1q_u8(output + 2*16, vreinterpretq_u8_u32(r0_2)); + vst1q_u8(output + 3*16, vreinterpretq_u8_u32(r0_3)); + + if (input) + { + r1_0 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 4*16)), r1_0); + r1_1 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 5*16)), r1_1); + r1_2 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 6*16)), r1_2); + r1_3 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 7*16)), r1_3); + } + + vst1q_u8(output + 4*16, vreinterpretq_u8_u32(r1_0)); + vst1q_u8(output + 5*16, vreinterpretq_u8_u32(r1_1)); + vst1q_u8(output + 6*16, vreinterpretq_u8_u32(r1_2)); + vst1q_u8(output + 7*16, vreinterpretq_u8_u32(r1_3)); + + if (input) + { + r2_0 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 8*16)), r2_0); + r2_1 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 9*16)), r2_1); + r2_2 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 10*16)), r2_2); + r2_3 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 11*16)), r2_3); + } + + vst1q_u8(output + 8*16, vreinterpretq_u8_u32(r2_0)); + vst1q_u8(output + 9*16, vreinterpretq_u8_u32(r2_1)); + vst1q_u8(output + 10*16, vreinterpretq_u8_u32(r2_2)); + vst1q_u8(output + 11*16, vreinterpretq_u8_u32(r2_3)); + + if (input) + { + r3_0 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 12*16)), r3_0); + r3_1 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 13*16)), r3_1); + r3_2 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 14*16)), r3_2); + r3_3 = veorq_u32(vreinterpretq_u32_u8(vld1q_u8(input + 15*16)), r3_3); + } + + vst1q_u8(output + 12*16, vreinterpretq_u8_u32(r3_0)); + vst1q_u8(output + 13*16, vreinterpretq_u8_u32(r3_1)); + vst1q_u8(output + 14*16, vreinterpretq_u8_u32(r3_2)); + vst1q_u8(output + 15*16, vreinterpretq_u8_u32(r3_3)); +} + +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +// ***************************** SSE2 ***************************** // + +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) + +void ChaCha_OperateKeystream_SSE2(const word32 *state, const byte* input, byte *output, unsigned int rounds) +{ + const __m128i state0 = _mm_load_si128(reinterpret_cast(state+0*4)); + const __m128i state1 = _mm_load_si128(reinterpret_cast(state+1*4)); + const __m128i state2 = _mm_load_si128(reinterpret_cast(state+2*4)); + const __m128i state3 = _mm_load_si128(reinterpret_cast(state+3*4)); + + __m128i r0_0 = state0; + __m128i r0_1 = state1; + __m128i r0_2 = state2; + __m128i r0_3 = state3; + + __m128i r1_0 = state0; + __m128i r1_1 = state1; + __m128i r1_2 = state2; + __m128i r1_3 = _mm_add_epi64(r0_3, _mm_set_epi32(0, 0, 0, 1)); + + __m128i r2_0 = state0; + __m128i r2_1 = state1; + __m128i r2_2 = state2; + __m128i r2_3 = _mm_add_epi64(r0_3, _mm_set_epi32(0, 0, 0, 2)); + + __m128i r3_0 = state0; + __m128i r3_1 = state1; + __m128i r3_2 = state2; + __m128i r3_3 = _mm_add_epi64(r0_3, _mm_set_epi32(0, 0, 0, 3)); + + for (int i = static_cast(rounds); i > 0; i -= 2) + { + r0_0 = _mm_add_epi32(r0_0, r0_1); + r1_0 = _mm_add_epi32(r1_0, r1_1); + r2_0 = _mm_add_epi32(r2_0, r2_1); + r3_0 = _mm_add_epi32(r3_0, r3_1); + + r0_3 = _mm_xor_si128(r0_3, r0_0); + r1_3 = _mm_xor_si128(r1_3, r1_0); + r2_3 = _mm_xor_si128(r2_3, r2_0); + r3_3 = _mm_xor_si128(r3_3, r3_0); + + r0_3 = RotateLeft<16>(r0_3); + r1_3 = RotateLeft<16>(r1_3); + r2_3 = RotateLeft<16>(r2_3); + r3_3 = RotateLeft<16>(r3_3); + + r0_2 = _mm_add_epi32(r0_2, r0_3); + r1_2 = _mm_add_epi32(r1_2, r1_3); + r2_2 = _mm_add_epi32(r2_2, r2_3); + r3_2 = _mm_add_epi32(r3_2, r3_3); + + r0_1 = _mm_xor_si128(r0_1, r0_2); + r1_1 = _mm_xor_si128(r1_1, r1_2); + r2_1 = _mm_xor_si128(r2_1, r2_2); + r3_1 = _mm_xor_si128(r3_1, r3_2); + + r0_1 = RotateLeft<12>(r0_1); + r1_1 = RotateLeft<12>(r1_1); + r2_1 = RotateLeft<12>(r2_1); + r3_1 = RotateLeft<12>(r3_1); + + r0_0 = _mm_add_epi32(r0_0, r0_1); + r1_0 = _mm_add_epi32(r1_0, r1_1); + r2_0 = _mm_add_epi32(r2_0, r2_1); + r3_0 = _mm_add_epi32(r3_0, r3_1); + + r0_3 = _mm_xor_si128(r0_3, r0_0); + r1_3 = _mm_xor_si128(r1_3, r1_0); + r2_3 = _mm_xor_si128(r2_3, r2_0); + r3_3 = _mm_xor_si128(r3_3, r3_0); + + r0_3 = RotateLeft<8>(r0_3); + r1_3 = RotateLeft<8>(r1_3); + r2_3 = RotateLeft<8>(r2_3); + r3_3 = RotateLeft<8>(r3_3); + + r0_2 = _mm_add_epi32(r0_2, r0_3); + r1_2 = _mm_add_epi32(r1_2, r1_3); + r2_2 = _mm_add_epi32(r2_2, r2_3); + r3_2 = _mm_add_epi32(r3_2, r3_3); + + r0_1 = _mm_xor_si128(r0_1, r0_2); + r1_1 = _mm_xor_si128(r1_1, r1_2); + r2_1 = _mm_xor_si128(r2_1, r2_2); + r3_1 = _mm_xor_si128(r3_1, r3_2); + + r0_1 = RotateLeft<7>(r0_1); + r1_1 = RotateLeft<7>(r1_1); + r2_1 = RotateLeft<7>(r2_1); + r3_1 = RotateLeft<7>(r3_1); + + r0_1 = _mm_shuffle_epi32(r0_1, _MM_SHUFFLE(0, 3, 2, 1)); + r0_2 = _mm_shuffle_epi32(r0_2, _MM_SHUFFLE(1, 0, 3, 2)); + r0_3 = _mm_shuffle_epi32(r0_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r1_1 = _mm_shuffle_epi32(r1_1, _MM_SHUFFLE(0, 3, 2, 1)); + r1_2 = _mm_shuffle_epi32(r1_2, _MM_SHUFFLE(1, 0, 3, 2)); + r1_3 = _mm_shuffle_epi32(r1_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r2_1 = _mm_shuffle_epi32(r2_1, _MM_SHUFFLE(0, 3, 2, 1)); + r2_2 = _mm_shuffle_epi32(r2_2, _MM_SHUFFLE(1, 0, 3, 2)); + r2_3 = _mm_shuffle_epi32(r2_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r3_1 = _mm_shuffle_epi32(r3_1, _MM_SHUFFLE(0, 3, 2, 1)); + r3_2 = _mm_shuffle_epi32(r3_2, _MM_SHUFFLE(1, 0, 3, 2)); + r3_3 = _mm_shuffle_epi32(r3_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r0_0 = _mm_add_epi32(r0_0, r0_1); + r1_0 = _mm_add_epi32(r1_0, r1_1); + r2_0 = _mm_add_epi32(r2_0, r2_1); + r3_0 = _mm_add_epi32(r3_0, r3_1); + + r0_3 = _mm_xor_si128(r0_3, r0_0); + r1_3 = _mm_xor_si128(r1_3, r1_0); + r2_3 = _mm_xor_si128(r2_3, r2_0); + r3_3 = _mm_xor_si128(r3_3, r3_0); + + r0_3 = RotateLeft<16>(r0_3); + r1_3 = RotateLeft<16>(r1_3); + r2_3 = RotateLeft<16>(r2_3); + r3_3 = RotateLeft<16>(r3_3); + + r0_2 = _mm_add_epi32(r0_2, r0_3); + r1_2 = _mm_add_epi32(r1_2, r1_3); + r2_2 = _mm_add_epi32(r2_2, r2_3); + r3_2 = _mm_add_epi32(r3_2, r3_3); + + r0_1 = _mm_xor_si128(r0_1, r0_2); + r1_1 = _mm_xor_si128(r1_1, r1_2); + r2_1 = _mm_xor_si128(r2_1, r2_2); + r3_1 = _mm_xor_si128(r3_1, r3_2); + + r0_1 = RotateLeft<12>(r0_1); + r1_1 = RotateLeft<12>(r1_1); + r2_1 = RotateLeft<12>(r2_1); + r3_1 = RotateLeft<12>(r3_1); + + r0_0 = _mm_add_epi32(r0_0, r0_1); + r1_0 = _mm_add_epi32(r1_0, r1_1); + r2_0 = _mm_add_epi32(r2_0, r2_1); + r3_0 = _mm_add_epi32(r3_0, r3_1); + + r0_3 = _mm_xor_si128(r0_3, r0_0); + r1_3 = _mm_xor_si128(r1_3, r1_0); + r2_3 = _mm_xor_si128(r2_3, r2_0); + r3_3 = _mm_xor_si128(r3_3, r3_0); + + r0_3 = RotateLeft<8>(r0_3); + r1_3 = RotateLeft<8>(r1_3); + r2_3 = RotateLeft<8>(r2_3); + r3_3 = RotateLeft<8>(r3_3); + + r0_2 = _mm_add_epi32(r0_2, r0_3); + r1_2 = _mm_add_epi32(r1_2, r1_3); + r2_2 = _mm_add_epi32(r2_2, r2_3); + r3_2 = _mm_add_epi32(r3_2, r3_3); + + r0_1 = _mm_xor_si128(r0_1, r0_2); + r1_1 = _mm_xor_si128(r1_1, r1_2); + r2_1 = _mm_xor_si128(r2_1, r2_2); + r3_1 = _mm_xor_si128(r3_1, r3_2); + + r0_1 = RotateLeft<7>(r0_1); + r1_1 = RotateLeft<7>(r1_1); + r2_1 = RotateLeft<7>(r2_1); + r3_1 = RotateLeft<7>(r3_1); + + r0_1 = _mm_shuffle_epi32(r0_1, _MM_SHUFFLE(2, 1, 0, 3)); + r0_2 = _mm_shuffle_epi32(r0_2, _MM_SHUFFLE(1, 0, 3, 2)); + r0_3 = _mm_shuffle_epi32(r0_3, _MM_SHUFFLE(0, 3, 2, 1)); + + r1_1 = _mm_shuffle_epi32(r1_1, _MM_SHUFFLE(2, 1, 0, 3)); + r1_2 = _mm_shuffle_epi32(r1_2, _MM_SHUFFLE(1, 0, 3, 2)); + r1_3 = _mm_shuffle_epi32(r1_3, _MM_SHUFFLE(0, 3, 2, 1)); + + r2_1 = _mm_shuffle_epi32(r2_1, _MM_SHUFFLE(2, 1, 0, 3)); + r2_2 = _mm_shuffle_epi32(r2_2, _MM_SHUFFLE(1, 0, 3, 2)); + r2_3 = _mm_shuffle_epi32(r2_3, _MM_SHUFFLE(0, 3, 2, 1)); + + r3_1 = _mm_shuffle_epi32(r3_1, _MM_SHUFFLE(2, 1, 0, 3)); + r3_2 = _mm_shuffle_epi32(r3_2, _MM_SHUFFLE(1, 0, 3, 2)); + r3_3 = _mm_shuffle_epi32(r3_3, _MM_SHUFFLE(0, 3, 2, 1)); + } + + r0_0 = _mm_add_epi32(r0_0, state0); + r0_1 = _mm_add_epi32(r0_1, state1); + r0_2 = _mm_add_epi32(r0_2, state2); + r0_3 = _mm_add_epi32(r0_3, state3); + + r1_0 = _mm_add_epi32(r1_0, state0); + r1_1 = _mm_add_epi32(r1_1, state1); + r1_2 = _mm_add_epi32(r1_2, state2); + r1_3 = _mm_add_epi32(r1_3, state3); + r1_3 = _mm_add_epi64(r1_3, _mm_set_epi32(0, 0, 0, 1)); + + r2_0 = _mm_add_epi32(r2_0, state0); + r2_1 = _mm_add_epi32(r2_1, state1); + r2_2 = _mm_add_epi32(r2_2, state2); + r2_3 = _mm_add_epi32(r2_3, state3); + r2_3 = _mm_add_epi64(r2_3, _mm_set_epi32(0, 0, 0, 2)); + + r3_0 = _mm_add_epi32(r3_0, state0); + r3_1 = _mm_add_epi32(r3_1, state1); + r3_2 = _mm_add_epi32(r3_2, state2); + r3_3 = _mm_add_epi32(r3_3, state3); + r3_3 = _mm_add_epi64(r3_3, _mm_set_epi32(0, 0, 0, 3)); + + if (input) + { + r0_0 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+0*16)), r0_0); + r0_1 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+1*16)), r0_1); + r0_2 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+2*16)), r0_2); + r0_3 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+3*16)), r0_3); + } + + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+0*16), r0_0); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+1*16), r0_1); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+2*16), r0_2); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+3*16), r0_3); + + if (input) + { + r1_0 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+4*16)), r1_0); + r1_1 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+5*16)), r1_1); + r1_2 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+6*16)), r1_2); + r1_3 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+7*16)), r1_3); + } + + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+4*16), r1_0); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+5*16), r1_1); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+6*16), r1_2); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+7*16), r1_3); + + if (input) + { + r2_0 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+ 8*16)), r2_0); + r2_1 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+ 9*16)), r2_1); + r2_2 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+10*16)), r2_2); + r2_3 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+11*16)), r2_3); + } + + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+ 8*16), r2_0); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+ 9*16), r2_1); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+10*16), r2_2); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+11*16), r2_3); + + if (input) + { + r3_0 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+12*16)), r3_0); + r3_1 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+13*16)), r3_1); + r3_2 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+14*16)), r3_2); + r3_3 = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast(input+15*16)), r3_3); + } + + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+12*16), r3_0); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+13*16), r3_1); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+14*16), r3_2); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output+15*16), r3_3); +} + +#endif // CRYPTOPP_SSE2_INTRIN_AVAILABLE + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + +// ChaCha_OperateKeystream_CORE will use either POWER7 or ALTIVEC, +// depending on the flags used to compile this source file. The +// abstractions are handled in VecLoad, VecStore and friends. In +// the future we may to provide both POWER7 or ALTIVEC at the same +// time to better support distros. +inline void ChaCha_OperateKeystream_CORE(const word32 *state, const byte* input, byte *output, unsigned int rounds) +{ + const uint32x4_p state0 = VecLoadAligned(state + 0*4); + const uint32x4_p state1 = VecLoadAligned(state + 1*4); + const uint32x4_p state2 = VecLoadAligned(state + 2*4); + const uint32x4_p state3 = VecLoadAligned(state + 3*4); + + const uint32x4_p CTRS[3] = { + {1,0,0,0}, {2,0,0,0}, {3,0,0,0} + }; + + uint32x4_p r0_0 = state0; + uint32x4_p r0_1 = state1; + uint32x4_p r0_2 = state2; + uint32x4_p r0_3 = state3; + + uint32x4_p r1_0 = state0; + uint32x4_p r1_1 = state1; + uint32x4_p r1_2 = state2; + uint32x4_p r1_3 = VecAdd64(r0_3, CTRS[0]); + + uint32x4_p r2_0 = state0; + uint32x4_p r2_1 = state1; + uint32x4_p r2_2 = state2; + uint32x4_p r2_3 = VecAdd64(r0_3, CTRS[1]); + + uint32x4_p r3_0 = state0; + uint32x4_p r3_1 = state1; + uint32x4_p r3_2 = state2; + uint32x4_p r3_3 = VecAdd64(r0_3, CTRS[2]); + + for (int i = static_cast(rounds); i > 0; i -= 2) + { + r0_0 = VecAdd(r0_0, r0_1); + r1_0 = VecAdd(r1_0, r1_1); + r2_0 = VecAdd(r2_0, r2_1); + r3_0 = VecAdd(r3_0, r3_1); + + r0_3 = VecXor(r0_3, r0_0); + r1_3 = VecXor(r1_3, r1_0); + r2_3 = VecXor(r2_3, r2_0); + r3_3 = VecXor(r3_3, r3_0); + + r0_3 = VecRotateLeft<16>(r0_3); + r1_3 = VecRotateLeft<16>(r1_3); + r2_3 = VecRotateLeft<16>(r2_3); + r3_3 = VecRotateLeft<16>(r3_3); + + r0_2 = VecAdd(r0_2, r0_3); + r1_2 = VecAdd(r1_2, r1_3); + r2_2 = VecAdd(r2_2, r2_3); + r3_2 = VecAdd(r3_2, r3_3); + + r0_1 = VecXor(r0_1, r0_2); + r1_1 = VecXor(r1_1, r1_2); + r2_1 = VecXor(r2_1, r2_2); + r3_1 = VecXor(r3_1, r3_2); + + r0_1 = VecRotateLeft<12>(r0_1); + r1_1 = VecRotateLeft<12>(r1_1); + r2_1 = VecRotateLeft<12>(r2_1); + r3_1 = VecRotateLeft<12>(r3_1); + + r0_0 = VecAdd(r0_0, r0_1); + r1_0 = VecAdd(r1_0, r1_1); + r2_0 = VecAdd(r2_0, r2_1); + r3_0 = VecAdd(r3_0, r3_1); + + r0_3 = VecXor(r0_3, r0_0); + r1_3 = VecXor(r1_3, r1_0); + r2_3 = VecXor(r2_3, r2_0); + r3_3 = VecXor(r3_3, r3_0); + + r0_3 = VecRotateLeft<8>(r0_3); + r1_3 = VecRotateLeft<8>(r1_3); + r2_3 = VecRotateLeft<8>(r2_3); + r3_3 = VecRotateLeft<8>(r3_3); + + r0_2 = VecAdd(r0_2, r0_3); + r1_2 = VecAdd(r1_2, r1_3); + r2_2 = VecAdd(r2_2, r2_3); + r3_2 = VecAdd(r3_2, r3_3); + + r0_1 = VecXor(r0_1, r0_2); + r1_1 = VecXor(r1_1, r1_2); + r2_1 = VecXor(r2_1, r2_2); + r3_1 = VecXor(r3_1, r3_2); + + r0_1 = VecRotateLeft<7>(r0_1); + r1_1 = VecRotateLeft<7>(r1_1); + r2_1 = VecRotateLeft<7>(r2_1); + r3_1 = VecRotateLeft<7>(r3_1); + + r0_1 = Shuffle<1>(r0_1); + r0_2 = Shuffle<2>(r0_2); + r0_3 = Shuffle<3>(r0_3); + + r1_1 = Shuffle<1>(r1_1); + r1_2 = Shuffle<2>(r1_2); + r1_3 = Shuffle<3>(r1_3); + + r2_1 = Shuffle<1>(r2_1); + r2_2 = Shuffle<2>(r2_2); + r2_3 = Shuffle<3>(r2_3); + + r3_1 = Shuffle<1>(r3_1); + r3_2 = Shuffle<2>(r3_2); + r3_3 = Shuffle<3>(r3_3); + + r0_0 = VecAdd(r0_0, r0_1); + r1_0 = VecAdd(r1_0, r1_1); + r2_0 = VecAdd(r2_0, r2_1); + r3_0 = VecAdd(r3_0, r3_1); + + r0_3 = VecXor(r0_3, r0_0); + r1_3 = VecXor(r1_3, r1_0); + r2_3 = VecXor(r2_3, r2_0); + r3_3 = VecXor(r3_3, r3_0); + + r0_3 = VecRotateLeft<16>(r0_3); + r1_3 = VecRotateLeft<16>(r1_3); + r2_3 = VecRotateLeft<16>(r2_3); + r3_3 = VecRotateLeft<16>(r3_3); + + r0_2 = VecAdd(r0_2, r0_3); + r1_2 = VecAdd(r1_2, r1_3); + r2_2 = VecAdd(r2_2, r2_3); + r3_2 = VecAdd(r3_2, r3_3); + + r0_1 = VecXor(r0_1, r0_2); + r1_1 = VecXor(r1_1, r1_2); + r2_1 = VecXor(r2_1, r2_2); + r3_1 = VecXor(r3_1, r3_2); + + r0_1 = VecRotateLeft<12>(r0_1); + r1_1 = VecRotateLeft<12>(r1_1); + r2_1 = VecRotateLeft<12>(r2_1); + r3_1 = VecRotateLeft<12>(r3_1); + + r0_0 = VecAdd(r0_0, r0_1); + r1_0 = VecAdd(r1_0, r1_1); + r2_0 = VecAdd(r2_0, r2_1); + r3_0 = VecAdd(r3_0, r3_1); + + r0_3 = VecXor(r0_3, r0_0); + r1_3 = VecXor(r1_3, r1_0); + r2_3 = VecXor(r2_3, r2_0); + r3_3 = VecXor(r3_3, r3_0); + + r0_3 = VecRotateLeft<8>(r0_3); + r1_3 = VecRotateLeft<8>(r1_3); + r2_3 = VecRotateLeft<8>(r2_3); + r3_3 = VecRotateLeft<8>(r3_3); + + r0_2 = VecAdd(r0_2, r0_3); + r1_2 = VecAdd(r1_2, r1_3); + r2_2 = VecAdd(r2_2, r2_3); + r3_2 = VecAdd(r3_2, r3_3); + + r0_1 = VecXor(r0_1, r0_2); + r1_1 = VecXor(r1_1, r1_2); + r2_1 = VecXor(r2_1, r2_2); + r3_1 = VecXor(r3_1, r3_2); + + r0_1 = VecRotateLeft<7>(r0_1); + r1_1 = VecRotateLeft<7>(r1_1); + r2_1 = VecRotateLeft<7>(r2_1); + r3_1 = VecRotateLeft<7>(r3_1); + + r0_1 = Shuffle<3>(r0_1); + r0_2 = Shuffle<2>(r0_2); + r0_3 = Shuffle<1>(r0_3); + + r1_1 = Shuffle<3>(r1_1); + r1_2 = Shuffle<2>(r1_2); + r1_3 = Shuffle<1>(r1_3); + + r2_1 = Shuffle<3>(r2_1); + r2_2 = Shuffle<2>(r2_2); + r2_3 = Shuffle<1>(r2_3); + + r3_1 = Shuffle<3>(r3_1); + r3_2 = Shuffle<2>(r3_2); + r3_3 = Shuffle<1>(r3_3); + } + + r0_0 = VecAdd(r0_0, state0); + r0_1 = VecAdd(r0_1, state1); + r0_2 = VecAdd(r0_2, state2); + r0_3 = VecAdd(r0_3, state3); + + r1_0 = VecAdd(r1_0, state0); + r1_1 = VecAdd(r1_1, state1); + r1_2 = VecAdd(r1_2, state2); + r1_3 = VecAdd(r1_3, state3); + r1_3 = VecAdd64(r1_3, CTRS[0]); + + r2_0 = VecAdd(r2_0, state0); + r2_1 = VecAdd(r2_1, state1); + r2_2 = VecAdd(r2_2, state2); + r2_3 = VecAdd(r2_3, state3); + r2_3 = VecAdd64(r2_3, CTRS[1]); + + r3_0 = VecAdd(r3_0, state0); + r3_1 = VecAdd(r3_1, state1); + r3_2 = VecAdd(r3_2, state2); + r3_3 = VecAdd(r3_3, state3); + r3_3 = VecAdd64(r3_3, CTRS[2]); + + if (input) + { + r0_0 = VecXor(VecLoad32LE(input + 0*16), r0_0); + r0_1 = VecXor(VecLoad32LE(input + 1*16), r0_1); + r0_2 = VecXor(VecLoad32LE(input + 2*16), r0_2); + r0_3 = VecXor(VecLoad32LE(input + 3*16), r0_3); + } + + VecStore32LE(output + 0*16, r0_0); + VecStore32LE(output + 1*16, r0_1); + VecStore32LE(output + 2*16, r0_2); + VecStore32LE(output + 3*16, r0_3); + + if (input) + { + r1_0 = VecXor(VecLoad32LE(input + 4*16), r1_0); + r1_1 = VecXor(VecLoad32LE(input + 5*16), r1_1); + r1_2 = VecXor(VecLoad32LE(input + 6*16), r1_2); + r1_3 = VecXor(VecLoad32LE(input + 7*16), r1_3); + } + + VecStore32LE(output + 4*16, r1_0); + VecStore32LE(output + 5*16, r1_1); + VecStore32LE(output + 6*16, r1_2); + VecStore32LE(output + 7*16, r1_3); + + if (input) + { + r2_0 = VecXor(VecLoad32LE(input + 8*16), r2_0); + r2_1 = VecXor(VecLoad32LE(input + 9*16), r2_1); + r2_2 = VecXor(VecLoad32LE(input + 10*16), r2_2); + r2_3 = VecXor(VecLoad32LE(input + 11*16), r2_3); + } + + VecStore32LE(output + 8*16, r2_0); + VecStore32LE(output + 9*16, r2_1); + VecStore32LE(output + 10*16, r2_2); + VecStore32LE(output + 11*16, r2_3); + + if (input) + { + r3_0 = VecXor(VecLoad32LE(input + 12*16), r3_0); + r3_1 = VecXor(VecLoad32LE(input + 13*16), r3_1); + r3_2 = VecXor(VecLoad32LE(input + 14*16), r3_2); + r3_3 = VecXor(VecLoad32LE(input + 15*16), r3_3); + } + + VecStore32LE(output + 12*16, r3_0); + VecStore32LE(output + 13*16, r3_1); + VecStore32LE(output + 14*16, r3_2); + VecStore32LE(output + 15*16, r3_3); +} + +#endif // CRYPTOPP_ALTIVEC_AVAILABLE + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + +void ChaCha_OperateKeystream_ALTIVEC(const word32 *state, const byte* input, byte *output, unsigned int rounds) +{ + ChaCha_OperateKeystream_CORE(state, input, output, rounds); +} + +#endif + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/chachapoly.cpp b/external/ours/library/crypto/src/shared/original/chachapoly.cpp new file mode 100755 index 000000000..934740605 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/chachapoly.cpp @@ -0,0 +1,211 @@ +// chachapoly.cpp - written and placed in the public domain by Jeffrey Walton +// RFC 8439, Section 2.8, AEAD Construction, http://tools.ietf.org/html/rfc8439 + +#include "pch.h" +#include "chachapoly.h" +#include "algparam.h" +#include "misc.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4244) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +////////////////////////////// IETF ChaChaTLS ////////////////////////////// + +// RekeyCipherAndMac is heavier-weight than we like. The Authenc framework was +// predicated on BlockCiphers, where the key and key schedule could be +// calculated independent of the IV being used. However, the ChaCha and +// ChaCha20Poly1305 construction combines key setup and IV. That is, both are +// needed to key or rekey the cipher. Even a simple Resync() requires us to +// regenerate the initial state for both ChaCha20 and Poly1305. +void ChaCha20Poly1305_Base::RekeyCipherAndMac(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) +{ + // Derive MAC key + AlgorithmParameters block0 = MakeParameters("InitialBlock", (word64)0, true); + AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block0)); + + // Only the first 256-bits are used to key the MAC + SecByteBlock derived(NULLPTR, 32); + AccessSymmetricCipher().ProcessString(derived, derived.size()); + + // Key the Poly1305 MAC + AccessMAC().SetKey(derived, derived.size(), params); + + // Key the ChaCha20 cipher + AlgorithmParameters block1 = MakeParameters("InitialBlock", (word64)1, true); + AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block1)); +} + +void ChaCha20Poly1305_Base::SetKeyWithoutResync(const byte *userKey, size_t userKeyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_ASSERT(userKey && userKeyLength == 32); + m_userKey.Assign(userKey, userKeyLength); + + // ChaCha/Poly1305 initial state depends on both the key and IV. The + // IV may or may not be present during the call to SetKeyWithoutResync. + // If the IV is present, the framework will call SetKeyWithoutResync + // followed by Resynchronize which calls Resync. In this case we defer + // calculating the initial state until the call to Resynchronize. + // If the IV is not present, it avoids calling ChaCha's SetKey without + // an IV, which results in an exception. In this case the user will need + // to call Resynchronize to key ChaCha and Poly1305. + // RekeyCipherAndMac(userKey, userKeyLength, params); + CRYPTOPP_UNUSED(params); +} + +void ChaCha20Poly1305_Base::Resync(const byte *iv, size_t len) +{ + CRYPTOPP_ASSERT(iv && len == 12); + RekeyCipherAndMac(m_userKey, m_userKey.SizeInBytes(), + MakeParameters(Name::IV(), ConstByteArrayParameter(iv,len))); +} + +size_t ChaCha20Poly1305_Base::AuthenticateBlocks(const byte *data, size_t len) +{ + AccessMAC().Update(data, len); + return 0; +} + +void ChaCha20Poly1305_Base::AuthenticateLastHeaderBlock() +{ + // Pad to a multiple of 16 or 0 + const byte zero[16] = {0}; + size_t pad = (16U - (m_totalHeaderLength % 16)) % 16; + AccessMAC().Update(zero, pad); +} + +void ChaCha20Poly1305_Base::AuthenticateLastConfidentialBlock() +{ + // Pad to a multiple of 16 or 0 + const byte zero[16] = {0}; + size_t pad = (16U - (m_totalMessageLength % 16)) % 16; + AccessMAC().Update(zero, pad); +} + +void ChaCha20Poly1305_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize) +{ + CRYPTOPP_ALIGN_DATA(8) byte length[2*sizeof(word64)]; + PutWord(true, LITTLE_ENDIAN_ORDER, length+0, m_totalHeaderLength); + PutWord(true, LITTLE_ENDIAN_ORDER, length+8, m_totalMessageLength); + AccessMAC().Update(length, sizeof(length)); + AccessMAC().TruncatedFinal(mac, macSize); + m_state = State_KeySet; +} + +void ChaCha20Poly1305_Base::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) +{ + Resynchronize(iv, ivLength); + Update(aad, aadLength); + ProcessString(ciphertext, message, messageLength); + TruncatedFinal(mac, macSize); +} + +bool ChaCha20Poly1305_Base::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength) +{ + Resynchronize(iv, ivLength); + Update(aad, aadLength); + ProcessString(message, ciphertext, ciphertextLength); + return TruncatedVerify(mac, macLength); +} + +////////////////////////////// IETF XChaCha20 draft ////////////////////////////// + +// RekeyCipherAndMac is heavier-weight than we like. The Authenc framework was +// predicated on BlockCiphers, where the key and key schedule could be +// calculated independent of the IV being used. However, the ChaCha and +// ChaCha20Poly1305 construction combines key setup and IV. That is, both are +// needed to key or rekey the cipher. Even a simple Resync() requires us to +// regenerate the initial state for both ChaCha20 and Poly1305. +void XChaCha20Poly1305_Base::RekeyCipherAndMac(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) +{ + // Derive MAC key + AlgorithmParameters block0 = MakeParameters("InitialBlock", (word64)0, true); + AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block0)); + + // Only the first 256-bits are used to key the MAC + SecByteBlock derived(NULLPTR, 32); + AccessSymmetricCipher().ProcessString(derived, derived.size()); + + // Key the Poly1305 MAC + AccessMAC().SetKey(derived, derived.size(), params); + + // Key the ChaCha20 cipher + AlgorithmParameters block1 = MakeParameters("InitialBlock", (word64)1, true); + AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block1)); +} + +void XChaCha20Poly1305_Base::SetKeyWithoutResync(const byte *userKey, size_t userKeyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_ASSERT(userKey && userKeyLength == 32); + m_userKey.Assign(userKey, userKeyLength); + + // XChaCha20/Poly1305 initial state depends on both the key and IV. The + // IV may or may not be present during the call to SetKeyWithoutResync. + // If the IV is present, the framework will call SetKeyWithoutResync + // followed by Resynchronize which calls Resync. In this case we defer + // calculating the initial state until the call to Resynchronize. + // If the IV is not present, it avoids calling ChaCha's SetKey without + // an IV, which results in an exception. In this case the user will need + // to call Resynchronize to key ChaCha and Poly1305. + // RekeyCipherAndMac(userKey, userKeyLength, params); + CRYPTOPP_UNUSED(params); +} + +void XChaCha20Poly1305_Base::Resync(const byte *iv, size_t len) +{ + CRYPTOPP_ASSERT(iv && len == 24); + RekeyCipherAndMac(m_userKey, m_userKey.SizeInBytes(), + MakeParameters(Name::IV(), ConstByteArrayParameter(iv,len))); +} + +size_t XChaCha20Poly1305_Base::AuthenticateBlocks(const byte *data, size_t len) +{ + AccessMAC().Update(data, len); + return 0; +} + +void XChaCha20Poly1305_Base::AuthenticateLastHeaderBlock() +{ + // Pad to a multiple of 16 or 0 + const byte zero[16] = {0}; + size_t pad = (16 - (m_totalHeaderLength % 16)) % 16; + AccessMAC().Update(zero, pad); +} + +void XChaCha20Poly1305_Base::AuthenticateLastConfidentialBlock() +{ + // Pad to a multiple of 16 or 0 + const byte zero[16] = {0}; + size_t pad = (16 - (m_totalMessageLength % 16)) % 16; + AccessMAC().Update(zero, pad); +} + +void XChaCha20Poly1305_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize) +{ + CRYPTOPP_ALIGN_DATA(8) byte length[2*sizeof(word64)]; + PutWord(true, LITTLE_ENDIAN_ORDER, length+0, m_totalHeaderLength); + PutWord(true, LITTLE_ENDIAN_ORDER, length+8, m_totalMessageLength); + AccessMAC().Update(length, sizeof(length)); + AccessMAC().TruncatedFinal(mac, macSize); + m_state = State_KeySet; +} + +void XChaCha20Poly1305_Base::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) +{ + Resynchronize(iv, ivLength); + Update(aad, aadLength); + ProcessString(ciphertext, message, messageLength); + TruncatedFinal(mac, macSize); +} + +bool XChaCha20Poly1305_Base::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength) +{ + Resynchronize(iv, ivLength); + Update(aad, aadLength); + ProcessString(message, ciphertext, ciphertextLength); + return TruncatedVerify(mac, macLength); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/chachapoly.h b/external/ours/library/crypto/src/shared/original/chachapoly.h new file mode 100755 index 000000000..e480456db --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/cham.cpp b/external/ours/library/crypto/src/shared/original/cham.cpp new file mode 100755 index 000000000..6cd5d1c26 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/cham.cpp @@ -0,0 +1,365 @@ +// cham.cpp - 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 + +#include "pch.h" +#include "config.h" + +#include "cham.h" +#include "misc.h" +#include "cpu.h" + +// CHAM table of parameters +// +------------------------------------------------- +// +cipher n k r w k/w +// +------------------------------------------------- +// +CHAM-64/128 64 128 80 16 8 +// +CHAM-128/128 128 128 80 32 4 +// +CHAM-128/256 128 256 96 32 8 +// +------------------------------------------------- + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::rotlConstant; +using CryptoPP::rotrConstant; + +/// \brief CHAM encryption round +/// \tparam RR the round number residue +/// \tparam KW the number of key words +/// \tparam T words type +/// \param x the state array +/// \param k the subkey table +/// \param i the round number +/// \details CHAM_EncRound applies the encryption round to the plain text. +/// RR is the "round residue" and it is used modulo 4. ProcessAndXorBlock +/// may provide a fully unrolled encryption transformation, or provide +/// a transformation that loops using multiples of 4 encryption rounds. +/// \details CHAM_EncRound calculates indexes into the x[] array based +/// on the round number residue. There is no need for the assignments +/// that shift values in preparations for the next round. +/// \details CHAM_EncRound depends on the round number. The actual round +/// being executed is passed through the parameter i. If +/// ProcessAndXorBlock fully unrolled the loop then the parameter +/// i would be unnecessary. +template +inline void CHAM_EncRound(T x[4], const T k[KW], unsigned int i) +{ + CRYPTOPP_CONSTANT(IDX0 = (RR+0) % 4); + CRYPTOPP_CONSTANT(IDX1 = (RR+1) % 4); + CRYPTOPP_CONSTANT(IDX3 = (RR+3+1) % 4); + CRYPTOPP_CONSTANT(R1 = (RR % 2 == 0) ? 1 : 8); + CRYPTOPP_CONSTANT(R2 = (RR % 2 == 0) ? 8 : 1); + + // Follows conventions in the ref impl + const T kk = k[i % KW]; + const T aa = x[IDX0] ^ static_cast(i); + const T bb = rotlConstant(x[IDX1]) ^ kk; + x[IDX3] = rotlConstant(static_cast(aa + bb)); +} + +/// \brief CHAM decryption round +/// \tparam RR the round number residue +/// \tparam KW the number of key words +/// \tparam T words type +/// \param x the state array +/// \param k the subkey table +/// \param i the round number +/// \details CHAM_DecRound applies the decryption round to the cipher text. +/// RR is the "round residue" and it is used modulo 4. ProcessAndXorBlock +/// may provide a fully unrolled decryption transformation, or provide +/// a transformation that loops using multiples of 4 decryption rounds. +/// \details CHAM_DecRound calculates indexes into the x[] array based +/// on the round number residue. There is no need for the assignments +/// that shift values in preparations for the next round. +/// \details CHAM_DecRound depends on the round number. The actual round +/// being executed is passed through the parameter i. If +/// ProcessAndXorBlock fully unrolled the loop then the parameter +/// i would be unnecessary. +template +inline void CHAM_DecRound(T x[4], const T k[KW], unsigned int i) +{ + CRYPTOPP_CONSTANT(IDX0 = (RR+0) % 4); + CRYPTOPP_CONSTANT(IDX1 = (RR+1) % 4); + CRYPTOPP_CONSTANT(IDX3 = (RR+3+1) % 4); + CRYPTOPP_CONSTANT(R1 = (RR % 2 == 0) ? 8 : 1); + CRYPTOPP_CONSTANT(R2 = (RR % 2 == 0) ? 1 : 8); + + // Follows conventions in the ref impl + const T kk = k[i % KW]; + const T aa = rotrConstant(x[IDX3]); + const T bb = rotlConstant(x[IDX1]) ^ kk; + x[IDX0] = static_cast(aa - bb) ^ static_cast(i); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS +# if (CRYPTOPP_SSSE3_AVAILABLE) +extern size_t CHAM64_Enc_AdvancedProcessBlocks_SSSE3(const word16* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t CHAM64_Dec_AdvancedProcessBlocks_SSSE3(const word16* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t CHAM128_Enc_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t CHAM128_Dec_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +# endif // CRYPTOPP_SSSE3_AVAILABLE +#endif // CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS + +void CHAM64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + m_kw = keyLength/sizeof(word16); + m_rk.New(2*m_kw); + + for (size_t i = 0; i < m_kw; userKey += sizeof(word32)) + { + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + const word32 rk = GetWord(false, BIG_ENDIAN_ORDER, userKey); + + const word16 rk1 = static_cast(rk >> 16); + m_rk[i] = rk1 ^ rotlConstant<1>(rk1) ^ rotlConstant<8>(rk1); + m_rk[(i + m_kw) ^ 1] = rk1 ^ rotlConstant<1>(rk1) ^ rotlConstant<11>(rk1); + i++; + + const word16 rk2 = static_cast(rk & 0xffff); + m_rk[i] = rk2 ^ rotlConstant<1>(rk2) ^ rotlConstant<8>(rk2); + m_rk[(i + m_kw) ^ 1] = rk2 ^ rotlConstant<1>(rk2) ^ rotlConstant<11>(rk2); + i++; + } +} + +void CHAM64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]); + + const int R = 80; + for (int i = 0; i < R; i+=16) + { + CHAM_EncRound< 0, 16>(m_x.begin(), m_rk.begin(), i+0); + CHAM_EncRound< 1, 16>(m_x.begin(), m_rk.begin(), i+1); + CHAM_EncRound< 2, 16>(m_x.begin(), m_rk.begin(), i+2); + CHAM_EncRound< 3, 16>(m_x.begin(), m_rk.begin(), i+3); + CHAM_EncRound< 4, 16>(m_x.begin(), m_rk.begin(), i+4); + CHAM_EncRound< 5, 16>(m_x.begin(), m_rk.begin(), i+5); + CHAM_EncRound< 6, 16>(m_x.begin(), m_rk.begin(), i+6); + CHAM_EncRound< 7, 16>(m_x.begin(), m_rk.begin(), i+7); + CHAM_EncRound< 8, 16>(m_x.begin(), m_rk.begin(), i+8); + CHAM_EncRound< 9, 16>(m_x.begin(), m_rk.begin(), i+9); + CHAM_EncRound<10, 16>(m_x.begin(), m_rk.begin(), i+10); + CHAM_EncRound<11, 16>(m_x.begin(), m_rk.begin(), i+11); + CHAM_EncRound<12, 16>(m_x.begin(), m_rk.begin(), i+12); + CHAM_EncRound<13, 16>(m_x.begin(), m_rk.begin(), i+13); + CHAM_EncRound<14, 16>(m_x.begin(), m_rk.begin(), i+14); + CHAM_EncRound<15, 16>(m_x.begin(), m_rk.begin(), i+15); + } + + PutBlock oblock(xorBlock, outBlock); + oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]); +} + +void CHAM64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]); + + const int R = 80; + for (int i = R-1; i >=0 ; i-=16) + { + CHAM_DecRound<15, 16>(m_x.begin(), m_rk.begin(), i-0); + CHAM_DecRound<14, 16>(m_x.begin(), m_rk.begin(), i-1); + CHAM_DecRound<13, 16>(m_x.begin(), m_rk.begin(), i-2); + CHAM_DecRound<12, 16>(m_x.begin(), m_rk.begin(), i-3); + CHAM_DecRound<11, 16>(m_x.begin(), m_rk.begin(), i-4); + CHAM_DecRound<10, 16>(m_x.begin(), m_rk.begin(), i-5); + CHAM_DecRound< 9, 16>(m_x.begin(), m_rk.begin(), i-6); + CHAM_DecRound< 8, 16>(m_x.begin(), m_rk.begin(), i-7); + CHAM_DecRound< 7, 16>(m_x.begin(), m_rk.begin(), i-8); + CHAM_DecRound< 6, 16>(m_x.begin(), m_rk.begin(), i-9); + CHAM_DecRound< 5, 16>(m_x.begin(), m_rk.begin(), i-10); + CHAM_DecRound< 4, 16>(m_x.begin(), m_rk.begin(), i-11); + CHAM_DecRound< 3, 16>(m_x.begin(), m_rk.begin(), i-12); + CHAM_DecRound< 2, 16>(m_x.begin(), m_rk.begin(), i-13); + CHAM_DecRound< 1, 16>(m_x.begin(), m_rk.begin(), i-14); + CHAM_DecRound< 0, 16>(m_x.begin(), m_rk.begin(), i-15); + } + + PutBlock oblock(xorBlock, outBlock); + oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]); +} + +std::string CHAM128::Base::AlgorithmProvider() const +{ +#if defined(CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return "SSSE3"; +#endif + return "C++"; +} + +void CHAM128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + m_kw = keyLength/sizeof(word32); + m_rk.New(2*m_kw); + + for (size_t i = 0; i < m_kw; userKey += sizeof(word32)) + { + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + const word32 rk = GetWord(false, BIG_ENDIAN_ORDER, userKey); + m_rk[i] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<8>(rk); + m_rk[(i + m_kw) ^ 1] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<11>(rk); + i++; + } +} + +void CHAM128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]); + + switch (m_kw) + { + case 4: // 128-bit key + { + const int R = 80; + for (int i = 0; i < R; i+=8) + { + CHAM_EncRound<0, 8>(m_x.begin(), m_rk.begin(), i+0); + CHAM_EncRound<1, 8>(m_x.begin(), m_rk.begin(), i+1); + CHAM_EncRound<2, 8>(m_x.begin(), m_rk.begin(), i+2); + CHAM_EncRound<3, 8>(m_x.begin(), m_rk.begin(), i+3); + CHAM_EncRound<4, 8>(m_x.begin(), m_rk.begin(), i+4); + CHAM_EncRound<5, 8>(m_x.begin(), m_rk.begin(), i+5); + CHAM_EncRound<6, 8>(m_x.begin(), m_rk.begin(), i+6); + CHAM_EncRound<7, 8>(m_x.begin(), m_rk.begin(), i+7); + } + break; + } + case 8: // 256-bit key + { + const int R = 96; + for (int i = 0; i < R; i+=16) + { + CHAM_EncRound< 0, 16>(m_x.begin(), m_rk.begin(), i+0); + CHAM_EncRound< 1, 16>(m_x.begin(), m_rk.begin(), i+1); + CHAM_EncRound< 2, 16>(m_x.begin(), m_rk.begin(), i+2); + CHAM_EncRound< 3, 16>(m_x.begin(), m_rk.begin(), i+3); + CHAM_EncRound< 4, 16>(m_x.begin(), m_rk.begin(), i+4); + CHAM_EncRound< 5, 16>(m_x.begin(), m_rk.begin(), i+5); + CHAM_EncRound< 6, 16>(m_x.begin(), m_rk.begin(), i+6); + CHAM_EncRound< 7, 16>(m_x.begin(), m_rk.begin(), i+7); + CHAM_EncRound< 8, 16>(m_x.begin(), m_rk.begin(), i+8); + CHAM_EncRound< 9, 16>(m_x.begin(), m_rk.begin(), i+9); + CHAM_EncRound<10, 16>(m_x.begin(), m_rk.begin(), i+10); + CHAM_EncRound<11, 16>(m_x.begin(), m_rk.begin(), i+11); + CHAM_EncRound<12, 16>(m_x.begin(), m_rk.begin(), i+12); + CHAM_EncRound<13, 16>(m_x.begin(), m_rk.begin(), i+13); + CHAM_EncRound<14, 16>(m_x.begin(), m_rk.begin(), i+14); + CHAM_EncRound<15, 16>(m_x.begin(), m_rk.begin(), i+15); + } + break; + } + default: + CRYPTOPP_ASSERT(0); + } + + PutBlock oblock(xorBlock, outBlock); + oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]); +} + +void CHAM128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]); + + switch (m_kw) + { + case 4: // 128-bit key + { + const int R = 80; + for (int i = R-1; i >= 0; i-=8) + { + CHAM_DecRound<7, 8>(m_x.begin(), m_rk.begin(), i-0); + CHAM_DecRound<6, 8>(m_x.begin(), m_rk.begin(), i-1); + CHAM_DecRound<5, 8>(m_x.begin(), m_rk.begin(), i-2); + CHAM_DecRound<4, 8>(m_x.begin(), m_rk.begin(), i-3); + CHAM_DecRound<3, 8>(m_x.begin(), m_rk.begin(), i-4); + CHAM_DecRound<2, 8>(m_x.begin(), m_rk.begin(), i-5); + CHAM_DecRound<1, 8>(m_x.begin(), m_rk.begin(), i-6); + CHAM_DecRound<0, 8>(m_x.begin(), m_rk.begin(), i-7); + } + break; + } + case 8: // 256-bit key + { + const int R = 96; + for (int i = R-1; i >= 0; i-=16) + { + CHAM_DecRound<15, 16>(m_x.begin(), m_rk.begin(), i-0); + CHAM_DecRound<14, 16>(m_x.begin(), m_rk.begin(), i-1); + CHAM_DecRound<13, 16>(m_x.begin(), m_rk.begin(), i-2); + CHAM_DecRound<12, 16>(m_x.begin(), m_rk.begin(), i-3); + CHAM_DecRound<11, 16>(m_x.begin(), m_rk.begin(), i-4); + CHAM_DecRound<10, 16>(m_x.begin(), m_rk.begin(), i-5); + CHAM_DecRound< 9, 16>(m_x.begin(), m_rk.begin(), i-6); + CHAM_DecRound< 8, 16>(m_x.begin(), m_rk.begin(), i-7); + CHAM_DecRound< 7, 16>(m_x.begin(), m_rk.begin(), i-8); + CHAM_DecRound< 6, 16>(m_x.begin(), m_rk.begin(), i-9); + CHAM_DecRound< 5, 16>(m_x.begin(), m_rk.begin(), i-10); + CHAM_DecRound< 4, 16>(m_x.begin(), m_rk.begin(), i-11); + CHAM_DecRound< 3, 16>(m_x.begin(), m_rk.begin(), i-12); + CHAM_DecRound< 2, 16>(m_x.begin(), m_rk.begin(), i-13); + CHAM_DecRound< 1, 16>(m_x.begin(), m_rk.begin(), i-14); + CHAM_DecRound< 0, 16>(m_x.begin(), m_rk.begin(), i-15); + } + break; + } + default: + CRYPTOPP_ASSERT(0); + } + + PutBlock oblock(xorBlock, outBlock); + oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]); +} + +#if CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS +size_t CHAM128::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, + byte *outBlocks, size_t length, word32 flags) const +{ +# if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) { + const size_t rounds = (m_kw == 4 ? 80 : 96); + return CHAM128_Enc_AdvancedProcessBlocks_SSSE3(m_rk, rounds, + inBlocks, xorBlocks, outBlocks, length, flags); + } +# endif // CRYPTOPP_SSSE3_AVAILABLE + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t CHAM128::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, + byte *outBlocks, size_t length, word32 flags) const +{ +# if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) { + const size_t rounds = (m_kw == 4 ? 80 : 96); + return CHAM128_Dec_AdvancedProcessBlocks_SSSE3(m_rk, rounds, + inBlocks, xorBlocks, outBlocks, length, flags); + } +# endif // CRYPTOPP_SSSE3_AVAILABLE + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/cham.h b/external/ours/library/crypto/src/shared/original/cham.h new file mode 100755 index 000000000..5100dd45d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/cham_simd.cpp b/external/ours/library/crypto/src/shared/original/cham_simd.cpp new file mode 100755 index 000000000..b848ba107 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/cham_simd.cpp @@ -0,0 +1,478 @@ +// cham_simd.cpp - written and placed in the public domain by Jeffrey Walton +// +// This source file uses intrinsics and built-ins to gain access to +// SSSE3, ARM NEON and ARMv8a, and Power7 Altivec instructions. A separate +// source file is needed because additional CXXFLAGS are required to enable +// the appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" + +#include "cham.h" +#include "misc.h" + +// Uncomment for benchmarking C++ against SSE or NEON. +// Do so in both simon.cpp and simon_simd.cpp. +// #undef CRYPTOPP_SSSE3_AVAILABLE +// #undef CRYPTOPP_ARM_NEON_AVAILABLE + +#if (CRYPTOPP_SSSE3_AVAILABLE) +#include "adv_simd.h" +# include +# include +#endif + +#if defined(__XOP__) +# include +# if defined(__GNUC__) +# include +# endif +#endif + +// Clang intrinsic casts, http://bugs.llvm.org/show_bug.cgi?id=20670 +#define DOUBLE_CAST(x) ((double*)(void*)(x)) +#define CONST_DOUBLE_CAST(x) ((const double*)(const void*)(x)) + +// Squash MS LNK4221 and libtool warnings +extern const char CHAM_SIMD_FNAME[] = __FILE__; + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word16; +using CryptoPP::word32; + +#if (CRYPTOPP_SSSE3_AVAILABLE) + +////////////////////////////////////////////////////////////////////////// + +NAMESPACE_BEGIN(W32) // CHAM128, 32-bit word size + +template +inline __m128i RotateLeft32(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, R); +#else + return _mm_or_si128( + _mm_slli_epi32(val, R), _mm_srli_epi32(val, 32-R)); +#endif +} + +template +inline __m128i RotateRight32(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, 32-R); +#else + return _mm_or_si128( + _mm_slli_epi32(val, 32-R), _mm_srli_epi32(val, R)); +#endif +} + +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +inline __m128i RotateLeft32<8>(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, 8); +#else + const __m128i mask = _mm_set_epi8(14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3); + return _mm_shuffle_epi8(val, mask); +#endif +} + +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +inline __m128i RotateRight32<8>(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, 32-8); +#else + const __m128i mask = _mm_set_epi8(12,15,14,13, 8,11,10,9, 4,7,6,5, 0,3,2,1); + return _mm_shuffle_epi8(val, mask); +#endif +} + +template +inline __m128i UnpackXMM(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // Should not be instantiated + CRYPTOPP_UNUSED(a); CRYPTOPP_UNUSED(b); + CRYPTOPP_UNUSED(c); CRYPTOPP_UNUSED(d); + CRYPTOPP_ASSERT(0); + return _mm_setzero_si128(); +} + +template <> +inline __m128i UnpackXMM<0>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // The shuffle converts to and from little-endian for SSE. A specialized + // CHAM implementation can avoid the shuffle by framing the data for + // encryption, decryption and benchmarks. The library cannot take the + // speed-up because of the byte oriented API. + const __m128i r1 = _mm_unpacklo_epi32(a, b); + const __m128i r2 = _mm_unpacklo_epi32(c, d); + return _mm_shuffle_epi8(_mm_unpacklo_epi64(r1, r2), + _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3)); +} + +template <> +inline __m128i UnpackXMM<1>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // The shuffle converts to and from little-endian for SSE. A specialized + // CHAM implementation can avoid the shuffle by framing the data for + // encryption, decryption and benchmarks. The library cannot take the + // speed-up because of the byte oriented API. + const __m128i r1 = _mm_unpacklo_epi32(a, b); + const __m128i r2 = _mm_unpacklo_epi32(c, d); + return _mm_shuffle_epi8(_mm_unpackhi_epi64(r1, r2), + _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3)); +} + +template <> +inline __m128i UnpackXMM<2>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // The shuffle converts to and from little-endian for SSE. A specialized + // CHAM implementation can avoid the shuffle by framing the data for + // encryption, decryption and benchmarks. The library cannot take the + // speed-up because of the byte oriented API. + const __m128i r1 = _mm_unpackhi_epi32(a, b); + const __m128i r2 = _mm_unpackhi_epi32(c, d); + return _mm_shuffle_epi8(_mm_unpacklo_epi64(r1, r2), + _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3)); +} + +template <> +inline __m128i UnpackXMM<3>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // The shuffle converts to and from little-endian for SSE. A specialized + // CHAM implementation can avoid the shuffle by framing the data for + // encryption, decryption and benchmarks. The library cannot take the + // speed-up because of the byte oriented API. + const __m128i r1 = _mm_unpackhi_epi32(a, b); + const __m128i r2 = _mm_unpackhi_epi32(c, d); + return _mm_shuffle_epi8(_mm_unpackhi_epi64(r1, r2), + _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3)); +} + +template +inline __m128i UnpackXMM(const __m128i& v) +{ + // Should not be instantiated + CRYPTOPP_UNUSED(v); CRYPTOPP_ASSERT(0); + return _mm_setzero_si128(); +} + +template <> +inline __m128i UnpackXMM<0>(const __m128i& v) +{ + return _mm_shuffle_epi8(v, _mm_set_epi8(0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3)); +} + +template <> +inline __m128i UnpackXMM<1>(const __m128i& v) +{ + return _mm_shuffle_epi8(v, _mm_set_epi8(4,5,6,7, 4,5,6,7, 4,5,6,7, 4,5,6,7)); +} + +template <> +inline __m128i UnpackXMM<2>(const __m128i& v) +{ + return _mm_shuffle_epi8(v, _mm_set_epi8(8,9,10,11, 8,9,10,11, 8,9,10,11, 8,9,10,11)); +} + +template <> +inline __m128i UnpackXMM<3>(const __m128i& v) +{ + return _mm_shuffle_epi8(v, _mm_set_epi8(12,13,14,15, 12,13,14,15, 12,13,14,15, 12,13,14,15)); +} + +template +inline __m128i RepackXMM(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + return UnpackXMM(a, b, c, d); +} + +template +inline __m128i RepackXMM(const __m128i& v) +{ + return UnpackXMM(v); +} + +inline void CHAM128_Enc_Block(__m128i &block0, + const word32 *subkeys, unsigned int rounds) +{ + // Rearrange the data for vectorization. UnpackXMM includes a + // little-endian swap for SSE. Thanks to Peter Cordes for help + // with packing and unpacking. + // [A1 A2 A3 A4][B1 B2 B3 B4] ... => [A1 B1 C1 D1][A2 B2 C2 D2] ... + __m128i a = UnpackXMM<0>(block0); + __m128i b = UnpackXMM<1>(block0); + __m128i c = UnpackXMM<2>(block0); + __m128i d = UnpackXMM<3>(block0); + + __m128i counter = _mm_set_epi32(0,0,0,0); + __m128i increment = _mm_set_epi32(1,1,1,1); + + const unsigned int MASK = (rounds == 80 ? 7 : 15); + for (int i=0; i(rounds); i+=4) + { + __m128i k, k1, k2, t1, t2; + k = _mm_castpd_si128(_mm_load_sd(CONST_DOUBLE_CAST(&subkeys[(i+0) & MASK]))); + + // Shuffle out two subkeys + k1 = _mm_shuffle_epi8(k, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); + k2 = _mm_shuffle_epi8(k, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); + + t1 = _mm_xor_si128(a, counter); + t2 = _mm_xor_si128(RotateLeft32<1>(b), k1); + a = RotateLeft32<8>(_mm_add_epi32(t1, t2)); + + counter = _mm_add_epi32(counter, increment); + + t1 = _mm_xor_si128(b, counter); + t2 = _mm_xor_si128(RotateLeft32<8>(c), k2); + b = RotateLeft32<1>(_mm_add_epi32(t1, t2)); + + counter = _mm_add_epi32(counter, increment); + k = _mm_castpd_si128(_mm_load_sd(CONST_DOUBLE_CAST(&subkeys[(i+2) & MASK]))); + + // Shuffle out two subkeys + k1 = _mm_shuffle_epi8(k, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); + k2 = _mm_shuffle_epi8(k, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); + + t1 = _mm_xor_si128(c, counter); + t2 = _mm_xor_si128(RotateLeft32<1>(d), k1); + c = RotateLeft32<8>(_mm_add_epi32(t1, t2)); + + counter = _mm_add_epi32(counter, increment); + + t1 = _mm_xor_si128(d, counter); + t2 = _mm_xor_si128(RotateLeft32<8>(a), k2); + d = RotateLeft32<1>(_mm_add_epi32(t1, t2)); + + counter = _mm_add_epi32(counter, increment); + } + + // [A1 B1 C1 D1][A2 B2 C2 D2] ... => [A1 A2 A3 A4][B1 B2 B3 B4] ... + block0 = RepackXMM<0>(a,b,c,d); +} + +inline void CHAM128_Dec_Block(__m128i &block0, + const word32 *subkeys, unsigned int rounds) +{ + // Rearrange the data for vectorization. UnpackXMM includes a + // little-endian swap for SSE. Thanks to Peter Cordes for help + // with packing and unpacking. + // [A1 A2 A3 A4][B1 B2 B3 B4] ... => [A1 B1 C1 D1][A2 B2 C2 D2] ... + __m128i a = UnpackXMM<0>(block0); + __m128i b = UnpackXMM<1>(block0); + __m128i c = UnpackXMM<2>(block0); + __m128i d = UnpackXMM<3>(block0); + + __m128i counter = _mm_set_epi32(rounds-1,rounds-1,rounds-1,rounds-1); + __m128i decrement = _mm_set_epi32(1,1,1,1); + + const unsigned int MASK = (rounds == 80 ? 7 : 15); + for (int i = static_cast(rounds)-1; i >= 0; i-=4) + { + __m128i k, k1, k2, t1, t2; + k = _mm_castpd_si128(_mm_load_sd(CONST_DOUBLE_CAST(&subkeys[(i-1) & MASK]))); + + // Shuffle out two subkeys + k1 = _mm_shuffle_epi8(k, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); + k2 = _mm_shuffle_epi8(k, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); + + // Odd round + t1 = RotateRight32<1>(d); + t2 = _mm_xor_si128(RotateLeft32<8>(a), k1); + d = _mm_xor_si128(_mm_sub_epi32(t1, t2), counter); + + counter = _mm_sub_epi32(counter, decrement); + + // Even round + t1 = RotateRight32<8>(c); + t2 = _mm_xor_si128(RotateLeft32<1>(d), k2); + c = _mm_xor_si128(_mm_sub_epi32(t1, t2), counter); + + counter = _mm_sub_epi32(counter, decrement); + k = _mm_castpd_si128(_mm_load_sd(CONST_DOUBLE_CAST(&subkeys[(i-3) & MASK]))); + + // Shuffle out two subkeys + k1 = _mm_shuffle_epi8(k, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); + k2 = _mm_shuffle_epi8(k, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); + + // Odd round + t1 = RotateRight32<1>(b); + t2 = _mm_xor_si128(RotateLeft32<8>(c), k1); + b = _mm_xor_si128(_mm_sub_epi32(t1, t2), counter); + + counter = _mm_sub_epi32(counter, decrement); + + // Even round + t1 = RotateRight32<8>(a); + t2 = _mm_xor_si128(RotateLeft32<1>(b), k2); + a = _mm_xor_si128(_mm_sub_epi32(t1, t2), counter); + + counter = _mm_sub_epi32(counter, decrement); + } + + // [A1 B1 C1 D1][A2 B2 C2 D2] ... => [A1 A2 A3 A4][B1 B2 B3 B4] ... + block0 = RepackXMM<0>(a,b,c,d); +} + +inline void CHAM128_Enc_4_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, const word32 *subkeys, unsigned int rounds) +{ + // Rearrange the data for vectorization. UnpackXMM includes a + // little-endian swap for SSE. Thanks to Peter Cordes for help + // with packing and unpacking. + // [A1 A2 A3 A4][B1 B2 B3 B4] ... => [A1 B1 C1 D1][A2 B2 C2 D2] ... + __m128i a = UnpackXMM<0>(block0, block1, block2, block3); + __m128i b = UnpackXMM<1>(block0, block1, block2, block3); + __m128i c = UnpackXMM<2>(block0, block1, block2, block3); + __m128i d = UnpackXMM<3>(block0, block1, block2, block3); + + __m128i counter = _mm_set_epi32(0,0,0,0); + __m128i increment = _mm_set_epi32(1,1,1,1); + + const unsigned int MASK = (rounds == 80 ? 7 : 15); + for (int i=0; i(rounds); i+=4) + { + __m128i k, k1, k2, t1, t2; + k = _mm_castpd_si128(_mm_load_sd(CONST_DOUBLE_CAST(&subkeys[(i+0) & MASK]))); + + // Shuffle out two subkeys + k1 = _mm_shuffle_epi8(k, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); + k2 = _mm_shuffle_epi8(k, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); + + t1 = _mm_xor_si128(a, counter); + t2 = _mm_xor_si128(RotateLeft32<1>(b), k1); + a = RotateLeft32<8>(_mm_add_epi32(t1, t2)); + + counter = _mm_add_epi32(counter, increment); + + t1 = _mm_xor_si128(b, counter); + t2 = _mm_xor_si128(RotateLeft32<8>(c), k2); + b = RotateLeft32<1>(_mm_add_epi32(t1, t2)); + + counter = _mm_add_epi32(counter, increment); + k = _mm_castpd_si128(_mm_load_sd(CONST_DOUBLE_CAST(&subkeys[(i+2) & MASK]))); + + // Shuffle out two subkeys + k1 = _mm_shuffle_epi8(k, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); + k2 = _mm_shuffle_epi8(k, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); + + t1 = _mm_xor_si128(c, counter); + t2 = _mm_xor_si128(RotateLeft32<1>(d), k1); + c = RotateLeft32<8>(_mm_add_epi32(t1, t2)); + + counter = _mm_add_epi32(counter, increment); + + t1 = _mm_xor_si128(d, counter); + t2 = _mm_xor_si128(RotateLeft32<8>(a), k2); + d = RotateLeft32<1>(_mm_add_epi32(t1, t2)); + + counter = _mm_add_epi32(counter, increment); + } + + // [A1 B1 C1 D1][A2 B2 C2 D2] ... => [A1 A2 A3 A4][B1 B2 B3 B4] ... + block0 = RepackXMM<0>(a,b,c,d); + block1 = RepackXMM<1>(a,b,c,d); + block2 = RepackXMM<2>(a,b,c,d); + block3 = RepackXMM<3>(a,b,c,d); +} + +inline void CHAM128_Dec_4_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, const word32 *subkeys, unsigned int rounds) +{ + // Rearrange the data for vectorization. UnpackXMM includes a + // little-endian swap for SSE. Thanks to Peter Cordes for help + // with packing and unpacking. + // [A1 A2 A3 A4][B1 B2 B3 B4] ... => [A1 B1 C1 D1][A2 B2 C2 D2] ... + __m128i a = UnpackXMM<0>(block0, block1, block2, block3); + __m128i b = UnpackXMM<1>(block0, block1, block2, block3); + __m128i c = UnpackXMM<2>(block0, block1, block2, block3); + __m128i d = UnpackXMM<3>(block0, block1, block2, block3); + + __m128i counter = _mm_set_epi32(rounds-1,rounds-1,rounds-1,rounds-1); + __m128i decrement = _mm_set_epi32(1,1,1,1); + + const unsigned int MASK = (rounds == 80 ? 7 : 15); + for (int i = static_cast(rounds)-1; i >= 0; i-=4) + { + __m128i k, k1, k2, t1, t2; + k = _mm_castpd_si128(_mm_load_sd(CONST_DOUBLE_CAST(&subkeys[(i-1) & MASK]))); + + // Shuffle out two subkeys + k1 = _mm_shuffle_epi8(k, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); + k2 = _mm_shuffle_epi8(k, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); + + // Odd round + t1 = RotateRight32<1>(d); + t2 = _mm_xor_si128(RotateLeft32<8>(a), k1); + d = _mm_xor_si128(_mm_sub_epi32(t1, t2), counter); + + counter = _mm_sub_epi32(counter, decrement); + + // Even round + t1 = RotateRight32<8>(c); + t2 = _mm_xor_si128(RotateLeft32<1>(d), k2); + c = _mm_xor_si128(_mm_sub_epi32(t1, t2), counter); + + counter = _mm_sub_epi32(counter, decrement); + k = _mm_castpd_si128(_mm_load_sd(CONST_DOUBLE_CAST(&subkeys[(i-3) & MASK]))); + + // Shuffle out two subkeys + k1 = _mm_shuffle_epi8(k, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); + k2 = _mm_shuffle_epi8(k, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); + + // Odd round + t1 = RotateRight32<1>(b); + t2 = _mm_xor_si128(RotateLeft32<8>(c), k1); + b = _mm_xor_si128(_mm_sub_epi32(t1, t2), counter); + + counter = _mm_sub_epi32(counter, decrement); + + // Even round + t1 = RotateRight32<8>(a); + t2 = _mm_xor_si128(RotateLeft32<1>(b), k2); + a = _mm_xor_si128(_mm_sub_epi32(t1, t2), counter); + + counter = _mm_sub_epi32(counter, decrement); + } + + // [A1 B1 C1 D1][A2 B2 C2 D2] ... => [A1 A2 A3 A4][B1 B2 B3 B4] ... + block0 = RepackXMM<0>(a,b,c,d); + block1 = RepackXMM<1>(a,b,c,d); + block2 = RepackXMM<2>(a,b,c,d); + block3 = RepackXMM<3>(a,b,c,d); +} + +////////////////////////////////////////////////////////////////////////// + +NAMESPACE_END // W32 + +#endif // CRYPTOPP_SSSE3_AVAILABLE + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_SSSE3_AVAILABLE) +size_t CHAM128_Enc_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_4x1_SSE(W32::CHAM128_Enc_Block, W32::CHAM128_Enc_4_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t CHAM128_Dec_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_4x1_SSE(W32::CHAM128_Dec_Block, W32::CHAM128_Dec_4_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_SSSE3_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/channels.cpp b/external/ours/library/crypto/src/shared/original/channels.cpp new file mode 100755 index 000000000..ec7a98a0f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/channels.cpp @@ -0,0 +1,316 @@ +// channels.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017 + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "cryptlib.h" +#include "channels.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if 0 +void MessageSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &channel) +{ + m_defaultRoutes.push_back(Route(&destination, channel)); +} + +void MessageSwitch::AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel) +{ + RangeRoute route(begin, end, Route(&destination, channel)); + RouteList::iterator it = upper_bound(m_routes.begin(), m_routes.end(), route); + m_routes.insert(it, route); +} + +/* +class MessageRouteIterator +{ +public: + typedef MessageSwitch::RouteList::const_iterator RouteIterator; + typedef MessageSwitch::DefaultRouteList::const_iterator DefaultIterator; + + bool m_useDefault; + RouteIterator m_itRouteCurrent, m_itRouteEnd; + DefaultIterator m_itDefaultCurrent, m_itDefaultEnd; + + MessageRouteIterator(MessageSwitch &ms, const std::string &channel) + : m_channel(channel) + { + std::pair range = cs.m_routeMap.equal_range(channel); + if (range.first == range.second) + { + m_useDefault = true; + m_itListCurrent = cs.m_defaultRoutes.begin(); + m_itListEnd = cs.m_defaultRoutes.end(); + } + else + { + m_useDefault = false; + m_itMapCurrent = range.first; + m_itMapEnd = range.second; + } + } + + bool End() const + { + return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd; + } + + void Next() + { + if (m_useDefault) + ++m_itListCurrent; + else + ++m_itMapCurrent; + } + + BufferedTransformation & Destination() + { + return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first; + } + + const std::string & Message() + { + if (m_useDefault) + return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel; + else + return m_itMapCurrent->second.second; + } +}; + +void MessageSwitch::Put(byte inByte); +void MessageSwitch::Put(const byte *inString, unsigned int length); + +void MessageSwitch::Flush(bool completeFlush, int propagation=-1); +void MessageSwitch::MessageEnd(int propagation=-1); +void MessageSwitch::PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1); +void MessageSwitch::MessageSeriesEnd(int propagation=-1); +*/ +#endif + + +// +// ChannelRouteIterator +////////////////////////// + +void ChannelRouteIterator::Reset(const std::string &channel) +{ + m_channel = channel; + std::pair range = m_cs.m_routeMap.equal_range(channel); + if (range.first == range.second) + { + m_useDefault = true; + m_itListCurrent = m_cs.m_defaultRoutes.begin(); + m_itListEnd = m_cs.m_defaultRoutes.end(); + } + else + { + m_useDefault = false; + m_itMapCurrent = range.first; + m_itMapEnd = range.second; + } +} + +bool ChannelRouteIterator::End() const +{ + return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd; +} + +void ChannelRouteIterator::Next() +{ + if (m_useDefault) + ++m_itListCurrent; + else + ++m_itMapCurrent; +} + +BufferedTransformation & ChannelRouteIterator::Destination() +{ + return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first; +} + +const std::string & ChannelRouteIterator::Channel() +{ + if (m_useDefault) + return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel; + else + return m_itMapCurrent->second.second; +} + + +// +// ChannelSwitch +/////////////////// + +size_t ChannelSwitch::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (m_blocked) + { + m_blocked = false; + goto WasBlocked; + } + + m_it.Reset(channel); + + while (!m_it.End()) + { +WasBlocked: + if (m_it.Destination().ChannelPut2(m_it.Channel(), begin, length, messageEnd, blocking)) + { + m_blocked = true; + return 1; + } + + m_it.Next(); + } + + return 0; +} + +void ChannelSwitch::IsolatedInitialize(const NameValuePairs& parameters) +{ + CRYPTOPP_UNUSED(parameters); + m_routeMap.clear(); + m_defaultRoutes.clear(); + m_blocked = false; +} + +bool ChannelSwitch::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking) +{ + if (m_blocked) + { + m_blocked = false; + goto WasBlocked; + } + + m_it.Reset(channel); + + while (!m_it.End()) + { + WasBlocked: + if (m_it.Destination().ChannelFlush(m_it.Channel(), completeFlush, propagation, blocking)) + { + m_blocked = true; + return true; + } + + m_it.Next(); + } + + return false; +} + +bool ChannelSwitch::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) +{ + CRYPTOPP_UNUSED(blocking); + if (m_blocked) + { + m_blocked = false; + goto WasBlocked; + } + + m_it.Reset(channel); + + while (!m_it.End()) + { + WasBlocked: + if (m_it.Destination().ChannelMessageSeriesEnd(m_it.Channel(), propagation)) + { + m_blocked = true; + return true; + } + + m_it.Next(); + } + + return false; +} + +byte * ChannelSwitch::ChannelCreatePutSpace(const std::string &channel, size_t &size) +{ + m_it.Reset(channel); + if (!m_it.End()) + { + BufferedTransformation &target = m_it.Destination(); + const std::string &ch = m_it.Channel(); + m_it.Next(); + if (m_it.End()) // there is only one target channel + return target.ChannelCreatePutSpace(ch, size); + } + size = 0; + return NULLPTR; +} + +size_t ChannelSwitch::ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking) +{ + ChannelRouteIterator it(*this); + it.Reset(channel); + + if (!it.End()) + { + BufferedTransformation &target = it.Destination(); + const std::string &targetChannel = it.Channel(); + it.Next(); + if (it.End()) // there is only one target channel + return target.ChannelPutModifiable2(targetChannel, inString, length, messageEnd, blocking); + } + + return ChannelPut2(channel, inString, length, messageEnd, blocking); +} + +void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination) +{ + m_defaultRoutes.push_back(DefaultRoute(&destination, value_ptr(NULLPTR))); +} + +void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination) +{ + for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it) + if (it->first == &destination && !it->second.get()) + { + m_defaultRoutes.erase(it); + break; + } +} + +void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel) +{ + m_defaultRoutes.push_back(DefaultRoute(&destination, outChannel)); +} + +void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel) +{ + for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it) + if (it->first == &destination && (it->second.get() && *it->second == outChannel)) + { + m_defaultRoutes.erase(it); + break; + } +} + +void ChannelSwitch::AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel) +{ + m_routeMap.insert(RouteMap::value_type(inChannel, Route(&destination, outChannel))); +} + +void ChannelSwitch::RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel) +{ + typedef ChannelSwitch::RouteMap::iterator MapIterator; + std::pair range = m_routeMap.equal_range(inChannel); + + for (MapIterator it = range.first; it != range.second; ++it) + if (it->second.first == &destination && it->second.second == outChannel) + { + m_routeMap.erase(it); + break; + } +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/channels.h b/external/ours/library/crypto/src/shared/original/channels.h new file mode 100755 index 000000000..da470a2b1 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/cmac.cpp b/external/ours/library/crypto/src/shared/original/cmac.cpp new file mode 100755 index 000000000..3ff57f1e3 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/cmac.cpp @@ -0,0 +1,164 @@ +// cmac.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "cmac.h" +#include "misc.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::IsPowerOf2; + +void MulU(byte *k, unsigned int len) +{ + byte carry = 0; + for (int i=len-1; i>=1; i-=2) + { + byte carry2 = k[i] >> 7; + k[i] += k[i] + carry; + carry = k[i-1] >> 7; + k[i-1] += k[i-1] + carry2; + } + +#ifndef CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS + CRYPTOPP_ASSERT(len == 16); + + if (carry) + { + k[15] ^= 0x87; + return; + } +#else + CRYPTOPP_ASSERT(IsPowerOf2(len)); + CRYPTOPP_ASSERT(len >= 8); + CRYPTOPP_ASSERT(len <= 128); + + if (carry) + { + switch (len) + { + case 8: + k[7] ^= 0x1b; + break; + case 16: + k[15] ^= 0x87; + break; + case 32: + // https://crypto.stackexchange.com/q/9815/10496 + // Polynomial x^256 + x^10 + x^5 + x^2 + 1 + k[30] ^= 4; + k[31] ^= 0x25; + break; + case 64: + // https://crypto.stackexchange.com/q/9815/10496 + // Polynomial x^512 + x^8 + x^5 + x^2 + 1 + k[62] ^= 1; + k[63] ^= 0x25; + break; + case 128: + // https://crypto.stackexchange.com/q/9815/10496 + // Polynomial x^1024 + x^19 + x^6 + x + 1 + k[125] ^= 8; + k[126] ^= 0x00; + k[127] ^= 0x43; + break; + default: + CRYPTOPP_ASSERT(0); + } + } +#endif // CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + BlockCipher &cipher = AccessCipher(); + cipher.SetKey(key, length, params); + + unsigned int blockSize = cipher.BlockSize(); + m_reg.CleanNew(3*blockSize); + m_counter = 0; + + cipher.ProcessBlock(m_reg, m_reg+blockSize); + MulU(m_reg+blockSize, blockSize); + memcpy(m_reg+2*blockSize, m_reg+blockSize, blockSize); + MulU(m_reg+2*blockSize, blockSize); +} + +void CMAC_Base::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT((input && length) || !(input || length)); + if (!length) + return; + + BlockCipher &cipher = AccessCipher(); + unsigned int blockSize = cipher.BlockSize(); + + if (m_counter > 0) + { + const unsigned int len = UnsignedMin(blockSize - m_counter, length); + if (len) + { + xorbuf(m_reg+m_counter, input, len); + length -= len; + input += len; + m_counter += len; + } + + if (m_counter == blockSize && length > 0) + { + cipher.ProcessBlock(m_reg); + m_counter = 0; + } + } + + if (length > blockSize) + { + CRYPTOPP_ASSERT(m_counter == 0); + size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput); + input += (length - leftOver); + length = leftOver; + } + + if (length > 0) + { + CRYPTOPP_ASSERT(m_counter + length <= blockSize); + xorbuf(m_reg+m_counter, input, length); + m_counter += (unsigned int)length; + } + + CRYPTOPP_ASSERT(m_counter > 0); +} + +void CMAC_Base::TruncatedFinal(byte *mac, size_t size) +{ + ThrowIfInvalidTruncatedSize(size); + + BlockCipher &cipher = AccessCipher(); + unsigned int blockSize = cipher.BlockSize(); + + if (m_counter < blockSize) + { + m_reg[m_counter] ^= 0x80; + cipher.AdvancedProcessBlocks(m_reg, m_reg+2*blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput); + } + else + cipher.AdvancedProcessBlocks(m_reg, m_reg+blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput); + + // UBsan finding + if (mac) + memcpy(mac, m_reg, size); + + m_counter = 0; + memset(m_reg, 0, blockSize); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/cmac.h b/external/ours/library/crypto/src/shared/original/cmac.h new file mode 100755 index 000000000..59a9f0201 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/config.h b/external/ours/library/crypto/src/shared/original/config.h index f0dfb23ee..cb4d24661 100755 --- a/external/ours/library/crypto/src/shared/original/config.h +++ b/external/ours/library/crypto/src/shared/original/config.h @@ -1,165 +1,33 @@ -#ifndef CRYPTOPP_CONFIG_H -#define CRYPTOPP_CONFIG_H - -// ***************** Important Settings ******************** - -// define this if running on a big-endian CPU -#if defined(__sparc__) || defined(__hppa__) || defined(__ppc__) || defined(__mips__) || (defined(__MWERKS__) && !defined(__INTEL__)) -#define IS_BIG_ENDIAN -#endif - -// define this if running on a little-endian CPU -// big endian will be assumed if IS_LITTLE_ENDIAN is not defined -#ifndef IS_BIG_ENDIAN -#define IS_LITTLE_ENDIAN -#endif - -// define this if you want to disable all OS-dependent features, -// such as sockets and OS-provided random number generators -// #define NO_OS_DEPENDENCE - -// Define this to use features provided by Microsoft's CryptoAPI. -// Currently the only feature used is random number generation. -// This macro will be ignored if NO_OS_DEPENDENCE is defined. -#define USE_MS_CRYPTOAPI - -// define this if your compiler does not support namespaces -// #define NO_NAMESPACE -#ifdef NO_NAMESPACE -#define std -#define CryptoPP -#define USING_NAMESPACE(x) -#define NAMESPACE_BEGIN(x) -#define NAMESPACE_END -#define ANONYMOUS_NAMESPACE_BEGIN -#else -#define USING_NAMESPACE(x) using namespace x; -#define NAMESPACE_BEGIN(x) namespace x { -#define ANONYMOUS_NAMESPACE_BEGIN namespace { -#define NAMESPACE_END } -#endif - -// ***************** Less Important Settings *************** - -// switch between different secure memory allocation mechnisms, this is the only -// one available right now -#define SECALLOC_DEFAULT - -#define GZIP_OS_CODE 0 - -// 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 - -// Try this if you have a large cache or your CPU is slow manipulating -// individual bytes. -// #define DIAMOND_USE_PERMTABLE - -// 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 - -// choose which style of sockets to wrap (mostly useful for cygwin which has both) -#define PREFER_BERKELEY_STYLE_SOCKETS -// #define PREFER_WINDOWS_STYLE_SOCKETS - -// ***************** Important Settings Again ******************** -// But the defaults should be ok. - -typedef unsigned char byte; // moved outside namespace for Borland C++Builder 5 - -NAMESPACE_BEGIN(CryptoPP) - -typedef unsigned short word16; -#if defined(__alpha) && !defined(_MSC_VER) -typedef unsigned int word32; -#else -typedef unsigned long word32; -#endif - -#if defined(__GNUC__) || defined(__MWERKS__) -#define WORD64_AVAILABLE -typedef unsigned long long word64; -#define W64LIT(x) x##LL -#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__) -#define WORD64_AVAILABLE -typedef unsigned __int64 word64; -#define W64LIT(x) x##ui64 -#endif - -// defined this if your CPU is not 64-bit -#if defined(WORD64_AVAILABLE) && !defined(__alpha) -#define SLOW_WORD64 -#endif - -// word should have the same size as your CPU registers -// dword should be twice as big as word - -#if (defined(__GNUC__) && !defined(__alpha)) || defined(__MWERKS__) -typedef unsigned long word; -typedef unsigned long long dword; -#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__) -typedef unsigned __int32 word; -typedef unsigned __int64 dword; -#else -typedef unsigned int word; -typedef unsigned long dword; -#endif - -const unsigned int WORD_SIZE = sizeof(word); -const unsigned int WORD_BITS = WORD_SIZE * 8; - -#define LOW_WORD(x) (word)(x) - -union dword_union -{ - dword_union (const dword &dw) : dw(dw) {} - dword dw; - word w[2]; -}; - -#ifdef IS_LITTLE_ENDIAN -#define HIGH_WORD(x) (dword_union(x).w[1]) -#else -#define HIGH_WORD(x) (dword_union(x).w[0]) -#endif - -// if the above HIGH_WORD macro doesn't work (if you are not sure, compile it -// and run the validation tests), try this: -// #define HIGH_WORD(x) (word)((x)>>WORD_BITS) - -#if defined(_MSC_VER) || defined(__BCPLUSPLUS__) -#define INTEL_INTRINSICS -#define FAST_ROTATE -#elif defined(__MWERKS__) && TARGET_CPU_PPC -#define PPC_INTRINSICS -#define FAST_ROTATE -#elif defined(__GNUC__) && defined(__i386__) -// GCC does peephole optimizations which should result in using rotate instructions -#define FAST_ROTATE -#endif - -// can't use std::min or std::max in MSVC60 or Cygwin 1.1.0 -template -inline const _Tp& STDMIN(const _Tp& __a, const _Tp& __b) { - return __b < __a ? __b : __a; -} - -template -inline const _Tp& STDMAX(const _Tp& __a, const _Tp& __b) { - return __a < __b ? __b : __a; -} - -#ifdef _MSC_VER -// 4250: dominance -// 4660: explicitly instantiating a class that's already implicitly instantiated -// 4786: identifer was truncated in debug information -// 4355: 'this' : used in base member initializer list -// 4800: converting int to bool -#pragma warning(disable: 4250 4660 4786 4355 4800 4710) -#endif - -NAMESPACE_END - -#endif +// 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/external/ours/library/crypto/src/shared/original/config_align.h b/external/ours/library/crypto/src/shared/original/config_align.h new file mode 100755 index 000000000..6a6e9e041 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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(_MSC_VER) + #define CRYPTOPP_MM_MALLOC_AVAILABLE +#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__) + #define CRYPTOPP_MEMALIGN_AVAILABLE +#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) + #define CRYPTOPP_MALLOC_ALIGNMENT_IS_16 +#elif (defined(_GNU_SOURCE) || ((_XOPEN_SOURCE + 0) >= 600)) && (_POSIX_ADVISORY_INFO > 0) + #define CRYPTOPP_POSIX_MEMALIGN_AVAILABLE +#else + #define CRYPTOPP_NO_ALIGNED_ALLOC +#endif + +// 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(_MSC_VER) + #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/external/ours/library/crypto/src/shared/original/config_asm.h b/external/ours/library/crypto/src/shared/original/config_asm.h new file mode 100755 index 000000000..3202a2c37 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/config_asm.h @@ -0,0 +1,480 @@ +// 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 will be +// compiled using C++ only. The library code will not include SSE2 (and +// above), NEON, Aarch32, Aarch64, or Altivec (and above). Note the compiler +// may use higher ISAs depending on compiler options, but the library will not +// explicitly use the ISAs. When disabling ASM, it is best to do it from +// config.h to ensure the library and all programs share the setting. +// #define CRYPTOPP_DISABLE_ASM 1 + +// https://github.com/weidai11/cryptopp/issues/719 +#if defined(__native_client__) +# undef CRYPTOPP_DISABLE_ASM +# define CRYPTOPP_DISABLE_ASM 1 +#endif + +// Some Clang and SunCC cannot handle mixed asm with positional arguments, +// where the body is Intel style with no prefix and the templates are +// AT&T style. Define this if the Makefile misdetects the configuration. +// Also see https://bugs.llvm.org/show_bug.cgi?id=39895 . +// #define CRYPTOPP_DISABLE_MIXED_ASM 1 + +#if defined(__clang__) || (defined(__APPLE__) && defined(__GNUC__)) || defined(__SUNPRO_CC) +# undef CRYPTOPP_DISABLE_MIXED_ASM +# define CRYPTOPP_DISABLE_MIXED_ASM 1 +#endif + +// Define this if you need to disable Android advanced ISAs. +// The problem is, Android-mk does not allow us to specify an +// ISA option, like -maes or -march=armv8-a+crypto for AES. +// Lack of an option results in a compile failure. To avoid +// the compile failure, set this define. Also see +// https://github.com/weidai11/cryptopp/issues/1015 +// CRYPTOPP_DISABLE_ANDROID_ADVANCED_ISA 1 + +// ***************** IA32 CPU features ******************** + +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + +// Apple Clang prior to 5.0 cannot handle SSE2 +#if defined(CRYPTOPP_APPLE_CLANG_VERSION) && (CRYPTOPP_APPLE_CLANG_VERSION < 50000) +# define CRYPTOPP_DISABLE_ASM 1 +#endif + +// Sun Studio 12.1 provides GCC inline assembly +// http://blogs.oracle.com/x86be/entry/gcc_style_asm_inlining_support +#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5100) +# define CRYPTOPP_DISABLE_ASM 1 +#endif + +// Guard everything in CRYPTOPP_DISABLE_ASM +#if !defined(CRYPTOPP_DISABLE_ASM) + +#if (defined(_MSC_VER) && defined(_M_IX86)) || ((defined(__GNUC__) && (defined(__i386__)) || defined(__x86_64__))) + // C++Builder 2010 does not allow "call label" where label is defined within inline assembly + #define CRYPTOPP_X86_ASM_AVAILABLE 1 + + #if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(_MSC_VER) || CRYPTOPP_GCC_VERSION >= 30300 || defined(__SSE2__)) + #define CRYPTOPP_SSE2_ASM_AVAILABLE 1 + #endif + + #if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1500 || CRYPTOPP_GCC_VERSION >= 40300 || defined(__SSSE3__)) + #define CRYPTOPP_SSSE3_ASM_AVAILABLE 1 + #endif +#endif + +#if defined(_MSC_VER) && defined(_M_X64) + #define CRYPTOPP_X64_MASM_AVAILABLE 1 +#endif + +#if defined(__GNUC__) && defined(__x86_64__) + #define CRYPTOPP_X64_ASM_AVAILABLE 1 +#endif + +// 32-bit SunCC does not enable SSE2 by default. +#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(_MSC_VER) || CRYPTOPP_GCC_VERSION >= 30300 || defined(__SSE2__) || (__SUNPRO_CC >= 0x5100)) + #define CRYPTOPP_SSE2_INTRIN_AVAILABLE 1 +#endif + +#if !defined(CRYPTOPP_DISABLE_SSSE3) +# if defined(__SSSE3__) || (_MSC_VER >= 1500) || \ + (CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1000) || (__SUNPRO_CC >= 0x5110) || \ + (CRYPTOPP_LLVM_CLANG_VERSION >= 20300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000) + #define CRYPTOPP_SSSE3_AVAILABLE 1 +# endif +#endif + +// Intrinsics 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 platofrms 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 + +// 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(__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 + +// 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/external/ours/library/crypto/src/shared/original/config_cpu.h b/external/ours/library/crypto/src/shared/original/config_cpu.h new file mode 100755 index 000000000..3eeaf2341 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/config_cpu.h @@ -0,0 +1,211 @@ +// 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(_MSC_VER) || defined(__BORLANDC__) + #define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 1 +#else + #define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY 1 +#endif + +#endif // CRYPTOPP_CONFIG_CPU_H diff --git a/external/ours/library/crypto/src/shared/original/config_cxx.h b/external/ours/library/crypto/src/shared/original/config_cxx.h new file mode 100755 index 000000000..95093de76 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/config_cxx.h @@ -0,0 +1,247 @@ +// 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(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || (defined(_STLPORT_VERSION) && ((_STLPORT_VERSION < 0x450) || defined(_STLP_NO_UNCAUGHT_EXCEPT_SUPPORT))) +#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION +#endif + +// 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 ((_MSC_VER >= 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 ((_MSC_VER >= 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 ((_MSC_VER >= 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/external/ours/library/crypto/src/shared/original/config_dll.h b/external/ours/library/crypto/src/shared/original/config_dll.h new file mode 100755 index 000000000..ab9c67afa --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 decalration 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/external/ours/library/crypto/src/shared/original/config_int.h b/external/ours/library/crypto/src/shared/original/config_int.h new file mode 100755 index 000000000..2f74480fb --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/config_int.h @@ -0,0 +1,253 @@ +// 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" + +/// \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(_MSC_VER) || defined(__BORLANDC__) + typedef signed __int64 sword64; + typedef unsigned __int64 word64; + #define SW64LIT(x) x##i64 + #define W64LIT(x) x##ui64 +#elif (_LP64 || __LP64__) + typedef signed long sword64; + typedef unsigned long word64; + #define SW64LIT(x) x##L + #define W64LIT(x) x##UL +#else + typedef signed long long sword64; + typedef unsigned long long word64; + #define SW64LIT(x) x##LL + #define W64LIT(x) x##ULL +#endif + +/// \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. +const 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(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__)) + typedef word32 hword; + typedef word64 word; + #else + #define CRYPTOPP_NATIVE_DWORD_AVAILABLE 1 + #if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__) || 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 +const unsigned int WORD_SIZE = sizeof(word); + +/// \brief Size of a platform word in bits +/// \details The size of a platform word, in bits +const unsigned int WORD_BITS = WORD_SIZE * 8; + +NAMESPACE_END + +#endif // CRYPTOPP_CONFIG_INT_H diff --git a/external/ours/library/crypto/src/shared/original/config_misc.h b/external/ours/library/crypto/src/shared/original/config_misc.h new file mode 100755 index 000000000..67b2d4ab2 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/config_misc.h @@ -0,0 +1,194 @@ +// 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(_MSC_VER) +# 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 +#if defined(CRYPTOPP_CXX11_CONSTEXPR) +# define CRYPTOPP_STATIC_CONSTEXPR static constexpr +# define CRYPTOPP_CONSTEXPR constexpr +#else +# define CRYPTOPP_STATIC_CONSTEXPR static +# define CRYPTOPP_CONSTEXPR +#endif // CRYPTOPP_CXX11_CONSTEXPR + +#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 _MSC_VER + // 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) + // _MSC_VER 1920 is VS2019 +# if _MSC_VER >= 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/external/ours/library/crypto/src/shared/original/config_ns.h b/external/ours/library/crypto/src/shared/original/config_ns.h new file mode 100755 index 000000000..9fa3a3cb4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/config_os.h b/external/ours/library/crypto/src/shared/original/config_os.h new file mode 100755 index 000000000..107e44528 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/config_os.h @@ -0,0 +1,169 @@ +// 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__) && \ + !(defined( __clang_analyzer__)) && !defined(__INTEL_LLVM_COMPILER)) +# 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(_MSC_VER) || defined(__fastcall) + #define CRYPTOPP_FASTCALL __fastcall +#else + #define CRYPTOPP_FASTCALL +#endif + +// Microsoft compilers +#if defined(_MSC_VER) + #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/external/ours/library/crypto/src/shared/original/config_ver.h b/external/ours/library/crypto/src/shared/original/config_ver.h new file mode 100755 index 000000000..178eafea4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/config_ver.h @@ -0,0 +1,90 @@ +// 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 6 +/// \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 860 + +// Compiler version macros + +#if defined(__GNUC__) +# define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +// 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__) +# undef CRYPTOPP_GCC_VERSION +# define CRYPTOPP_APPLE_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#elif defined(__clang__) +# undef CRYPTOPP_GCC_VERSION +# 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(__xlc__) || defined(__xlC__) +# undef CRYPTOPP_LLVM_CLANG_VERSION +# define CRYPTOPP_XLC_VERSION ((__xlC__ / 256) * 10000 + (__xlC__ % 256) * 100) +#endif + +#ifdef __INTEL_COMPILER +# undef CRYPTOPP_LLVM_CLANG_VERSION +# define CRYPTOPP_INTEL_VERSION (__INTEL_COMPILER) +#endif + +#ifdef _MSC_VER +# undef CRYPTOPP_LLVM_CLANG_VERSION +# define CRYPTOPP_MSC_VERSION (_MSC_VER) +#endif + +#endif // CRYPTOPP_CONFIG_VERSION_H diff --git a/external/ours/library/crypto/src/shared/original/cpu.cpp b/external/ours/library/crypto/src/shared/original/cpu.cpp new file mode 100755 index 000000000..0e8cd7df5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/cpu.cpp @@ -0,0 +1,1459 @@ +// cpu.cpp - originally written and placed in the public domain by Wei Dai +// modified by Jeffrey Walton and the community over the years. + +#include "pch.h" +#include "config.h" + +#ifndef EXCEPTION_EXECUTE_HANDLER +# define EXCEPTION_EXECUTE_HANDLER 1 +#endif + +#ifndef CRYPTOPP_IMPORTS + +#include "cpu.h" +#include "misc.h" +#include "stdcpp.h" + +// For _xgetbv on Microsoft 32-bit and 64-bit Intel platforms +// https://github.com/weidai11/cryptopp/issues/972 +#if _MSC_VER >= 1600 && (defined(_M_IX86) || defined(_M_X64)) +# include +#endif + +// For IsProcessorFeaturePresent on Microsoft Arm64 platforms, +// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent +#if defined(_WIN32) && defined(_M_ARM64) +# include +# include +#endif + +#ifdef _AIX +# include +#endif + +#ifdef __linux__ +# include +#endif + +// Capability queries, requires Glibc 2.16, http://lwn.net/Articles/519085/ +// CRYPTOPP_GLIBC_VERSION not used because config.h is missing +#if (((__GLIBC__ * 100) + __GLIBC_MINOR__) >= 216) +# define CRYPTOPP_GETAUXV_AVAILABLE 1 +#endif + +#if CRYPTOPP_GETAUXV_AVAILABLE +# include +#else +#ifndef AT_HWCAP +# define AT_HWCAP 16 +#endif +#ifndef AT_HWCAP2 +# define AT_HWCAP2 26 +#endif +unsigned long int getauxval(unsigned long int) { return 0; } +#endif + +#if defined(__APPLE__) +# include +# include +#endif + +// FreeBSD headers are giving us trouble... +// https://github.com/weidai11/cryptopp/pull/1029 +#if defined(__FreeBSD__) +# include +# include +#endif + +// The cpu-features header and source file are located in +// "$ANDROID_NDK_ROOT/sources/android/cpufeatures". +// setenv-android.sh will copy the header and source file +// into PWD and the makefile will build it in place. +#if defined(__ANDROID__) +# include "cpu-features.h" +#endif + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +// Visual Studio 2008 and below are missing _xgetbv and _cpuidex. +// The 32-bit versions use inline ASM below. The 64-bit versions are in x64dll.asm. +#if defined(_MSC_VER) && defined(_M_X64) +extern "C" unsigned long long __fastcall XGETBV64(unsigned int); +extern "C" unsigned long long __fastcall CPUID64(unsigned int, unsigned int, unsigned int*); +#endif + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); +} + +extern "C" +{ + static jmp_buf s_jmpNoCPUID; + static void SigIllHandler(int) + { + longjmp(s_jmpNoCPUID, 1); + } +} +#endif // CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY + +ANONYMOUS_NAMESPACE_BEGIN + +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + +using CryptoPP::word32; + +inline bool IsIntel(const word32 output[4]) +{ + // This is the "GenuineIntel" string + return (output[1] /*EBX*/ == 0x756e6547) && + (output[2] /*ECX*/ == 0x6c65746e) && + (output[3] /*EDX*/ == 0x49656e69); +} + +inline bool IsAMD(const word32 output[4]) +{ + // This is the "AuthenticAMD" string. + return ((output[1] /*EBX*/ == 0x68747541) && + (output[2] /*ECX*/ == 0x444D4163) && + (output[3] /*EDX*/ == 0x69746E65)) || + // Early K5's can return "AMDisbetter!" + ((output[1] /*EBX*/ == 0x69444d41) && + (output[2] /*ECX*/ == 0x74656273) && + (output[3] /*EDX*/ == 0x21726574)); +} + +inline bool IsHygon(const word32 output[4]) +{ + // This is the "HygonGenuine" string. + return (output[1] /*EBX*/ == 0x6f677948) && + (output[2] /*ECX*/ == 0x656e6975) && + (output[3] /*EDX*/ == 0x6e65476e); +} + +inline bool IsVIA(const word32 output[4]) +{ + // This is the "CentaurHauls" string. + return ((output[1] /*EBX*/ == 0x746e6543) && + (output[2] /*ECX*/ == 0x736c7561) && + (output[3] /*EDX*/ == 0x48727561)) || + // Some non-PadLock's return "VIA VIA VIA " + ((output[1] /*EBX*/ == 0x32414956) && + (output[2] /*ECX*/ == 0x32414956) && + (output[3] /*EDX*/ == 0x32414956)); +} + +#endif // X86, X32 and X64 + +#if defined(__APPLE__) + +// http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios +class AppleMachineInfo +{ +public: + enum { PowerMac=1, Mac, iPhone, iPod, iPad, AppleTV, AppleWatch }; + enum { PowerPC=1, I386, I686, X86_64, ARM32, ARMV8, ARMV82, ARMV83 }; + + AppleMachineInfo() : m_device(0), m_version(0), m_arch(0) + { + struct utsname systemInfo; + systemInfo.machine[0] = '\0'; + uname(&systemInfo); + + std::string machine(systemInfo.machine); + + std::string::size_type pos = machine.find_first_of("0123456789"); + if (pos != std::string::npos) + m_version = std::atoi(machine.substr(pos).c_str()); + + if (machine.find("iPhone") != std::string::npos) + { + m_device = iPhone; + if (m_version >= 6) { m_arch = ARMV8; } + else { m_arch = ARM32; } + } + else if (machine.find("iPod") != std::string::npos) + { + m_device = iPod; + if (m_version >= 6) { m_arch = ARMV8; } + else { m_arch = ARM32; } + } + else if (machine.find("iPad") != std::string::npos) + { + m_device = iPad; + if (m_version >= 5) { m_arch = ARMV8; } + else { m_arch = ARM32; } + } + else if (machine.find("PowerMac") != std::string::npos || + machine.find("Power Macintosh") != std::string::npos) + { + m_device = PowerMac; + m_arch = PowerPC; + } + else if (machine.find("Mac") != std::string::npos || + machine.find("Macintosh") != std::string::npos) + { +#if defined(__x86_64) || defined(__amd64) + m_device = Mac; + m_arch = X86_64; +#elif defined(__i386) + m_device = Mac; + m_arch = I386; +#elif defined(__i686) + m_device = Mac; + m_arch = I686; +#else + // Should never get here + m_device = Mac; + m_arch = 0; +#endif + } + else if (machine.find("AppleTV") != std::string::npos) + { + m_device = AppleTV; + if (m_version >= 4) { m_arch = ARMV8; } + else { m_arch = ARM32; } + } + else if (machine.find("AppleWatch") != std::string::npos) + { + m_device = AppleWatch; + if (m_version >= 4) { m_arch = ARMV8; } + else { m_arch = ARM32; } + } + else if (machine.find("arm64") != std::string::npos) + { + // M1 machine? + std::string brand; + size_t size = 32; + + // Supply an oversized buffer, and avoid + // an extra call to sysctlbyname. + brand.resize(size); + if (sysctlbyname("machdep.cpu.brand_string", &brand[0], &size, NULL, 0) == 0 && size > 0) + { + if (brand[size-1] == '\0') + size--; + brand.resize(size); + } + + if (brand == "Apple M1") + { + m_device = Mac; + m_arch = ARMV82; + } + else + { + // ??? + m_device = 0; + m_arch = ARMV8; + } + } + else + { + CRYPTOPP_ASSERT(0); + } + } + + unsigned int Device() const { + return m_device; + } + + unsigned int Version() const { + return m_version; + } + + unsigned int Arch() const { + return m_arch; + } + + bool IsARM32() const { + return m_arch == ARM32; + } + + bool IsARMv8() const { + return m_arch >= ARMV8; + } + + bool IsARMv82() const { + return m_arch >= ARMV82; + } + + bool IsARMv83() const { + return m_arch >= ARMV83; + } + +private: + unsigned int m_device, m_version, m_arch; +}; + +void GetAppleMachineInfo(unsigned int& device, unsigned int& version, unsigned int& arch) +{ +#if CRYPTOPP_CXX11_STATIC_INIT + static const AppleMachineInfo info; +#else + using CryptoPP::Singleton; + const AppleMachineInfo& info = Singleton().Ref(); +#endif + + device = info.Device(); + version = info.Version(); + arch = info.Arch(); +} + +inline bool IsAppleMachineARM32() +{ + static unsigned int arch; + if (arch == 0) + { + unsigned int unused; + GetAppleMachineInfo(unused, unused, arch); + } + return arch == AppleMachineInfo::ARM32; +} + +inline bool IsAppleMachineARMv8() +{ + static unsigned int arch; + if (arch == 0) + { + unsigned int unused; + GetAppleMachineInfo(unused, unused, arch); + } + return arch >= AppleMachineInfo::ARMV8; +} + +inline bool IsAppleMachineARMv82() +{ + static unsigned int arch; + if (arch == 0) + { + unsigned int unused; + GetAppleMachineInfo(unused, unused, arch); + } + return arch >= AppleMachineInfo::ARMV82; +} + +inline bool IsAppleMachineARMv83() +{ + static unsigned int arch; + if (arch == 0) + { + unsigned int unused; + GetAppleMachineInfo(unused, unused, arch); + } + return arch >= AppleMachineInfo::ARMV83; +} + +#endif // __APPLE__ + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +// *************************** IA-32 CPUs *************************** + +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + +bool CRYPTOPP_SECTION_INIT g_x86DetectionDone = false; +bool CRYPTOPP_SECTION_INIT g_hasSSE2 = false; +bool CRYPTOPP_SECTION_INIT g_hasSSSE3 = false; +bool CRYPTOPP_SECTION_INIT g_hasSSE41 = false; +bool CRYPTOPP_SECTION_INIT g_hasSSE42 = false; +bool CRYPTOPP_SECTION_INIT g_hasAESNI = false; +bool CRYPTOPP_SECTION_INIT g_hasCLMUL = false; +bool CRYPTOPP_SECTION_INIT g_hasMOVBE = false; +bool CRYPTOPP_SECTION_INIT g_hasAVX = false; +bool CRYPTOPP_SECTION_INIT g_hasAVX2 = false; +bool CRYPTOPP_SECTION_INIT g_hasADX = false; +bool CRYPTOPP_SECTION_INIT g_hasSHA = false; +bool CRYPTOPP_SECTION_INIT g_hasRDRAND = false; +bool CRYPTOPP_SECTION_INIT g_hasRDSEED = false; +bool CRYPTOPP_SECTION_INIT g_isP4 = false; +bool CRYPTOPP_SECTION_INIT g_hasPadlockRNG = false; +bool CRYPTOPP_SECTION_INIT g_hasPadlockACE = false; +bool CRYPTOPP_SECTION_INIT g_hasPadlockACE2 = false; +bool CRYPTOPP_SECTION_INIT g_hasPadlockPHE = false; +bool CRYPTOPP_SECTION_INIT g_hasPadlockPMM = false; +word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; + +// For Solaris 11 +extern bool CPU_ProbeSSE2(); + +// xcr0 is available when xgetbv is present. +// The intrinsic is broke on GCC 8.1 and earlier. Also see +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684. +word64 XGetBV(word32 num) +{ +// Visual Studio 2010 SP1 and above, 32 and 64-bit +// https://github.com/weidai11/cryptopp/issues/972 +#if defined(_MSC_VER) && (_MSC_FULL_VER >= 160040219) + + return _xgetbv(num); + +// Visual Studio 2008 and below, 64-bit +#elif defined(_MSC_VER) && defined(_M_X64) + + return XGETBV64(num); + +// Visual Studio 2008 and below, 32-bit +#elif defined(_MSC_VER) && defined(_M_IX86) + + word32 a=0, d=0; + __asm { + push eax + push edx + push ecx + mov ecx, num + _emit 0x0f + _emit 0x01 + _emit 0xd0 + mov a, eax + mov d, edx + pop ecx + pop edx + pop eax + } + return (static_cast(d) << 32) | a; + +// GCC 4.4 and above +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + + word32 a=0, d=0; + __asm__ + ( + "xgetbv" : "=a"(a), "=d"(d) : "c"(num) : "cc" + ); + return (static_cast(d) << 32) | a; + +// Remainder of GCC and compatibles. +#elif defined(__GNUC__) || defined(__clang__) || defined(__SUNPRO_CC) + + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71659 and + // http://www.agner.org/optimize/vectorclass/read.php?i=65 + word32 a=0, d=0; + __asm__ + ( + ".byte 0x0f, 0x01, 0xd0" "\n\t" + : "=a"(a), "=d"(d) : "c"(num) : "cc" + ); + return (static_cast(d) << 32) | a; +#else + # error "Need an xgetbv function" +#endif +} + +// No inline due to Borland/Embarcadero and Issue 498 +// cpu.cpp (131): E2211 Inline assembly not allowed in inline and template functions +bool CpuId(word32 func, word32 subfunc, word32 output[4]) +{ +// Visual Studio 2010 and above, 32 and 64-bit +#if defined(_MSC_VER) && (_MSC_VER >= 1600) + + __cpuidex((int *)output, func, subfunc); + return true; + +// Visual Studio 2008 and below, 64-bit +#elif defined(_MSC_VER) && defined(_M_X64) + + CPUID64(func, subfunc, output); + return true; + +// Visual Studio 2008 and below, 32-bit +#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__BORLANDC__) + + __try + { + // Borland/Embarcadero and Issue 500 + // Local variables for cpuid output + word32 a, b, c, d; + __asm + { + push ebx + mov eax, func + mov ecx, subfunc + cpuid + mov [a], eax + mov [b], ebx + mov [c], ecx + mov [d], edx + pop ebx + } + output[0] = a; + output[1] = b; + output[2] = c; + output[3] = d; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + + return true; + +// Linux, Unix, OS X, Solaris, Cygwin, MinGW +#else + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + +# ifndef __MINGW32__ + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask) != 0) + { + signal(SIGILL, oldHandler); + return false; + } +# endif + + if (setjmp(s_jmpNoCPUID)) + result = false; + else + { + asm volatile + ( + // save ebx in case -fPIC is being used +# if CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 + "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx" +# else + "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" +# endif + : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3]) + : "a" (func), "c" (subfunc) + : "cc" + ); + } + +# ifndef __MINGW32__ + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); +# endif + + signal(SIGILL, oldHandler); + return result; +#endif +} + +void DetectX86Features() +{ + // Coverity finding CID 171239. Initialize arrays. + // Indexes: EAX=0, EBX=1, ECX=2, EDX=3 + word32 cpuid0[4]={0}, cpuid1[4]={0}, cpuid2[4]={0}; + +#if defined(CRYPTOPP_DISABLE_ASM) + // Not available + goto done; +#else + if (!CpuId(0, 0, cpuid0)) + goto done; + if (!CpuId(1, 0, cpuid1)) + goto done; +#endif + + CRYPTOPP_CONSTANT(EAX_REG = 0); + CRYPTOPP_CONSTANT(EBX_REG = 1); + CRYPTOPP_CONSTANT(ECX_REG = 2); + CRYPTOPP_CONSTANT(EDX_REG = 3); + + CRYPTOPP_CONSTANT(MMX_FLAG = (1 << 24)); // EDX + CRYPTOPP_CONSTANT(SSE_FLAG = (1 << 25)); // EDX + CRYPTOPP_CONSTANT(SSE2_FLAG = (1 << 26)); // EDX + + CRYPTOPP_CONSTANT(SSE3_FLAG = (1 << 0)); // ECX + CRYPTOPP_CONSTANT(SSSE3_FLAG = (1 << 9)); // ECX + CRYPTOPP_CONSTANT(SSE41_FLAG = (1 << 19)); // ECX + CRYPTOPP_CONSTANT(SSE42_FLAG = (1 << 20)); // ECX + CRYPTOPP_CONSTANT(MOVBE_FLAG = (1 << 22)); // ECX + CRYPTOPP_CONSTANT(AESNI_FLAG = (1 << 25)); // ECX + CRYPTOPP_CONSTANT(CLMUL_FLAG = (1 << 1)); // ECX + + CRYPTOPP_CONSTANT(XSAVE_FLAG = (1 << 26)); // ECX + CRYPTOPP_CONSTANT(OSXSAVE_FLAG = (1 << 27)); // ECX + + CRYPTOPP_CONSTANT(AVX_FLAG = (3 << 27)); // ECX + CRYPTOPP_CONSTANT(YMM_FLAG = (3 << 1)); // CR0 + + // x86_64 machines don't check some flags because SSE2 + // is part of the core instruction set architecture + CRYPTOPP_UNUSED(MMX_FLAG); CRYPTOPP_UNUSED(SSE_FLAG); + CRYPTOPP_UNUSED(SSE2_FLAG); CRYPTOPP_UNUSED(SSE3_FLAG); + CRYPTOPP_UNUSED(XSAVE_FLAG); + +#if (CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + // 64-bit core instruction set includes SSE2. Just check + // the OS enabled SSE2 support using OSXSAVE. + g_hasSSE2 = (cpuid1[ECX_REG] & OSXSAVE_FLAG) != 0; +#else + // Check the processor supports SSE2. Then use OSXSAVE to + // signal OS support for SSE2 to avoid probes. + // Also see http://stackoverflow.com/a/22521619/608639 + // and http://github.com/weidai11/cryptopp/issues/511. + if ((cpuid1[EDX_REG] & SSE2_FLAG) == SSE2_FLAG) + g_hasSSE2 = (cpuid1[ECX_REG] & XSAVE_FLAG) != 0 && + (cpuid1[ECX_REG] & OSXSAVE_FLAG) != 0; +#endif + + // Solaris 11 i86pc does not signal SSE support using + // OSXSAVE. We need to probe for SSE support. + if (g_hasSSE2 == false) + g_hasSSE2 = CPU_ProbeSSE2(); + + if (g_hasSSE2 == false) + goto done; + + g_hasSSSE3 = (cpuid1[ECX_REG] & SSSE3_FLAG) != 0; + g_hasSSE41 = (cpuid1[ECX_REG] & SSE41_FLAG) != 0; + g_hasSSE42 = (cpuid1[ECX_REG] & SSE42_FLAG) != 0; + g_hasMOVBE = (cpuid1[ECX_REG] & MOVBE_FLAG) != 0; + g_hasAESNI = (cpuid1[ECX_REG] & AESNI_FLAG) != 0; + g_hasCLMUL = (cpuid1[ECX_REG] & CLMUL_FLAG) != 0; + + // AVX is similar to SSE. Check if AVX is available on the cpu, then + // check if the OS enabled XSAVE/XRESTORE for the extended registers. + // https://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled + if ((cpuid1[ECX_REG] & AVX_FLAG) == AVX_FLAG) + { + word64 xcr0 = XGetBV(0); + g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG; + } + + if (IsIntel(cpuid0)) + { + CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30)); + CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18)); + CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19)); + CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29)); + CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5)); + + g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf; + g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1); + g_hasRDRAND = (cpuid1[ECX_REG] & RDRAND_FLAG) != 0; + + if (cpuid0[EAX_REG] >= 7) + { + if (CpuId(7, 0, cpuid2)) + { + g_hasRDSEED = (cpuid2[EBX_REG] & RDSEED_FLAG) != 0; + g_hasADX = (cpuid2[EBX_REG] & ADX_FLAG) != 0; + g_hasSHA = (cpuid2[EBX_REG] & SHA_FLAG) != 0; + g_hasAVX2 = (cpuid2[EBX_REG] & AVX2_FLAG) != 0; + } + } + } + else if (IsAMD(cpuid0) || IsHygon(cpuid0)) + { + CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30)); + CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18)); + CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19)); + CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29)); + CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5)); + + CpuId(0x80000005, 0, cpuid2); + g_cacheLineSize = GETBYTE(cpuid2[ECX_REG], 0); + g_hasRDRAND = (cpuid1[ECX_REG] & RDRAND_FLAG) != 0; + + if (cpuid0[EAX_REG] >= 7) + { + if (CpuId(7, 0, cpuid2)) + { + g_hasRDSEED = (cpuid2[EBX_REG] & RDSEED_FLAG) != 0; + g_hasADX = (cpuid2[EBX_REG] & ADX_FLAG) != 0; + g_hasSHA = (cpuid2[EBX_REG] & SHA_FLAG) != 0; + g_hasAVX2 = (cpuid2[EBX_REG] & AVX2_FLAG) != 0; + } + } + + // Unconditionally disable RDRAND and RDSEED on AMD cpu's with family 15h or 16h. + // See Crypto++ Issue 924, https://github.com/weidai11/cryptopp/issues/924, + // Clear RDRAND CPUID bit on AMD family 15h/16h, https://lore.kernel.org/patchwork/patch/1115413/, + // and AMD CPUID Specification, https://www.amd.com/system/files/TechDocs/25481.pdf + { + CRYPTOPP_CONSTANT(FAMILY_BASE_FLAG = (0x0f << 8)); + CRYPTOPP_CONSTANT(FAMILY_EXT_FLAG = (0xff << 20)); + + word32 family = (cpuid1[0] & FAMILY_BASE_FLAG) >> 8; + if (family == 0xf) + family += (cpuid1[0] & FAMILY_EXT_FLAG) >> 20; + if (family == 0x15 || family == 0x16) + { + g_hasRDRAND = false; + g_hasRDSEED = false; + } + } + } + else if (IsVIA(cpuid0)) + { + // Two bits: available and enabled + CRYPTOPP_CONSTANT( RNG_FLAGS = (0x3 << 2)); + CRYPTOPP_CONSTANT( ACE_FLAGS = (0x3 << 6)); + CRYPTOPP_CONSTANT(ACE2_FLAGS = (0x3 << 8)); + CRYPTOPP_CONSTANT( PHE_FLAGS = (0x3 << 10)); + CRYPTOPP_CONSTANT( PMM_FLAGS = (0x3 << 12)); + + CpuId(0xC0000000, 0, cpuid2); + word32 extendedFeatures = cpuid2[0]; + + if (extendedFeatures >= 0xC0000001) + { + CpuId(0xC0000001, 0, cpuid2); + g_hasPadlockRNG = (cpuid2[EDX_REG] & RNG_FLAGS) != 0; + g_hasPadlockACE = (cpuid2[EDX_REG] & ACE_FLAGS) != 0; + g_hasPadlockACE2 = (cpuid2[EDX_REG] & ACE2_FLAGS) != 0; + g_hasPadlockPHE = (cpuid2[EDX_REG] & PHE_FLAGS) != 0; + g_hasPadlockPMM = (cpuid2[EDX_REG] & PMM_FLAGS) != 0; + } + + if (extendedFeatures >= 0xC0000005) + { + CpuId(0xC0000005, 0, cpuid2); + g_cacheLineSize = GETBYTE(cpuid2[ECX_REG], 0); + } + } + + // Keep AVX2 in sync with OS support for AVX. AVX tests both + // cpu support and OS support, while AVX2 only tests cpu support. + g_hasAVX2 &= g_hasAVX; + +done: + +#if defined(_SC_LEVEL1_DCACHE_LINESIZE) + // Glibc does not implement on some platforms. The runtime returns 0 instead of error. + // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c + int cacheLineSize = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE); + if (g_cacheLineSize == 0 && cacheLineSize > 0) + g_cacheLineSize = cacheLineSize; +#endif + + if (g_cacheLineSize == 0) + g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; + + *const_cast(&g_x86DetectionDone) = true; +} + +// *************************** ARM-32, Aarch32 and Aarch64 *************************** + +#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8) + +bool CRYPTOPP_SECTION_INIT g_ArmDetectionDone = false; +bool CRYPTOPP_SECTION_INIT g_hasARMv7 = false; +bool CRYPTOPP_SECTION_INIT g_hasNEON = false; +bool CRYPTOPP_SECTION_INIT g_hasPMULL = false; +bool CRYPTOPP_SECTION_INIT g_hasCRC32 = false; +bool CRYPTOPP_SECTION_INIT g_hasAES = false; +bool CRYPTOPP_SECTION_INIT g_hasSHA1 = false; +bool CRYPTOPP_SECTION_INIT g_hasSHA2 = false; +bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false; +bool CRYPTOPP_SECTION_INIT g_hasSHA3 = false; +bool CRYPTOPP_SECTION_INIT g_hasSM3 = false; +bool CRYPTOPP_SECTION_INIT g_hasSM4 = false; +word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; + +// ARM does not have an unprivileged equivalent to CPUID on IA-32. We have to +// jump through some hoops to detect features on a wide array of platforms. +// Our strategy is two part. First, attempt to *Query* the OS for a feature, +// like using getauxval on Linux. If that fails, then *Probe* the cpu +// executing an instruction and an observe a SIGILL if unsupported. The probes +// are in source files where compilation options like -march=armv8-a+crc make +// intrinsics available. They are expensive when compared to a standard OS +// feature query. Always perform the feature query first. For Linux see +// http://sourceware.org/ml/libc-help/2017-08/msg00012.html +// Avoid probes on Apple platforms because Apple's signal handling for SIGILLs +// appears broken. We are trying to figure out a way to feature test without +// probes. Also see http://stackoverflow.com/a/11197770/608639 and +// http://gist.github.com/erkanyildiz/390a480f27e86f8cd6ba. + +extern bool CPU_ProbeARMv7(); +extern bool CPU_ProbeNEON(); +extern bool CPU_ProbeCRC32(); +extern bool CPU_ProbeAES(); +extern bool CPU_ProbeSHA1(); +extern bool CPU_ProbeSHA256(); +extern bool CPU_ProbeSHA512(); +extern bool CPU_ProbeSHA3(); +extern bool CPU_ProbeSM3(); +extern bool CPU_ProbeSM4(); +extern bool CPU_ProbePMULL(); + +// https://github.com/torvalds/linux/blob/master/arch/arm/include/uapi/asm/hwcap.h +// https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h +#ifndef HWCAP_ARMv7 +# define HWCAP_ARMv7 (1 << 29) +#endif +#ifndef HWCAP_ASIMD +# define HWCAP_ASIMD (1 << 1) +#endif +#ifndef HWCAP_NEON +# define HWCAP_NEON (1 << 12) +#endif +#ifndef HWCAP_CRC32 +# define HWCAP_CRC32 (1 << 7) +#endif +#ifndef HWCAP2_CRC32 +# define HWCAP2_CRC32 (1 << 4) +#endif +#ifndef HWCAP_PMULL +# define HWCAP_PMULL (1 << 4) +#endif +#ifndef HWCAP2_PMULL +# define HWCAP2_PMULL (1 << 1) +#endif +#ifndef HWCAP_AES +# define HWCAP_AES (1 << 3) +#endif +#ifndef HWCAP2_AES +# define HWCAP2_AES (1 << 0) +#endif +#ifndef HWCAP_SHA1 +# define HWCAP_SHA1 (1 << 5) +#endif +#ifndef HWCAP_SHA2 +# define HWCAP_SHA2 (1 << 6) +#endif +#ifndef HWCAP2_SHA1 +# define HWCAP2_SHA1 (1 << 2) +#endif +#ifndef HWCAP2_SHA2 +# define HWCAP2_SHA2 (1 << 3) +#endif +#ifndef HWCAP_SHA3 +# define HWCAP_SHA3 (1 << 17) +#endif +#ifndef HWCAP_SM3 +# define HWCAP_SM3 (1 << 18) +#endif +#ifndef HWCAP_SM4 +# define HWCAP_SM4 (1 << 19) +#endif +#ifndef HWCAP_SHA512 +# define HWCAP_SHA512 (1 << 21) +#endif + +inline bool CPU_QueryARMv7() +{ +#if defined(__ANDROID__) && defined(__arm__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0)) + return true; +#elif defined(__linux__) && defined(__arm__) + if ((getauxval(AT_HWCAP) & HWCAP_ARMv7) != 0 || + (getauxval(AT_HWCAP) & HWCAP_NEON) != 0) + return true; +#elif defined(__APPLE__) && defined(__arm__) + // Apple hardware is ARMv7 or above. + return true; +#elif defined(_WIN32) && defined(_M_ARM64) + // Windows 10 ARM64 is only supported on Armv8a and above + return true; +#endif + return false; +} + +inline bool CPU_QueryNEON() +{ +#if defined(__ANDROID__) && defined(__aarch64__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_ASIMD) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__arm__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_ASIMD) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_ASIMD) != 0) + return true; +#elif defined(__linux__) && defined(__arm__) + if ((getauxval(AT_HWCAP) & HWCAP_NEON) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) + // Core feature set for Aarch32 and Aarch64. + if (IsAppleMachineARMv8()) + return true; +#elif defined(_WIN32) && defined(_M_ARM64) + // Windows 10 ARM64 is only supported on Armv8a and above + if (IsProcessorFeaturePresent(PF_ARM_V8_INSTRUCTIONS_AVAILABLE) != 0) + return true; +#endif + return false; +} + +inline bool CPU_QueryCRC32() +{ +#if defined(__ANDROID__) && defined(__aarch64__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_CRC32) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__aarch32__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_CRC32) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_CRC32) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) + // M1 processor + if (IsAppleMachineARMv82()) + return true; +#elif defined(_WIN32) && defined(_M_ARM64) + if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0) + return true; +#endif + return false; +} + +inline bool CPU_QueryPMULL() +{ +#if defined(__ANDROID__) && defined(__aarch64__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_PMULL) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__aarch32__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_PMULL) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_PMULL) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_PMULL) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) + // M1 processor + if (IsAppleMachineARMv82()) + return true; +#elif defined(_WIN32) && defined(_M_ARM64) + if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0) + return true; +#endif + return false; +} + +inline bool CPU_QueryAES() +{ +#if defined(__ANDROID__) && defined(__aarch64__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__aarch32__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_AES) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_AES) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) + // M1 processor + if (IsAppleMachineARMv82()) + return true; +#elif defined(_WIN32) && defined(_M_ARM64) + if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0) + return true; +#endif + return false; +} + +inline bool CPU_QuerySHA1() +{ +#if defined(__ANDROID__) && defined(__aarch64__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA1) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__aarch32__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA1) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_SHA1) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_SHA1) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) + // M1 processor + if (IsAppleMachineARMv82()) + return true; +#elif defined(_WIN32) && defined(_M_ARM64) + if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0) + return true; +#endif + return false; +} + +inline bool CPU_QuerySHA256() +{ +#if defined(__ANDROID__) && defined(__aarch64__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA2) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__aarch32__) + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA2) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_SHA2) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_SHA2) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) + // M1 processor + if (IsAppleMachineARMv82()) + return true; +#elif defined(_WIN32) && defined(_M_ARM64) + if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0) + return true; +#endif + return false; +} + +// Some ARMv8.2 features are disabled at the moment +inline bool CPU_QuerySHA3() +{ + // According to the ARM manual, SHA3 depends upon SHA1 and SHA2. + // If SHA1 and SHA2 are not present, then SHA3 and SHA512 are + // not present. Also see Arm A64 Instruction Set Architecture, + // https://developer.arm.com/documentation/ddi0596/2020-12/ + if (!g_hasSHA1 || !g_hasSHA2) { return false; } + +#if defined(__ANDROID__) && defined(__aarch64__) && 0 + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA3) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__aarch32__) && 0 + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA3) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_SHA3) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_SHA3) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) + // M1 processor + if (IsAppleMachineARMv82()) + return true; +#endif + return false; +} + +// Some ARMv8.2 features are disabled at the moment +inline bool CPU_QuerySHA512() +{ + // According to the ARM manual, SHA512 depends upon SHA1 and SHA2. + // If SHA1 and SHA2 are not present, then SHA3 and SHA512 are + // not present. Also see Arm A64 Instruction Set Architecture, + // https://developer.arm.com/documentation/ddi0596/2020-12/ + if (!g_hasSHA1 || !g_hasSHA2) { return false; } + +#if defined(__ANDROID__) && defined(__aarch64__) && 0 + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA512) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__aarch32__) && 0 + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA512) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_SHA512) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_SHA512) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) + // M1 processor + if (IsAppleMachineARMv82()) + return true; +#endif + return false; +} + +// Some ARMv8.2 features are disabled at the moment +inline bool CPU_QuerySM3() +{ +#if defined(__ANDROID__) && defined(__aarch64__) && 0 + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM3) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__aarch32__) && 0 + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM3) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_SM3) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_SM3) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) && 0 + // No Apple support yet. +#endif + return false; +} + +// Some ARMv8.2 features are disabled at the moment +inline bool CPU_QuerySM4() +{ +#if defined(__ANDROID__) && defined(__aarch64__) && 0 + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM4) != 0)) + return true; +#elif defined(__ANDROID__) && defined(__aarch32__) && 0 + if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) && + ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM4) != 0)) + return true; +#elif defined(__linux__) && defined(__aarch64__) + if ((getauxval(AT_HWCAP) & HWCAP_SM4) != 0) + return true; +#elif defined(__linux__) && defined(__aarch32__) + if ((getauxval(AT_HWCAP2) & HWCAP2_SM4) != 0) + return true; +#elif defined(__APPLE__) && defined(__aarch64__) && 0 + // No Apple support yet. +#endif + return false; +} + +void DetectArmFeatures() +{ + // The CPU_ProbeXXX's return false for OSes which + // can't tolerate SIGILL-based probes + g_hasARMv7 = CPU_QueryARMv7() || CPU_ProbeARMv7(); + g_hasNEON = CPU_QueryNEON() || CPU_ProbeNEON(); + g_hasCRC32 = CPU_QueryCRC32() || CPU_ProbeCRC32(); + g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL(); + g_hasAES = CPU_QueryAES() || CPU_ProbeAES(); + g_hasSHA1 = CPU_QuerySHA1() || CPU_ProbeSHA1(); + g_hasSHA2 = CPU_QuerySHA256() || CPU_ProbeSHA256(); + g_hasSHA512 = CPU_QuerySHA512(); // || CPU_ProbeSHA512(); + g_hasSHA3 = CPU_QuerySHA3(); // || CPU_ProbeSHA3(); + g_hasSM3 = CPU_QuerySM3(); // || CPU_ProbeSM3(); + g_hasSM4 = CPU_QuerySM4(); // || CPU_ProbeSM4(); + +#if defined(_SC_LEVEL1_DCACHE_LINESIZE) + // Glibc does not implement on some platforms. The runtime returns 0 instead of error. + // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c + int cacheLineSize = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE); + if (cacheLineSize > 0) + g_cacheLineSize = cacheLineSize; +#endif + + if (g_cacheLineSize == 0) + g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; + + *const_cast(&g_ArmDetectionDone) = true; +} + +// *************************** PowerPC and PowerPC64 *************************** + +#elif (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) + +bool CRYPTOPP_SECTION_INIT g_PowerpcDetectionDone = false; +bool CRYPTOPP_SECTION_INIT g_hasAltivec = false; +bool CRYPTOPP_SECTION_INIT g_hasPower7 = false; +bool CRYPTOPP_SECTION_INIT g_hasPower8 = false; +bool CRYPTOPP_SECTION_INIT g_hasPower9 = false; +bool CRYPTOPP_SECTION_INIT g_hasAES = false; +bool CRYPTOPP_SECTION_INIT g_hasPMULL = false; +bool CRYPTOPP_SECTION_INIT g_hasSHA256 = false; +bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false; +bool CRYPTOPP_SECTION_INIT g_hasDARN = false; +word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; + +extern bool CPU_ProbeAltivec(); +extern bool CPU_ProbePower7(); +extern bool CPU_ProbePower8(); +extern bool CPU_ProbePower9(); +extern bool CPU_ProbeAES(); +extern bool CPU_ProbePMULL(); +extern bool CPU_ProbeSHA256(); +extern bool CPU_ProbeSHA512(); +extern bool CPU_ProbeDARN(); + +// AIX defines. We used to just call __power_7_andup() +// and friends but at Power9, too many compilers were +// missing __power_9_andup(). Instead we switched to +// a pattern similar to OpenSSL caps testing. +#ifndef __power_6_andup +# define __power_6_andup() __power_set(0xffffffffU<<14) +#endif +#ifndef __power_7_andup +# define __power_7_andup() __power_set(0xffffffffU<<15) +#endif +#ifndef __power_8_andup +# define __power_8_andup() __power_set(0xffffffffU<<16) +#endif +#ifndef __power_9_andup +# define __power_9_andup() __power_set(0xffffffffU<<17) +#endif + +// AIX first supported Altivec at Power6, though it +// was available much earlier for other vendors. +inline bool CPU_QueryAltivec() +{ +#if defined(__linux__) && defined(PPC_FEATURE_HAS_ALTIVEC) + if ((getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC) != 0) + return true; +#elif defined(_AIX) + if (__power_6_andup() != 0) + return true; +#elif defined(__APPLE__) && defined(__POWERPC__) + unsigned int unused, arch; + GetAppleMachineInfo(unused, unused, arch); + return arch == AppleMachineInfo::PowerMac; +#elif defined(__FreeBSD__) && defined(PPC_FEATURE_HAS_ALTIVEC) + unsigned long cpufeatures; + if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)) == 0) + if ((cpufeatures & PPC_FEATURE_HAS_ALTIVEC) != 0) + return true; +#endif + return false; +} + +inline bool CPU_QueryPower7() +{ + // Power7 and ISA 2.06 +#if defined(__linux__) && defined(PPC_FEATURE_ARCH_2_06) + if ((getauxval(AT_HWCAP) & PPC_FEATURE_ARCH_2_06) != 0) + return true; +#elif defined(_AIX) + if (__power_7_andup() != 0) + return true; +#elif defined(__FreeBSD__) && defined(PPC_FEATURE_ARCH_2_06) + unsigned long cpufeatures; + if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)) == 0) + if ((cpufeatures & PPC_FEATURE_ARCH_2_06) != 0) + return true; +#endif + return false; +} + +inline bool CPU_QueryPower8() +{ + // Power8 and ISA 2.07 provide in-core crypto. +#if defined(__linux__) && defined(PPC_FEATURE2_ARCH_2_07) + if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07) != 0) + return true; +#elif defined(_AIX) + if (__power_8_andup() != 0) + return true; +#elif defined(__FreeBSD__) && defined(PPC_FEATURE2_ARCH_2_07) + unsigned long cpufeatures; + if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)) == 0) + if ((cpufeatures & PPC_FEATURE_ARCH_2_07) != 0) + return true; +#endif + return false; +} + +inline bool CPU_QueryPower9() +{ + // Power9 and ISA 3.0. +#if defined(__linux__) && defined(PPC_FEATURE2_ARCH_3_00) + if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0) + return true; +#elif defined(_AIX) + if (__power_9_andup() != 0) + return true; +#elif defined(__FreeBSD__) && defined(PPC_FEATURE2_ARCH_3_00) + unsigned long cpufeatures; + if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)) == 0) + if ((cpufeatures & PPC_FEATURE_ARCH2_3_00) != 0) + return true; +#endif + return false; +} + +inline bool CPU_QueryAES() +{ + // Power8 and ISA 2.07 provide in-core crypto. Glibc + // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO. +#if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO) + if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0) + return true; +#elif defined(_AIX) + if (__power_8_andup() != 0) + return true; +#elif defined(__FreeBSD__) && defined(PPC_FEATURE2_HAS_VEC_CRYPTO) + unsigned long cpufeatures; + if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0) + if ((cpufeatures & PPC_FEATURE2_HAS_VEC_CRYPTO != 0) + return true; +#endif + return false; +} + +inline bool CPU_QueryPMULL() +{ + // Power8 and ISA 2.07 provide in-core crypto. Glibc + // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO. +#if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO) + if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0) + return true; +#elif defined(_AIX) + if (__power_8_andup() != 0) + return true; +#elif defined(__FreeBSD__) && defined(PPC_FEATURE2_HAS_VEC_CRYPTO) + unsigned long cpufeatures; + if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0) + if ((cpufeatures & PPC_FEATURE2_HAS_VEC_CRYPTO != 0) + return true; +#endif + return false; +} + +inline bool CPU_QuerySHA256() +{ + // Power8 and ISA 2.07 provide in-core crypto. Glibc + // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO. +#if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO) + if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0) + return true; +#elif defined(_AIX) + if (__power_8_andup() != 0) + return true; +#elif defined(__FreeBSD__) && defined(PPC_FEATURE2_HAS_VEC_CRYPTO) + unsigned long cpufeatures; + if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0) + if ((cpufeatures & PPC_FEATURE2_HAS_VEC_CRYPTO != 0) + return true; +#endif + return false; +} +inline bool CPU_QuerySHA512() +{ + // Power8 and ISA 2.07 provide in-core crypto. Glibc + // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO. +#if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO) + if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0) + return true; +#elif defined(_AIX) + if (__power_8_andup() != 0) + return true; +#elif defined(__FreeBSD__) && defined(PPC_FEATURE2_HAS_VEC_CRYPTO) + unsigned long cpufeatures; + if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0) + if ((cpufeatures & PPC_FEATURE2_HAS_VEC_CRYPTO != 0) + return true; +#endif + return false; +} + +// Power9 random number generator +inline bool CPU_QueryDARN() +{ + // Power9 and ISA 3.0 provide DARN. It looks like + // Glibc offers PPC_FEATURE2_DARN. +#if defined(__linux__) && defined(PPC_FEATURE2_ARCH_3_00) + if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0) + return true; +#elif defined(_AIX) + if (__power_9_andup() != 0) + return true; +#elif defined(__FreeBSD__) && defined(PPC_FEATURE2_ARCH_3_00) + unsigned long cpufeatures; + if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0) + if ((cpufeatures & PPC_FEATURE2_ARCH_3_00) != 0) + return true; +#endif + return false; +} + +void DetectPowerpcFeatures() +{ + // GCC 10 is giving us trouble in CPU_ProbePower9() and + // CPU_ProbeDARN(). GCC is generating POWER9 instructions + // on POWER8 for ppc_power9.cpp. The compiler idiots did + // not think through the consequences of requiring us to + // use -mcpu=power9 to unlock the ISA. Epic fail. + // https://github.com/weidai11/cryptopp/issues/986 + + // The CPU_ProbeXXX's return false for OSes which + // can't tolerate SIGILL-based probes, like Apple + g_hasAltivec = CPU_QueryAltivec() || CPU_ProbeAltivec(); + g_hasPower7 = CPU_QueryPower7() || CPU_ProbePower7(); + g_hasPower8 = CPU_QueryPower8() || CPU_ProbePower8(); + g_hasPower9 = CPU_QueryPower9() || CPU_ProbePower9(); + g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL(); + g_hasAES = CPU_QueryAES() || CPU_ProbeAES(); + g_hasSHA256 = CPU_QuerySHA256() || CPU_ProbeSHA256(); + g_hasSHA512 = CPU_QuerySHA512() || CPU_ProbeSHA512(); + g_hasDARN = CPU_QueryDARN() || CPU_ProbeDARN(); + +#if defined(_AIX) && defined(SC_L1C_DLS) + // /usr/include/sys/systemcfg.h + int cacheLineSize = getsystemcfg(SC_L1C_DLS); + if (cacheLineSize > 0) + g_cacheLineSize = cacheLineSize; +#elif defined(_SC_LEVEL1_DCACHE_LINESIZE) + // Glibc does not implement on some platforms. The runtime returns 0 instead of error. + // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c + int cacheLineSize = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE); + if (cacheLineSize > 0) + g_cacheLineSize = cacheLineSize; +#endif + + if (g_cacheLineSize == 0) + g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; + + *const_cast(&g_PowerpcDetectionDone) = true; +} + +#endif +NAMESPACE_END + +// *************************** C++ Static Initialization *************************** + +ANONYMOUS_NAMESPACE_BEGIN + +class InitCpu +{ +public: + InitCpu() + { +#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 + CryptoPP::DetectX86Features(); +#elif CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8 + CryptoPP::DetectArmFeatures(); +#elif CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64 + CryptoPP::DetectPowerpcFeatures(); +#endif + } +}; + +// This is not really needed because HasSSE() and friends can dynamically initialize. +// Everything depends on CPU features so we initialize it once at load time. +// Dynamic initialization will be used if init priorities are not available. + +#if HAVE_GCC_INIT_PRIORITY + const InitCpu s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 10))) = InitCpu(); +#elif HAVE_MSC_INIT_PRIORITY + #pragma warning(disable: 4075) + #pragma init_seg(".CRT$XCU") + const InitCpu s_init; + #pragma warning(default: 4075) +#elif HAVE_XLC_INIT_PRIORITY + // XLC needs constant, not a define + #pragma priority(270) + const InitCpu s_init; +#else + const InitCpu s_init; +#endif + +ANONYMOUS_NAMESPACE_END + +#endif // CRYPTOPP_IMPORTS diff --git a/external/ours/library/crypto/src/shared/original/cpu.h b/external/ours/library/crypto/src/shared/original/cpu.h new file mode 100755 index 000000000..c6f836671 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/cpu.h @@ -0,0 +1,1085 @@ +// 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(__GNUC__) + #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 + +#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(_MSC_VER) || 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/external/ours/library/crypto/src/shared/original/crc.cpp b/external/ours/library/crypto/src/shared/original/crc.cpp new file mode 100755 index 000000000..20addce6a --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/crc.cpp @@ -0,0 +1,367 @@ +// crc.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" +#include "crc.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +// crc_simd.cpp +#if (CRYPTOPP_ARM_CRC32_AVAILABLE) +extern void CRC32_Update_ARMV8(const byte *s, size_t n, word32& c); +extern void CRC32C_Update_ARMV8(const byte *s, size_t n, word32& c); +#endif + +// crc_simd.cpp +#if (CRYPTOPP_SSE42_AVAILABLE) +extern void CRC32C_Update_SSE42(const byte *s, size_t n, word32& c); +#endif + +/* Table of CRC-32's of all single byte values (made by makecrc.c) */ +const word32 CRC32::m_tab[] = { +#if (CRYPTOPP_LITTLE_ENDIAN) + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +#else + 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L, + 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L, + 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L, + 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L, + 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L, + 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L, + 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L, + 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L, + 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L, + 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L, + 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL, + 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L, + 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L, + 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L, + 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L, + 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L, + 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL, + 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L, + 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL, + 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L, + 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L, + 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L, + 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL, + 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL, + 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L, + 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL, + 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L, + 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL, + 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L, + 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L, + 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L, + 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L, + 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L, + 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL, + 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L, + 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L, + 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L, + 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L, + 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L, + 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L, + 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L, + 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L, + 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL, + 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L, + 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L, + 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L, + 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L, + 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L, + 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL, + 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L, + 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL, + 0x8def022dL +#endif +}; + +std::string CRC32::AlgorithmProvider() const +{ +#if (CRYPTOPP_ARM_CRC32_AVAILABLE) + if (HasCRC32()) + return "ARMv8"; +#endif + return "C++"; +} + +CRC32::CRC32() +{ + Reset(); +} + +void CRC32::Update(const byte *s, size_t n) +{ +#if (CRYPTOPP_ARM_CRC32_AVAILABLE) + if (HasCRC32()) + { + CRC32_Update_ARMV8(s, n, m_crc); + return; + } +#endif + + word32 crc = m_crc; + + for(; !IsAligned(s) && n > 0; n--) + crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc); + + while (n >= 4) + { + crc ^= *(const word32 *)(void*)s; + crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); + crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); + crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); + crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); + n -= 4; s += 4; + } + + while (n--) + crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc); + + m_crc = crc; +} + +void CRC32::TruncatedFinal(byte *hash, size_t size) +{ + ThrowIfInvalidTruncatedSize(size); + + m_crc ^= CRC32_NEGL; + for (size_t i=0; i(s) && n > 0; n--) + crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc); + + while (n >= 4) + { + crc ^= *(const word32 *)(void*)s; + crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); + crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); + crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); + crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); + n -= 4; s += 4; + } + + while (n--) + crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc); + + m_crc = crc; +} + +void CRC32C::TruncatedFinal(byte *hash, size_t size) +{ + ThrowIfInvalidTruncatedSize(size); + + m_crc ^= CRC32_NEGL; + for (size_t i=0; i> 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();} + + void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);} + 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();} + + void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);} + 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/external/ours/library/crypto/src/shared/original/crc_simd.cpp b/external/ours/library/crypto/src/shared/original/crc_simd.cpp new file mode 100755 index 000000000..c1a0725f5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/crc_simd.cpp @@ -0,0 +1,172 @@ +// crc_simd.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// +// This source file uses intrinsics to gain access to SSE4.2 and +// ARMv8a CRC-32 and CRC-32C instructions. A separate source file +// is needed because additional CXXFLAGS are required to enable +// the appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" +#include "misc.h" + +#if (CRYPTOPP_SSE42_AVAILABLE) +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +#if (CRYPTOPP_ARM_CRC32_AVAILABLE) +# include "arm_simd.h" +#endif + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#ifndef EXCEPTION_EXECUTE_HANDLER +# define EXCEPTION_EXECUTE_HANDLER 1 +#endif + +#define CONST_WORD32_CAST(x) ((const word32 *)(void*)(x)) + +// Squash MS LNK4221 and libtool warnings +extern const char CRC_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); + + static jmp_buf s_jmpSIGILL; + static void SigIllHandler(int) + { + longjmp(s_jmpSIGILL, 1); + } +} +#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY + +#if (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8) + +bool CPU_ProbeCRC32() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (CRYPTOPP_ARM_CRC32_AVAILABLE) +# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) + volatile bool result = true; + __try + { + word32 w=0, x=1; byte z=3; + w = CRC32W(w,x); + w = CRC32B(w,z); + w = CRC32CW(w,x); + w = CRC32CB(w,z); + + result = !!w; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + return result; +#else + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + word32 w=0, x=1; byte z=3; + w = CRC32W(w,x); + w = CRC32B(w,z); + w = CRC32CW(w,x); + w = CRC32CB(w,z); + + // Hack... GCC optimizes away the code and returns true + result = !!w; + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_ARM_CRC32_AVAILABLE +} +#endif // ARM32 or ARM64 + +#if (CRYPTOPP_ARM_CRC32_AVAILABLE) +void CRC32_Update_ARMV8(const byte *s, size_t n, word32& c) +{ + for(; !IsAligned(s) && n > 0; s++, n--) + c = CRC32B(c, *s); + + for(; n >= 16; s+=16, n-=16) + c = CRC32Wx4(c, CONST_WORD32_CAST(s)); + + for(; n >= 4; s+=4, n-=4) + c = CRC32W(c, *CONST_WORD32_CAST(s)); + + for(; n > 0; s++, n--) + c = CRC32B(c, *s); +} + +void CRC32C_Update_ARMV8(const byte *s, size_t n, word32& c) +{ + for(; !IsAligned(s) && n > 0; s++, n--) + c = CRC32CB(c, *s); + + for(; n >= 16; s+=16, n-=16) + c = CRC32CWx4(c, CONST_WORD32_CAST(s)); + + for(; n >= 4; s+=4, n-=4) + c = CRC32CW(c, *CONST_WORD32_CAST(s)); + + for(; n > 0; s++, n--) + c = CRC32CB(c, *s); +} +#endif + +#if (CRYPTOPP_SSE42_AVAILABLE) +void CRC32C_Update_SSE42(const byte *s, size_t n, word32& c) +{ + for(; !IsAligned(s) && n > 0; s++, n--) + c = _mm_crc32_u8(c, *s); + + for(; n >= 16; s+=16, n-=16) + { + c = _mm_crc32_u32(_mm_crc32_u32(_mm_crc32_u32(_mm_crc32_u32(c, + *CONST_WORD32_CAST(s+ 0)), *CONST_WORD32_CAST(s+ 4)), + *CONST_WORD32_CAST(s+ 8)), *CONST_WORD32_CAST(s+12)); + } + + for(; n >= 4; s+=4, n-=4) + c = _mm_crc32_u32(c, *CONST_WORD32_CAST(s)); + + for(; n > 0; s++, n--) + c = _mm_crc32_u8(c, *s); +} +#endif + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/cryptest.nmake b/external/ours/library/crypto/src/shared/original/cryptest.nmake new file mode 100755 index 000000000..1164c25f2 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/cryptest.nmake @@ -0,0 +1,363 @@ +# cryptest.nmake - written and placed in public domain by Jeffrey Walton. +# Copyright assigned to the Crypto++ project. + +# This makefile is used for testing and building cryptlib.lib and cryptest.exe +# under nmake. Open a Visual Studio Developer Prompt and then run +# "nmake /f cryptest.nmake". The build procedure will reveal not so readily +# apparent problems under Microsoft ARM and Metro UI apps. + +# The makefile is not intended for production use, though it may be used as a +# starting point. For example, you can add switches like /MD and /MDd for +# dynamic runtime linking against the Microsoft C++ Runtime libraries. If you +# are building for Windows Phone or Windows Store, then you probably want to +# remove /D_MBCS. The resulting cryptlib.lib may be suitable as a starting +# point for a DLL project using Crypto++. + +# You must also add /DCRYPTOPP_DEBUG or /DDEBUG if you want a debug build with +# the library's assert. The library moved from Posix NDEBUG and assert() to +# CRYPTOPP_ASSERT at 5.6.5 due to CVE-2016-7420. CRYPTOPP_ASSERT has the +# additional benefit of using DebugBreak(), and the program does not crash +# while you are debugging it like would happen with Posix assert(). + +# There is mention of cryptopp.dll, CRYPTOPP_IMPORTS and CRYPTOPP_EXPORTS +# below. They are for testing only. Attempting to produce a working DLL on +# Windows fails. Too many missing symbols because cryptest.exe exercises +# about 80% of the library, but CRYPTOPP_DLL is only used for FIPS algos. + +# The list of LIB_SRCS and TEST_SRCS was generated under Linux with +# "make sources | fold -w73 -s". The list of LIB_OBJS and TEST_OBJS was +# generated with "make sources | fold -w73 -s | sed 's|.cpp|.obj|g'". The +# order of the first three object files are significant. See C++ Static +# Initialization Order Fiasco on the Crypto++ wiki for details. + +# You are free to add and remove files to the list. For example, you can remove +# rdrand.asm build it using NASM, and then include the NASM object file +# rdrand_x86.obj or rdrand_x64.obj. + +########################################################################################### + +# To test debug builds, use the following CXXFLAGS: +# - /DDEBUG /D_DEBUG /Oi /Oy- /Od +# To test release builds, use the following CXXFLAGS: +# - /DNDEBUG /D_NDEBUG /Oi /Oy /O2 +# To test with static C++ runtime linking, use the following CXXFLAGS: +# - /MT (release) or /MTd (debug) +# To test with dynamic C++ runtime linking, use the following CXXFLAGS: +# - /MD (release) or /MDd (debug) +# To test Desktop app, use the following CXXFLAGS: +# - /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP +# To test Windows Store app, use the following CXXFLAGS: +# - /DWINAPI_FAMILY=WINAPI_FAMILY_APP +# To test Windows Phone, use the following CXXFLAGS: +# - /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP +# To test Surface RT (ARM tablet), use the following CXXFLAGS: +# - /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP + +########################################################################################### + +LIB_SRCS = \ + cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp \ + algparam.cpp allocate.cpp arc4.cpp aria.cpp aria_simd.cpp ariatab.cpp \ + asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp \ + blake2.cpp blake2b_simd.cpp blake2s_simd.cpp blowfish.cpp blumshub.cpp \ + camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp \ + chacha_avx.cpp chacha_simd.cpp chachapoly.cpp cham.cpp cham_simd.cpp \ + channels.cpp cmac.cpp crc.cpp crc_simd.cpp darn.cpp default.cpp des.cpp \ + dessp.cpp dh.cpp dh2.cpp dll.cpp donna_32.cpp donna_64.cpp donna_sse.cpp \ + dsa.cpp eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp \ + eprecomp.cpp esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp \ + gcm.cpp gcm_simd.cpp gf256.cpp gf2_32.cpp gf2n.cpp gf2n_simd.cpp \ + gfpcrypt.cpp gost.cpp gzip.cpp hc128.cpp hc256.cpp hex.cpp hight.cpp \ + hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp \ + kalynatab.cpp keccak.cpp keccak_core.cpp keccak_simd.cpp lea.cpp \ + lea_simd.cpp lsh256.cpp lsh256_avx.cpp lsh256_sse.cpp lsh512.cpp \ + lsh512_avx.cpp lsh512_sse.cpp luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp \ + md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp nbtheory.cpp oaep.cpp \ + osrng.cpp padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp \ + pssr.cpp pubkey.cpp queue.cpp rabbit.cpp rabin.cpp randpool.cpp rc2.cpp \ + rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp rijndael.cpp rijndael_simd.cpp \ + ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp \ + seal.cpp seed.cpp serpent.cpp sha.cpp sha3.cpp sha_simd.cpp shacal2.cpp \ + shacal2_simd.cpp shake.cpp shark.cpp sharkbox.cpp simeck.cpp simon.cpp \ + simon128_simd.cpp skipjack.cpp sm3.cpp sm4.cpp sm4_simd.cpp \ + sosemanuk.cpp speck.cpp speck128_simd.cpp square.cpp squaretb.cpp \ + sse_simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp \ + tigertab.cpp ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wake.cpp \ + whrlpool.cpp xed25519.cpp xtr.cpp xtrcrypt.cpp xts.cpp zdeflate.cpp \ + zinflate.cpp zlib.cpp + +LIB_OBJS = \ + cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj \ + algparam.obj allocate.obj arc4.obj aria.obj aria_simd.obj ariatab.obj \ + asn.obj authenc.obj base32.obj base64.obj basecode.obj bfinit.obj \ + blake2.obj blake2b_simd.obj blake2s_simd.obj blowfish.obj blumshub.obj \ + camellia.obj cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj \ + chacha_avx.obj chacha_simd.obj chachapoly.obj cham.obj cham_simd.obj \ + channels.obj cmac.obj crc.obj crc_simd.obj darn.obj default.obj des.obj \ + dessp.obj dh.obj dh2.obj dll.obj donna_32.obj donna_64.obj donna_sse.obj \ + dsa.obj eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj \ + eprecomp.obj esign.obj files.obj filters.obj fips140.obj fipstest.obj \ + gcm.obj gcm_simd.obj gf256.obj gf2_32.obj gf2n.obj gf2n_simd.obj \ + gfpcrypt.obj gost.obj gzip.obj hc128.obj hc256.obj hex.obj hight.obj \ + hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj \ + kalynatab.obj keccak.obj keccak_core.obj keccak_simd.obj lea.obj \ + lea_simd.obj lsh256.obj lsh256_avx.obj lsh256_sse.obj lsh512.obj \ + lsh512_avx.obj lsh512_sse.obj luc.obj mars.obj marss.obj md2.obj md4.obj \ + md5.obj misc.obj modes.obj mqueue.obj mqv.obj nbtheory.obj oaep.obj \ + osrng.obj padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj \ + pssr.obj pubkey.obj queue.obj rabbit.obj rabin.obj randpool.obj rc2.obj \ + rc5.obj rc6.obj rdrand.obj rdtables.obj rijndael.obj rijndael_simd.obj \ + ripemd.obj rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj \ + seal.obj seed.obj serpent.obj sha.obj sha3.obj sha_simd.obj shacal2.obj \ + shacal2_simd.obj shake.obj shark.obj sharkbox.obj simeck.obj simon.obj \ + simon128_simd.obj skipjack.obj sm3.obj sm4.obj sm4_simd.obj \ + sosemanuk.obj speck.obj speck128_simd.obj square.obj squaretb.obj \ + sse_simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj \ + tigertab.obj ttmac.obj tweetnacl.obj twofish.obj vmac.obj wake.obj \ + whrlpool.obj xed25519.obj xtr.obj xtrcrypt.obj xts.obj zdeflate.obj \ + zinflate.obj zlib.obj + +ASM_OBJS = \ + rdrand-x86.obj rdrand-x64.obj rdseed-x86.obj rdseed-x64.obj x64masm.obj x64dll.obj + +TEST_SRCS = \ + test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp \ + dlltest.cpp fipsalgt.cpp validat0.cpp validat1.cpp validat2.cpp \ + validat3.cpp validat4.cpp validat5.cpp validat6.cpp validat7.cpp \ + validat8.cpp validat9.cpp validat10.cpp regtest1.cpp regtest2.cpp \ + regtest3.cpp regtest4.cpp + +TEST_OBJS = \ + test.obj bench1.obj bench2.obj bench3.obj datatest.obj \ + dlltest.obj fipsalgt.obj validat0.obj validat1.obj validat2.obj \ + validat3.obj validat4.obj validat5.obj validat6.obj validat7.obj \ + validat8.obj validat9.obj validat10.obj regtest1.obj regtest2.obj \ + regtest3.obj regtest4.obj + +CXX = cl.exe +LD = link.exe +AR = lib.exe +RM = del +RMDIR = rd + +# We may misdetect the environment on VS2005 or so. Uncomment as +# needed to match the Developer Prompt environment. +# PLATFORM = x86 +# PLATFORM = x64 +# PLATFORM = arm +# PLATFORM = arm64 + +# C4231 is needed for VS2008 and below. Lots of noise... +CXXFLAGS = /nologo /W4 /wd4231 /wd4511 /wd4156 /D_MBCS /Zi /TP /GR /EHsc +LDFLAGS = /nologo /SUBSYSTEM:CONSOLE /DEBUG +ARFLAGS = /nologo +LDLIBS = + +# Compiler debug build. +# CXXFLAGS = $(CXXFLAGS) /DDEBUG /D_DEBUG /Oi /Oy- /Od /MTd +# Compiler release build. +CXXFLAGS = $(CXXFLAGS) /DNDEBUG /D_NDEBUG /Oi /Oy /O2 /MT +# Linker debug build. +# LDFLAGS = $(LDFLAGS) /DEBUG +# Linker release build. +LDFLAGS = $(LDFLAGS) /DEBUG /OPT:REF + +# Attempt to detect when and are available +# http://stackoverflow.com/q/40577415 ? +!IF "$(WINDOWSSDKDIR)" != "" || "$(WINDOWSSDKLIBVERSION)" != "" +CXXFLAGS = $(CXXFLAGS) /FI sdkddkver.h +!ENDIF +!IF "$(WINDOWSPHONEKITDIR)" != "" || "$(UNIVERSALCRTSDKDIR)" != "" || "$(UCRTVERSION)" != "" +CXXFLAGS = $(CXXFLAGS) /FI winapifamily.h +!ELSEIF "$(PLATFORM)" == "ARM" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "ARM64" || "$(PLATFORM)" == "arm64" +CXXFLAGS = $(CXXFLAGS) /FI winapifamily.h +!ENDIF + +# Check for empty Platform and Processor +!IF "$(PLATFORM)" == "" +!IF "$(PROCESSOR_ARCHITECTURE)" == "x86" +PLATFORM = x86 +!ELSEIF "$(PROCESSOR_ARCHITECTURE)" == "x64" || "$(PROCESSOR_ARCHITECTURE)" == "AMD64" +PLATFORM = x64 +!ELSE +!ERROR "Unknown platform" +!ENDIF +!ENDIF + +!MESSAGE +!MESSAGE ****************************** +!MESSAGE Platform is $(PLATFORM) +!MESSAGE ****************************** +!MESSAGE + +!IF "$(PLATFORM)" == "x86" || "$(PLATFORM)" == "X86" +# CXXFLAGS = $(CXXFLAGS) /arch:SSE2 +# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP +# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP +AS = ml.exe +ASFLAGS = /nologo /D_M_X86 /W3 /Cx /Zi /safeseh +LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm rdseed.asm +LIB_OBJS = $(LIB_OBJS) rdrand-x86.obj rdseed-x86.obj +LDFLAGS = $(LDFLAGS) /MACHINE:X86 +LDLIBS = $(LDLIBS) kernel32.lib +RDRAND_OBJ = rdrand-x86.obj +RDSEED_OBJ = rdseed-x86.obj +!ENDIF + +# May need $(VCINSTALLDIR)\bin\amd64\ml64.exe +!IF "$(PLATFORM)" == "x64" || "$(PLATFORM)" == "X64" || "$(PLATFORM)" == "amd64" +# CXXFLAGS = $(CXXFLAGS) /arch:AVX2 +# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP +# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP +AS = ml64.exe +ASFLAGS = /nologo /D_M_X64 /W3 /Cx /Zi +LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm rdseed.asm +LIB_OBJS = $(LIB_OBJS) rdrand-x64.obj rdseed-x64.obj x64masm.obj x64dll.obj +LDFLAGS = $(LDFLAGS) /MACHINE:X64 +LDLIBS = $(LDLIBS) kernel32.lib +RDRAND_OBJ = rdrand-x64.obj +RDSEED_OBJ = rdseed-x64.obj +!ENDIF + +!IF "$(PLATFORM)" == "ARM" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "ARM64" || "$(PLATFORM)" == "arm64" +# CXXFLAGS = $(CXXFLAGS) /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP +CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP +LIB_SRCS = $(LIB_SRCS) neon_simd.cpp +LIB_OBJS = $(LIB_OBJS) neon_simd.obj +# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP +# LDLIBS = $(LDLIBS) +!ENDIF + +all: cryptest.exe + +# For testing cryptopp.dll and CRYPTOPP_IMPORTS +#cryptest.exe: pch.pch cryptopp.lib $(TEST_OBJS) +# $(LD) $(LDFLAGS) $(TEST_OBJS) cryptopp.lib $(LDLIBS) /out:$@ + +cryptest.exe: pch.pch cryptlib.lib $(TEST_OBJS) + $(LD) $(LDFLAGS) $(TEST_OBJS) cryptlib.lib $(LDLIBS) /out:$@ + +cryptlib.lib: $(LIB_OBJS) + $(AR) $(ARFLAGS) $(LIB_OBJS) /out:$@ + +cryptopp.dump: cryptlib.lib + dumpbin.exe /LINKERMEMBER cryptlib.lib /OUT:$@ + +cryptopp.map: $(LIB_OBJS) + $(LD) $(LDFLAGS) /DLL /MAP /MAPINFO:EXPORTS $(LIB_OBJS) + mv cryptlib.map cryptopp.map + +cryptopp.def: cryptopp.dump + dump2def.exe cryptopp.dump cryptopp.def + +# LD produces 3 output artifacts for cryptopp.dll +cryptopp.dll cryptopp.lib cryptopp.exp: $(LIB_OBJS) cryptopp.def + $(LD) $(LDFLAGS) /DLL /DEF:cryptopp.def /IGNORE:4102 $(LIB_OBJS) $(LDLIBS) /out:cryptopp.dll + +clean :: + $(RM) /F /Q cryptest.exe cryptest.lib cryptest.exp pch.pch 2>nul +clean :: + $(RM) /F /Q cryptlib.lib cryptlib.exp cryptlib.dll 2>nul +clean :: + $(RM) /F /Q cryptopp.dll cryptopp.lib cryptopp.exp cryptopp.def 2>nul +clean :: + $(RM) /F /Q pch.obj $(LIB_OBJS) $(ASM_OBJS) $(TEST_OBJS) *.pdb 2>nul + +distclean :: clean +!IF EXIST ("$(USERNAME).sdf") + attrib -r -a -s -h "$(USERNAME).sdf" 2>nul + $(RM) /F /Q "$(USERNAME).sdf" 2>nul +!ENDIF +!IF EXIST ("$(USERNAME).suo") + attrib -r -a -s -h $(USERNAME).suo" 2>nul + $(RM) /F /Q $(USERNAME).suo" 2>nul +!ENDIF +!IF EXIST (Win32\) + $(RMDIR) Win32\ /q /s 2>nul +!ENDIF +!IF EXIST (x64\) + $(RMDIR) x64\ /q /s 2>nul +!ENDIF +!IF EXIST (ipch\) + $(RMDIR) ipch\ /q /s 2>nul +!ENDIF + +# Precompiled header +pch.pch: pch.h pch.cpp + $(CXX) $(CXXFLAGS) /Yc"pch.h" /Fp"pch.pch" /c pch.cpp + +# No precompiled headers +iterhash.obj: iterhash.h iterhash.cpp + $(CXX) $(CXXFLAGS) /Y- /c iterhash.cpp +dll.obj: dll.h dll.cpp + $(CXX) $(CXXFLAGS) /Y- /c dll.cpp +rdrand.obj: rdrand.h rdrand.cpp + $(CXX) $(CXXFLAGS) /c rdrand.cpp + +# Built for x86/x64 +rdrand-x86.obj: rdrand.asm + $(AS) $(ASFLAGS) /Fo rdrand-x86.obj /c rdrand.asm +rdrand-x64.obj: rdrand.asm + $(AS) $(ASFLAGS) /Fo rdrand-x64.obj /c rdrand.asm +rdseed-x86.obj: rdseed.asm + $(AS) $(ASFLAGS) /Fo rdseed-x86.obj /c rdseed.asm +rdseed-x64.obj: rdseed.asm + $(AS) $(ASFLAGS) /Fo rdseed-x64.obj /c rdseed.asm +x64masm.obj: x64masm.asm + $(AS) $(ASFLAGS) /Fo x64masm.obj /c x64masm.asm +x64dll.obj: x64dll.asm + $(AS) $(ASFLAGS) /Fo x64dll.obj /c x64dll.asm + +# For testing cryptopp.dll and CRYPTOPP_IMPORTS +#CXXFLAGS_IMPORTS = /wd4275 /wd4251 /DCRYPTOPP_IMPORTS +#test.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#datatest.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#fipstest.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#bench1.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#bench2.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#bench3.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#regtest1.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#regtest2.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#regtest3.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#regtest4.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat1.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat2.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat3.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat4.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat5.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat6.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat7.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat8.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat9.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? +#validat10.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $? + +# For testing cryptopp.dll and CRYPTOPP_EXPORTS +#CXXFLAGS_EXPORTS = /wd4275 /wd4251 /DCXXFLAGS_EXPORTS +#.cpp.obj: +# $(CXX) $(CXXFLAGS) $(CXXFLAGS_EXPORTS) /c $< + +.cpp.obj: + $(CXX) $(CXXFLAGS) /c $< + +.asm.obj: + $(AS) $(ASFLAGS) /c $< diff --git a/external/ours/library/crypto/src/shared/original/cryptlib.cpp b/external/ours/library/crypto/src/shared/original/cryptlib.cpp index 174cea86d..80f452695 100755 --- a/external/ours/library/crypto/src/shared/original/cryptlib.cpp +++ b/external/ours/library/crypto/src/shared/original/cryptlib.cpp @@ -1,488 +1,1054 @@ -// cryptlib.cpp - written and placed in the public domain by Wei Dai - -#include "FirstCrypto.h" -#include "cryptlib.h" -#include "misc.h" -#include "filters.h" - -#include - -NAMESPACE_BEGIN(CryptoPP) - -const std::string BufferedTransformation::NULL_CHANNEL; - -unsigned int RandomNumberGenerator::GenerateBit() -{ - return Parity(GetByte()); -} - -void RandomNumberGenerator::GenerateBlock(byte *output, unsigned int size) -{ - while (size--) - *output++ = GetByte(); -} - -word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max) -{ - word32 range = max-min; - const int maxBytes = BytePrecision(range); - const int maxBits = BitPrecision(range); - - word32 value; - - do - { - value = 0; - for (int i=0; i range); - - return value+min; -} - -void StreamCipher::ProcessString(byte *outString, const byte *inString, unsigned int length) -{ - while(length--) - *outString++ = ProcessByte(*inString++); -} - -void StreamCipher::ProcessString(byte *inoutString, unsigned int length) -{ - while(length--) { - (*inoutString)++; - *inoutString = ProcessByte(*inoutString); - } -} - -bool HashModule::Verify(const byte *digestIn) -{ - SecByteBlock digest(DigestSize()); - Final(digest); - return memcmp(digest, digestIn, DigestSize()) == 0; -} - -BufferedTransformation::Err::Err(ErrorType errorType, const std::string &s) - : Exception(s), m_errorType(errorType) -{ - if (GetWhat().empty()) - { - switch (errorType) - { - case CANNOT_FLUSH: - SetWhat("BufferedTransformation: cannot flush buffer"); - break; - case DATA_INTEGRITY_CHECK_FAILED: - SetWhat("BufferedTransformation: data integrity check failed"); - break; - case INVALID_DATA_FORMAT: - SetWhat("BufferedTransformation: invalid data format"); - break; - case OUTPUT_ERROR: - SetWhat("BufferedTransformation: cannot write to output device"); - break; - case OTHER_ERROR: - SetWhat("BufferedTransformation: unknown error"); - break; - default: - assert(false); - break; - } - } -} - -void BufferedTransformation::Put(byte b) -{ - if (AttachedTransformation()) - AttachedTransformation()->Put(b); -} - -void BufferedTransformation::Put(const byte *inString, unsigned int length) -{ - if (AttachedTransformation()) - AttachedTransformation()->Put(inString, length); -} - -void BufferedTransformation::Flush(bool completeFlush, int propagation) -{ - if (AttachedTransformation() && propagation) - AttachedTransformation()->Flush(completeFlush, propagation-1); -} - -void BufferedTransformation::MessageEnd(int propagation) -{ - if (AttachedTransformation() && propagation) - AttachedTransformation()->MessageEnd(propagation-1); -} - -void BufferedTransformation::MessageSeriesEnd(int propagation) -{ - if (AttachedTransformation() && propagation) - AttachedTransformation()->MessageSeriesEnd(propagation-1); -} - -void BufferedTransformation::PutMessageEnd(const byte *inString, unsigned int length, int propagation) -{ - Put(inString, length); - MessageEnd(propagation); -} - -void BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation) -{ - if (channel.empty()) - Flush(completeFlush, propagation); - else if (AttachedTransformation() && propagation) - AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation-1); -} - -void BufferedTransformation::ChannelMessageEnd(const std::string &channel, int propagation) -{ - if (channel.empty()) - MessageEnd(propagation); - else if (AttachedTransformation() && propagation) - AttachedTransformation()->ChannelMessageEnd(channel, propagation-1); -} - -void BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation) -{ - if (channel.empty()) - MessageSeriesEnd(propagation); - else if (AttachedTransformation() && propagation) - AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1); -} - -void BufferedTransformation::ChannelPutMessageEnd(const std::string &channel, const byte *inString, unsigned int length, int propagation) -{ - if (channel.empty()) - PutMessageEnd(inString, length, propagation); - else - { - ChannelPut(channel, inString, length); - ChannelMessageEnd(channel, propagation); - } -} - -unsigned long BufferedTransformation::MaxRetrievable() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->MaxRetrievable(); - else - return CopyTo(g_bitBucket); -} - -bool BufferedTransformation::AnyRetrievable() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->AnyRetrievable(); - else - { - byte b; - return Peek(b) != 0; - } -} - -unsigned int BufferedTransformation::Get(byte &outByte) -{ - if (AttachedTransformation()) - return AttachedTransformation()->Get(outByte); - else - return Get(&outByte, 1); -} - -unsigned int BufferedTransformation::Get(byte *outString, unsigned int getMax) -{ - if (AttachedTransformation()) - return AttachedTransformation()->Get(outString, getMax); - else - { - ArraySink arraySink(outString, getMax); - return TransferTo(arraySink, getMax); - } -} - -unsigned int BufferedTransformation::Peek(byte &outByte) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->Peek(outByte); - else - return Peek(&outByte, 1); -} - -unsigned int BufferedTransformation::Peek(byte *outString, unsigned int peekMax) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->Peek(outString, peekMax); - else - { - ArraySink arraySink(outString, peekMax); - return CopyTo(arraySink, peekMax); - } -} - -unsigned long BufferedTransformation::Skip(unsigned long skipMax) -{ - if (AttachedTransformation()) - return AttachedTransformation()->Skip(skipMax); - else - return TransferTo(g_bitBucket, skipMax); -} - -unsigned long BufferedTransformation::CopyTo(BufferedTransformation &target, unsigned long copyMax) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->CopyTo(target, copyMax); - else - return 0; -} - -unsigned long BufferedTransformation::TransferTo(BufferedTransformation &target, unsigned long size) -{ - if (AttachedTransformation()) - return AttachedTransformation()->TransferTo(target, size); - else - return 0; -} - -unsigned long BufferedTransformation::TotalBytesRetrievable() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->TotalBytesRetrievable(); - else - return MaxRetrievable(); -} - -unsigned int BufferedTransformation::NumberOfMessages() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->NumberOfMessages(); - else - return CopyMessagesTo(g_bitBucket); -} - -bool BufferedTransformation::AnyMessages() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->NumberOfMessages(); - else - return NumberOfMessages() != 0; -} - -bool BufferedTransformation::GetNextMessage() -{ - if (AttachedTransformation()) - return AttachedTransformation()->GetNextMessage(); - else - return false; -} - -unsigned int BufferedTransformation::SkipMessages(unsigned int count) -{ - if (AttachedTransformation()) - return AttachedTransformation()->SkipMessages(count); - else - return TransferMessagesTo(g_bitBucket, count); -} - -unsigned int BufferedTransformation::TransferMessagesTo(BufferedTransformation &target, unsigned int count) -{ - if (AttachedTransformation()) - return AttachedTransformation()->TransferMessagesTo(target, count); - else - { - unsigned int i; - for (i=0; i (result); - target.MessageEnd(GetAutoSignalPropagation()); - } - return i; - } -} - -unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->CopyMessagesTo(target, count); - else - return 0; -} - -void BufferedTransformation::SkipAll() -{ - if (AttachedTransformation()) - AttachedTransformation()->SkipAll(); - else - { - while (SkipMessages()) {} - while (Skip()) {} - } -} - -void BufferedTransformation::TransferAllTo(BufferedTransformation &target) -{ - if (AttachedTransformation()) - AttachedTransformation()->TransferAllTo(target); - else - { - while (TransferMessagesTo(target)) {} - while (TransferTo(target)) {} - } -} - -void BufferedTransformation::CopyAllTo(BufferedTransformation &target) const -{ - if (AttachedTransformation()) - AttachedTransformation()->CopyAllTo(target); - else - { - CopyMessagesTo(target); - CopyTo(target); - } -} - -void BufferedTransformation::SetRetrievalChannel(const std::string &channel) -{ - if (AttachedTransformation()) - AttachedTransformation()->SetRetrievalChannel(channel); -} - -void BufferedTransformation::ChannelPut(const std::string &channel, byte inByte) -{ - if (channel.empty()) - Put(inByte); -} - -void BufferedTransformation::ChannelPut(const std::string &channel, const byte *inString, unsigned int length) -{ - if (channel.empty()) - Put(inString, length); -} - -void BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, bool highFirst) -{ - if (highFirst) - { - ChannelPut(channel, value>>8); - ChannelPut(channel, byte(value)); - } - else - { - ChannelPut(channel, byte(value)); - ChannelPut(channel, value>>8); - } -} - -void BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, bool highFirst) -{ - if (highFirst) - { - for (int i=0; i<4; i++) - ChannelPut(channel, byte(value>>((3-i)*8))); - } - else - { - for (int i=0; i<4; i++) - ChannelPut(channel, byte(value>>(i*8))); - } -} - -void BufferedTransformation::PutWord16(word16 value, bool highFirst) -{ - ChannelPutWord16(NULL_CHANNEL, value, highFirst); -} - -void BufferedTransformation::PutWord32(word32 value, bool highFirst) -{ - ChannelPutWord32(NULL_CHANNEL, value, highFirst); -} - -unsigned int BufferedTransformation::PeekWord16(word16 &value, bool highFirst) -{ - byte buf[2] = {0, 0}; - unsigned int len = Peek(buf, 2); - - if (highFirst) - value = (buf[0] << 8) | buf[1]; - else - value = (buf[1] << 8) | buf[0]; - - return len; -} - -unsigned int BufferedTransformation::PeekWord32(word32 &value, bool highFirst) -{ - byte buf[4] = {0, 0, 0, 0}; - unsigned int len = Peek(buf, 4); - - if (highFirst) - value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3]; - else - value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0]; - - return len; -} - -unsigned int BufferedTransformation::GetWord16(word16 &value, bool highFirst) -{ - return Skip(PeekWord16(value, highFirst)); -} - -unsigned int BufferedTransformation::GetWord32(word32 &value, bool highFirst) -{ - return Skip(PeekWord32(value, highFirst)); -} - -void BufferedTransformation::Attach(BufferedTransformation *newOut) -{ - if (!Attachable()) - return; - - if (AttachedTransformation() && AttachedTransformation()->Attachable()) - AttachedTransformation()->Attach(newOut); - else - Detach(newOut); -} - -unsigned int PK_FixedLengthCryptoSystem::MaxPlainTextLength(unsigned int cipherTextLength) const -{ - if (cipherTextLength == CipherTextLength()) - return MaxPlainTextLength(); - else - return 0; -} - -unsigned int PK_FixedLengthCryptoSystem::CipherTextLength(unsigned int plainTextLength) const -{ - if (plainTextLength <= MaxPlainTextLength()) - return CipherTextLength(); - else - return 0; -} - -unsigned int PK_FixedLengthDecryptor::Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText) -{ - if (cipherTextLength != CipherTextLength()) - return 0; - - return Decrypt(cipherText, plainText); -} - -void PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) const -{ - std::unique_ptr accumulator(NewMessageAccumulator()); - accumulator->Update(message, messageLen); - Sign(rng, accumulator.release(), signature); -} - -bool PK_Verifier::VerifyMessage(const byte *message, unsigned int messageLen, const byte *sig) const -{ - std::unique_ptr accumulator(NewMessageAccumulator()); - accumulator->Update(message, messageLen); - return Verify(accumulator.release(), sig); -} - -NAMESPACE_END +// cryptlib.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4127 4189 4459) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wunused-value" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#ifndef CRYPTOPP_IMPORTS + +#include "cryptlib.h" +#include "filters.h" +#include "algparam.h" +#include "fips140.h" +#include "argnames.h" +#include "fltrimpl.h" +#include "osrng.h" +#include "secblock.h" +#include "smartptr.h" +#include "stdcpp.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1); +CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2); +CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4); +CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8); +#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE +CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word)); +#endif + +BufferedTransformation & TheBitBucket() +{ + static BitBucket bitBucket; + return bitBucket; +} + +Algorithm::Algorithm(bool checkSelfTestStatus) +{ + if (checkSelfTestStatus && FIPS_140_2_ComplianceEnabled()) + { + if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_NOT_DONE && !PowerUpSelfTestInProgressOnThisThread()) + throw SelfTestFailure("Cryptographic algorithms are disabled before the power-up self tests are performed."); + + if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_FAILED) + throw SelfTestFailure("Cryptographic algorithms are disabled after a power-up self test failed."); + } +} + +void SimpleKeyingInterface::SetKey(const byte *key, size_t length, const NameValuePairs ¶ms) +{ + this->ThrowIfInvalidKeyLength(length); + this->UncheckedSetKey(key, static_cast(length), params); +} + +void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int rounds) +{ + SetKey(key, length, MakeParameters(Name::Rounds(), rounds)); +} + +void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength) +{ + SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, ivLength))); +} + +void SimpleKeyingInterface::ThrowIfInvalidKeyLength(size_t length) +{ + if (!IsValidKeyLength(length)) + throw InvalidKeyLength(GetAlgorithm().AlgorithmName(), length); +} + +void SimpleKeyingInterface::ThrowIfResynchronizable() +{ + if (IsResynchronizable()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object requires an IV"); +} + +void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv) +{ + if (!iv && IVRequirement() == UNPREDICTABLE_RANDOM_IV) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object cannot use a null IV"); +} + +size_t SimpleKeyingInterface::ThrowIfInvalidIVLength(int length) +{ + size_t size = 0; + if (length < 0) + size = static_cast(IVSize()); + else if ((size_t)length < MinIVLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(length) + " is less than the minimum of " + IntToString(MinIVLength())); + else if ((size_t)length > MaxIVLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(length) + " exceeds the maximum of " + IntToString(MaxIVLength())); + else + size = static_cast(length); + + return size; +} + +const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size) +{ + ConstByteArrayParameter ivWithLength; + const byte *iv = NULLPTR; + bool found = false; + + try {found = params.GetValue(Name::IV(), ivWithLength);} + catch (const NameValuePairs::ValueTypeMismatch &) {} + + if (found) + { + iv = ivWithLength.begin(); + ThrowIfInvalidIV(iv); + size = ThrowIfInvalidIVLength(static_cast(ivWithLength.size())); + } + else if (params.GetValue(Name::IV(), iv)) + { + ThrowIfInvalidIV(iv); + size = static_cast(IVSize()); + } + else + { + ThrowIfResynchronizable(); + size = 0; + } + + return iv; +} + +void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *iv) +{ + rng.GenerateBlock(iv, IVSize()); +} + +size_t BlockTransformation::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const +{ + CRYPTOPP_ASSERT(inBlocks); + CRYPTOPP_ASSERT(outBlocks); + CRYPTOPP_ASSERT(length); + + const unsigned int blockSize = BlockSize(); + size_t inIncrement = (flags & (BT_InBlockIsCounter|BT_DontIncrementInOutPointers)) ? 0 : blockSize; + size_t xorIncrement = xorBlocks ? blockSize : 0; + size_t outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : blockSize; + + 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; + } + + // Coverity finding. + const bool xorFlag = xorBlocks && (flags & BT_XorInput); + while (length >= blockSize) + { + if (xorFlag) + { + // xorBlocks non-NULL and with BT_XorInput. + xorbuf(outBlocks, xorBlocks, inBlocks, blockSize); + ProcessBlock(outBlocks); + } + else + { + // xorBlocks may be non-NULL and without BT_XorInput. + ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks); + } + + if (flags & BT_InBlockIsCounter) + const_cast(inBlocks)[blockSize-1]++; + + inBlocks = PtrAdd(inBlocks, inIncrement); + outBlocks = PtrAdd(outBlocks, outIncrement); + xorBlocks = PtrAdd(xorBlocks, xorIncrement); + length -= blockSize; + } + + return length; +} + +unsigned int BlockTransformation::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +unsigned int StreamTransformation::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +unsigned int HashTransformation::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +#if 0 +void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length) +{ + CRYPTOPP_ASSERT(MinLastBlockSize() == 0); // this function should be overridden otherwise + + if (length == MandatoryBlockSize()) + ProcessData(outString, inString, length); + else if (length != 0) + throw NotImplemented(AlgorithmName() + ": this object doesn't support a special last block"); +} +#endif + +size_t StreamTransformation::ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength) +{ + // this function should be overridden otherwise + CRYPTOPP_ASSERT(MinLastBlockSize() == 0); + + if (inLength == MandatoryBlockSize()) + { + outLength = inLength; // squash unused warning + ProcessData(outString, inString, inLength); + } + else if (inLength != 0) + throw NotImplemented(AlgorithmName() + ": this object doesn't support a special last block"); + + return outLength; +} + +void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) +{ + if (headerLength > MaxHeaderLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": header length " + IntToString(headerLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength())); + + if (messageLength > MaxMessageLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": message length " + IntToString(messageLength) + " exceeds the maximum of " + IntToString(MaxMessageLength())); + + if (footerLength > MaxFooterLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": footer length " + IntToString(footerLength) + " exceeds the maximum of " + IntToString(MaxFooterLength())); + + UncheckedSpecifyDataLengths(headerLength, messageLength, footerLength); +} + +void AuthenticatedSymmetricCipher::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) +{ + Resynchronize(iv, ivLength); + SpecifyDataLengths(headerLength, messageLength); + Update(header, headerLength); + ProcessString(ciphertext, message, messageLength); + TruncatedFinal(mac, macSize); +} + +bool AuthenticatedSymmetricCipher::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength) +{ + Resynchronize(iv, ivLength); + SpecifyDataLengths(headerLength, ciphertextLength); + Update(header, headerLength); + ProcessString(message, ciphertext, ciphertextLength); + return TruncatedVerify(mac, macLength); +} + +std::string AuthenticatedSymmetricCipher::AlgorithmName() const +{ + // Squash C4505 on Visual Studio 2008 and friends + return "Unknown"; +} + +unsigned int RandomNumberGenerator::GenerateBit() +{ + return GenerateByte() & 1; +} + +byte RandomNumberGenerator::GenerateByte() +{ + byte b; + GenerateBlock(&b, 1); + return b; +} + +word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max) +{ + const word32 range = max-min; + const unsigned int maxBits = BitPrecision(range); + + word32 value; + + do + { + GenerateBlock((byte *)&value, sizeof(value)); + value = Crop(value, maxBits); + } while (value > range); + + return value+min; +} + +// Stack recursion below... GenerateIntoBufferedTransformation calls GenerateBlock, +// and GenerateBlock calls GenerateIntoBufferedTransformation. Ad infinitum. Also +// see http://github.com/weidai11/cryptopp/issues/38. +// +// According to Wei, RandomNumberGenerator is an interface, and it should not +// be instantiable. Its now spilt milk, and we are going to CRYPTOPP_ASSERT it in Debug +// builds to alert the programmer and throw in Release builds. Developers have +// a reference implementation in case its needed. If a programmer +// unintentionally lands here, then they should ensure use of a +// RandomNumberGenerator pointer or reference so polymorphism can provide the +// proper runtime dispatching. + +void RandomNumberGenerator::GenerateBlock(byte *output, size_t size) +{ + CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size); + + ArraySink s(output, size); + GenerateIntoBufferedTransformation(s, DEFAULT_CHANNEL, size); +} + +void RandomNumberGenerator::DiscardBytes(size_t n) +{ + GenerateIntoBufferedTransformation(TheBitBucket(), DEFAULT_CHANNEL, n); +} + +void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) +{ + FixedSizeSecBlock buffer; + while (length) + { + size_t len = UnsignedMin(buffer.size(), length); + GenerateBlock(buffer, len); + (void)target.ChannelPut(channel, buffer, len); + length -= len; + } +} + +size_t KeyDerivationFunction::MinDerivedKeyLength() const +{ + return 0; +} + +size_t KeyDerivationFunction::MaxDerivedKeyLength() const +{ + return static_cast(-1); +} + +void KeyDerivationFunction::ThrowIfInvalidDerivedKeyLength(size_t length) const +{ + if (!IsValidDerivedLength(length)) + throw InvalidDerivedKeyLength(GetAlgorithm().AlgorithmName(), length); +} + +void KeyDerivationFunction::SetParameters(const NameValuePairs& params) { + CRYPTOPP_UNUSED(params); +} + +/// \brief Random Number Generator that does not produce random numbers +/// \details ClassNullRNG can be used for functions that require a RandomNumberGenerator +/// but don't actually use it. The class throws NotImplemented when a generation function is called. +/// \sa NullRNG() +class ClassNullRNG : public RandomNumberGenerator +{ +public: + /// \brief The name of the generator + /// \returns the string \a NullRNGs + std::string AlgorithmName() const {return "NullRNG";} + +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) + /// \brief An implementation that throws NotImplemented + byte GenerateByte () {} + /// \brief An implementation that throws NotImplemented + unsigned int GenerateBit () {} + /// \brief An implementation that throws NotImplemented + word32 GenerateWord32 (word32 min, word32 max) {} +#endif + + /// \brief An implementation that throws NotImplemented + void GenerateBlock(byte *output, size_t size) + { + CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(size); + throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes"); + } + +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) + /// \brief An implementation that throws NotImplemented + void GenerateIntoBufferedTransformation (BufferedTransformation &target, const std::string &channel, lword length) {} + /// \brief An implementation that throws NotImplemented + void IncorporateEntropy (const byte *input, size_t length) {} + /// \brief An implementation that returns \p false + bool CanIncorporateEntropy () const {} + /// \brief An implementation that does nothing + void DiscardBytes (size_t n) {} + /// \brief An implementation that does nothing + void Shuffle (IT begin, IT end) {} + +private: + Clonable* Clone () const { return NULLPTR; } +#endif +}; + +RandomNumberGenerator & NullRNG() +{ + static ClassNullRNG s_nullRNG; + return s_nullRNG; +} + +bool HashTransformation::TruncatedVerify(const byte *digest, size_t digestLength) +{ + // Allocate at least 1 for calculated to avoid triggering diagnostics + ThrowIfInvalidTruncatedSize(digestLength); + SecByteBlock calculated(digestLength ? digestLength : 1); + TruncatedFinal(calculated, digestLength); + return VerifyBufsEqual(calculated, digest, digestLength); +} + +void HashTransformation::ThrowIfInvalidTruncatedSize(size_t size) const +{ + if (size > DigestSize()) + throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes"); +} + +unsigned int BufferedTransformation::GetMaxWaitObjectCount() const +{ + const BufferedTransformation *t = AttachedTransformation(); + return t ? t->GetMaxWaitObjectCount() : 0; +} + +void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) +{ + BufferedTransformation *t = AttachedTransformation(); + if (t) + t->GetWaitObjects(container, callStack); // reduce clutter by not adding to stack here +} + +void BufferedTransformation::Initialize(const NameValuePairs ¶meters, int propagation) +{ + CRYPTOPP_UNUSED(propagation); + CRYPTOPP_ASSERT(!AttachedTransformation()); + IsolatedInitialize(parameters); +} + +bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking) +{ + CRYPTOPP_UNUSED(propagation); + CRYPTOPP_ASSERT(!AttachedTransformation()); + return IsolatedFlush(hardFlush, blocking); +} + +bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking) +{ + CRYPTOPP_UNUSED(propagation); + CRYPTOPP_ASSERT(!AttachedTransformation()); + return IsolatedMessageSeriesEnd(blocking); +} + +byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, size_t &size) +{ + byte* space = NULLPTR; + if (channel.empty()) + space = CreatePutSpace(size); + else + throw NoChannelSupport(AlgorithmName()); + return space; +} + +size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byte *inString, size_t length, int messageEnd, bool blocking) +{ + size_t size = 0; + if (channel.empty()) + size = Put2(inString, length, messageEnd, blocking); + else + throw NoChannelSupport(AlgorithmName()); + return size; +} + +size_t BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking) +{ + size_t size = 0; + if (channel.empty()) + size = PutModifiable2(inString, length, messageEnd, blocking); + else + size = ChannelPut2(channel, inString, length, messageEnd, blocking); + return size; +} + +bool BufferedTransformation::ChannelFlush(const std::string &channel, bool hardFlush, int propagation, bool blocking) +{ + bool result = 0; + if (channel.empty()) + result = Flush(hardFlush, propagation, blocking); + else + throw NoChannelSupport(AlgorithmName()); + return result; +} + +bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) +{ + bool result = false; + if (channel.empty()) + result = MessageSeriesEnd(propagation, blocking); + else + throw NoChannelSupport(AlgorithmName()); + return result; +} + +lword BufferedTransformation::MaxRetrievable() const +{ + lword size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->MaxRetrievable(); + else + size = CopyTo(TheBitBucket()); + return size; +} + +bool BufferedTransformation::AnyRetrievable() const +{ + bool result = false; + if (AttachedTransformation()) + result = AttachedTransformation()->AnyRetrievable(); + else + { + byte b; + result = Peek(b) != 0; + } + return result; +} + +size_t BufferedTransformation::Get(byte &outByte) +{ + size_t size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->Get(outByte); + else + size = Get(&outByte, 1); + return size; +} + +size_t BufferedTransformation::Get(byte *outString, size_t getMax) +{ + size_t size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->Get(outString, getMax); + else + { + ArraySink arraySink(outString, getMax); + size = (size_t)TransferTo(arraySink, getMax); + } + return size; +} + +size_t BufferedTransformation::Peek(byte &outByte) const +{ + size_t size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->Peek(outByte); + else + size = Peek(&outByte, 1); + return size; +} + +size_t BufferedTransformation::Peek(byte *outString, size_t peekMax) const +{ + size_t size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->Peek(outString, peekMax); + else + { + ArraySink arraySink(outString, peekMax); + size = (size_t)CopyTo(arraySink, peekMax); + } + return size; +} + +lword BufferedTransformation::Skip(lword skipMax) +{ + lword size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->Skip(skipMax); + else + size = TransferTo(TheBitBucket(), skipMax); + return size; +} + +lword BufferedTransformation::TotalBytesRetrievable() const +{ + lword size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->TotalBytesRetrievable(); + else + size = MaxRetrievable(); + return size; +} + +unsigned int BufferedTransformation::NumberOfMessages() const +{ + unsigned int size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->NumberOfMessages(); + else + size = CopyMessagesTo(TheBitBucket()); + return size; +} + +bool BufferedTransformation::AnyMessages() const +{ + bool result = false; + if (AttachedTransformation()) + result = AttachedTransformation()->AnyMessages(); + else + result = NumberOfMessages() != 0; + return result; +} + +bool BufferedTransformation::GetNextMessage() +{ + bool result = false; + if (AttachedTransformation()) + result = AttachedTransformation()->GetNextMessage(); + else + { + CRYPTOPP_ASSERT(!AnyMessages()); + } + return result; +} + +unsigned int BufferedTransformation::SkipMessages(unsigned int count) +{ + unsigned int size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->SkipMessages(count); + else + size = TransferMessagesTo(TheBitBucket(), count); + return size; +} + +size_t BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking) +{ + if (AttachedTransformation()) + return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking); + else + { + unsigned int maxMessages = messageCount; + for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++) + { + size_t blockedBytes; + lword transferredBytes; + + while (AnyRetrievable()) + { + // MaxRetrievable() instead of LWORD_MAX due to GH #962. If + // the target calls CreatePutSpace(), then the allocation + // size will be LWORD_MAX. That happens when target is a + // ByteQueue. Maybe ByteQueue should check the size, and if + // it is LWORD_MAX or -1, then use a default like 4096. + transferredBytes = MaxRetrievable(); + blockedBytes = TransferTo2(target, transferredBytes, channel, blocking); + if (blockedBytes > 0) + return blockedBytes; + } + + if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking)) + return 1; + + bool result = GetNextMessage(); + CRYPTOPP_UNUSED(result); CRYPTOPP_ASSERT(result); + } + return 0; + } +} + +unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const +{ + unsigned int size = 0; + if (AttachedTransformation()) + size = AttachedTransformation()->CopyMessagesTo(target, count, channel); + return size; +} + +void BufferedTransformation::SkipAll() +{ + if (AttachedTransformation()) + AttachedTransformation()->SkipAll(); + else + { + while (SkipMessages()) {} + while (Skip()) {} + } +} + +size_t BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking) +{ + if (AttachedTransformation()) + return AttachedTransformation()->TransferAllTo2(target, channel, blocking); + else + { + CRYPTOPP_ASSERT(!NumberOfMessageSeries()); + + unsigned int messageCount; + do + { + messageCount = UINT_MAX; + size_t blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking); + if (blockedBytes) + return blockedBytes; + } + while (messageCount != 0); + + lword byteCount; + do + { + byteCount = ULONG_MAX; + size_t blockedBytes = TransferTo2(target, byteCount, channel, blocking); + if (blockedBytes) + return blockedBytes; + } + while (byteCount != 0); + + return 0; + } +} + +void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const +{ + if (AttachedTransformation()) + AttachedTransformation()->CopyAllTo(target, channel); + else + { + CRYPTOPP_ASSERT(!NumberOfMessageSeries()); + while (CopyMessagesTo(target, UINT_MAX, channel)) {} + } +} + +void BufferedTransformation::SetRetrievalChannel(const std::string &channel) +{ + if (AttachedTransformation()) + AttachedTransformation()->SetRetrievalChannel(channel); +} + +size_t BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking) +{ + PutWord(false, order, m_buf, value); + return ChannelPut(channel, m_buf, 2, blocking); +} + +size_t BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking) +{ + PutWord(false, order, m_buf, value); + return ChannelPut(channel, m_buf, 4, blocking); +} + +size_t BufferedTransformation::ChannelPutWord64(const std::string &channel, word64 value, ByteOrder order, bool blocking) +{ + PutWord(false, order, m_buf, value); + return ChannelPut(channel, m_buf, 8, blocking); +} + +size_t BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking) +{ + return ChannelPutWord16(DEFAULT_CHANNEL, value, order, blocking); +} + +size_t BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking) +{ + return ChannelPutWord32(DEFAULT_CHANNEL, value, order, blocking); +} + +size_t BufferedTransformation::PutWord64(word64 value, ByteOrder order, bool blocking) +{ + return ChannelPutWord64(DEFAULT_CHANNEL, value, order, blocking); +} + +size_t BufferedTransformation::PeekWord16(word16 &value, ByteOrder order) const +{ + byte buf[2] = {0, 0}; + size_t len = Peek(buf, 2); + + if (order == BIG_ENDIAN_ORDER) + value = word16((buf[0] << 8) | buf[1]); + else + value = word16((buf[1] << 8) | buf[0]); + + return len; +} + +size_t BufferedTransformation::PeekWord32(word32 &value, ByteOrder order) const +{ + byte buf[4] = {0, 0, 0, 0}; + size_t len = Peek(buf, 4); + + if (order == BIG_ENDIAN_ORDER) + value = word32((buf[0] << 24) | (buf[1] << 16) | + (buf[2] << 8) | (buf[3] << 0)); + else + value = word32((buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | (buf[0] << 0)); + + return len; +} + +size_t BufferedTransformation::PeekWord64(word64 &value, ByteOrder order) const +{ + byte buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + size_t len = Peek(buf, 8); + + if (order == BIG_ENDIAN_ORDER) + value = ((word64)buf[0] << 56) | ((word64)buf[1] << 48) | ((word64)buf[2] << 40) | + ((word64)buf[3] << 32) | ((word64)buf[4] << 24) | ((word64)buf[5] << 16) | + ((word64)buf[6] << 8) | (word64)buf[7]; + else + value = ((word64)buf[7] << 56) | ((word64)buf[6] << 48) | ((word64)buf[5] << 40) | + ((word64)buf[4] << 32) | ((word64)buf[3] << 24) | ((word64)buf[2] << 16) | + ((word64)buf[1] << 8) | (word64)buf[0]; + + return len; +} + +size_t BufferedTransformation::GetWord16(word16 &value, ByteOrder order) +{ + return (size_t)Skip(PeekWord16(value, order)); +} + +size_t BufferedTransformation::GetWord32(word32 &value, ByteOrder order) +{ + return (size_t)Skip(PeekWord32(value, order)); +} + +size_t BufferedTransformation::GetWord64(word64 &value, ByteOrder order) +{ + return (size_t)Skip(PeekWord64(value, order)); +} + +void BufferedTransformation::Attach(BufferedTransformation *newAttachment) +{ + if (AttachedTransformation() && AttachedTransformation()->Attachable()) + AttachedTransformation()->Attach(newAttachment); + else + Detach(newAttachment); +} + +void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize) +{ + GenerateRandom(rng, MakeParameters("KeySize", (int)keySize)); +} + +class PK_DefaultEncryptionFilter : public Unflushable +{ +public: + PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters) + : m_rng(rng), m_encryptor(encryptor), m_parameters(parameters) + { + Detach(attachment); + } + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + FILTER_BEGIN; + m_plaintextQueue.Put(inString, length); + + if (messageEnd) + { + { + size_t plaintextLength; + if (!SafeConvert(m_plaintextQueue.CurrentSize(), plaintextLength)) + throw InvalidArgument("PK_DefaultEncryptionFilter: plaintext too long"); + size_t ciphertextLength = m_encryptor.CiphertextLength(plaintextLength); + + SecByteBlock plaintext(plaintextLength); + m_plaintextQueue.Get(plaintext, plaintextLength); + m_ciphertext.resize(ciphertextLength); + m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext, m_parameters); + } + + FILTER_OUTPUT(1, m_ciphertext, m_ciphertext.size(), messageEnd); + } + FILTER_END_NO_MESSAGE_END; + } + + RandomNumberGenerator &m_rng; + const PK_Encryptor &m_encryptor; + const NameValuePairs &m_parameters; + ByteQueue m_plaintextQueue; + SecByteBlock m_ciphertext; +}; + +BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const +{ + return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters); +} + +class PK_DefaultDecryptionFilter : public Unflushable +{ +public: + PK_DefaultDecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters) + : m_rng(rng), m_decryptor(decryptor), m_parameters(parameters) + { + Detach(attachment); + } + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + FILTER_BEGIN; + m_ciphertextQueue.Put(inString, length); + + if (messageEnd) + { + { + size_t ciphertextLength; + if (!SafeConvert(m_ciphertextQueue.CurrentSize(), ciphertextLength)) + throw InvalidArgument("PK_DefaultDecryptionFilter: ciphertext too long"); + size_t maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength); + + SecByteBlock ciphertext(ciphertextLength); + m_ciphertextQueue.Get(ciphertext, ciphertextLength); + m_plaintext.resize(maxPlaintextLength); + m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters); + if (!m_result.isValidCoding) + throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext"); + } + + FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd); + } + FILTER_END_NO_MESSAGE_END; + } + + RandomNumberGenerator &m_rng; + const PK_Decryptor &m_decryptor; + const NameValuePairs &m_parameters; + ByteQueue m_ciphertextQueue; + SecByteBlock m_plaintext; + DecodingResult m_result; +}; + +BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const +{ + return new PK_DefaultDecryptionFilter(rng, *this, attachment, parameters); +} + +size_t PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const +{ + member_ptr m(messageAccumulator); + return SignAndRestart(rng, *m, signature, false); +} + +size_t PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const +{ + member_ptr m(NewSignatureAccumulator(rng)); + m->Update(message, messageLen); + return SignAndRestart(rng, *m, signature, false); +} + +size_t PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, + const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const +{ + member_ptr m(NewSignatureAccumulator(rng)); + InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength); + m->Update(nonrecoverableMessage, nonrecoverableMessageLength); + return SignAndRestart(rng, *m, signature, false); +} + +bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const +{ + member_ptr m(messageAccumulator); + return VerifyAndRestart(*m); +} + +bool PK_Verifier::VerifyMessage(const byte *message, size_t messageLen, const byte *signature, size_t signatureLen) const +{ + member_ptr m(NewVerificationAccumulator()); + InputSignature(*m, signature, signatureLen); + m->Update(message, messageLen); + return VerifyAndRestart(*m); +} + +DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const +{ + member_ptr m(messageAccumulator); + return RecoverAndRestart(recoveredMessage, *m); +} + +DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage, + const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, + const byte *signature, size_t signatureLength) const +{ + member_ptr m(NewVerificationAccumulator()); + InputSignature(*m, signature, signatureLength); + m->Update(nonrecoverableMessage, nonrecoverableMessageLength); + return RecoverAndRestart(recoveredMessage, *m); +} + +void SimpleKeyAgreementDomain::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const +{ + GeneratePrivateKey(rng, privateKey); + GeneratePublicKey(rng, privateKey, publicKey); +} + +void AuthenticatedKeyAgreementDomain::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const +{ + GenerateStaticPrivateKey(rng, privateKey); + GenerateStaticPublicKey(rng, privateKey, publicKey); +} + +void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const +{ + GenerateEphemeralPrivateKey(rng, privateKey); + GenerateEphemeralPublicKey(rng, privateKey, publicKey); +} + +// Allow a distro or packager to override the build-time version +// http://github.com/weidai11/cryptopp/issues/371 +#ifndef CRYPTOPP_BUILD_VERSION +# define CRYPTOPP_BUILD_VERSION CRYPTOPP_VERSION +#endif +int LibraryVersion(CRYPTOPP_NOINLINE_DOTDOTDOT) +{ + return CRYPTOPP_BUILD_VERSION; +} + +class NullNameValuePairs : public NameValuePairs +{ +public: + NullNameValuePairs() {} // Clang complains a default ctor must be available + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + {CRYPTOPP_UNUSED(name); CRYPTOPP_UNUSED(valueType); CRYPTOPP_UNUSED(pValue); return false;} +}; + +#if HAVE_GCC_INIT_PRIORITY + const std::string DEFAULT_CHANNEL __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 25))) = ""; + const std::string AAD_CHANNEL __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 26))) = "AAD"; + const NullNameValuePairs s_nullNameValuePairs __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 27))); + const NameValuePairs& g_nullNameValuePairs = s_nullNameValuePairs; +#elif HAVE_MSC_INIT_PRIORITY + #pragma warning(disable: 4073) + #pragma init_seg(lib) + const std::string DEFAULT_CHANNEL = ""; + const std::string AAD_CHANNEL = "AAD"; + const NullNameValuePairs s_nullNameValuePairs; + const NameValuePairs& g_nullNameValuePairs = s_nullNameValuePairs; + #pragma warning(default: 4073) +#elif HAVE_XLC_INIT_PRIORITY + #pragma priority(260) + const std::string DEFAULT_CHANNEL = ""; + const std::string AAD_CHANNEL = "AAD"; + const NullNameValuePairs s_nullNameValuePairs; + const NameValuePairs& g_nullNameValuePairs = s_nullNameValuePairs; +#else + const std::string DEFAULT_CHANNEL = ""; + const std::string AAD_CHANNEL = "AAD"; + const simple_ptr s_pNullNameValuePairs(new NullNameValuePairs); + const NameValuePairs &g_nullNameValuePairs = *s_pNullNameValuePairs.m_p; +#endif + +NAMESPACE_END // CryptoPP + +#endif // CRYPTOPP_IMPORTS diff --git a/external/ours/library/crypto/src/shared/original/cryptlib.h b/external/ours/library/crypto/src/shared/original/cryptlib.h index fd2587063..6fe6b2bbc 100755 --- a/external/ours/library/crypto/src/shared/original/cryptlib.h +++ b/external/ours/library/crypto/src/shared/original/cryptlib.h @@ -1,818 +1,3379 @@ -// cryptlib.h - written and placed in the public domain by Wei Dai -/*! \file - This file contains the declarations for the abstract base - classes that provide a uniform interface to this library. -*/ - -/*! \mainpage Crypto++ Reference Manual -
-
Abstract Base Classes
- cryptlib.h -
Algebraic Structures
- Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver, - ModularArithmetic, MontgomeryRepresentation, GFP2_ONB, - GF2NP, GF256, GF2_32, EC2N, ECP -
Block Ciphers (in ECB mode)
- 3way.h, blowfish.h, cast.h, des.h, diamond.h, gost.h, - idea.h, lubyrack.h, mars.h, mdc.h, - rc2.h, rc5.h, rc6.h, rijndael.h, safer.h, serpent.h, shark.h, skipjack.h, - square.h, tea.h, twofish.h -
Block Cipher Modes
- modes.h, cbc.h -
Compression
- Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor -
Secret Sharing and Information Dispersal
- SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery -
Stream Ciphers
- ARC4, PanamaCipher, BlumBlumShub, SEAL, SapphireEncryption, WAKEEncryption -
Hash Functions
- HAVAL, MD2, MD5, PanamaHash, RIPEMD160, SHA, SHA256, SHA384, SHA512, Tiger -
Non-Cryptographic Checksums
- CRC32, Adler32 -
Message Authentication Codes
- MD5MAC, XMACC, HMAC, CBC_MAC, DMAC, PanamaMAC -
Random Number Generators
- NullRNG, LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool -
Public Key Cryptography
- blumgold.h, dh.h, dh2.h, dsa.h, eccrypto.h, luc.h, mqv.h, - nr.h, rsa.h, rabin.h, rw.h, xtrcrypt.h -
Input Source Classes
- StringSource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource -
Output Sink Classes
- StringSinkTemplate, ArraySink, FileSink, SocketSink, WindowsPipeSink -
Filter Wrappers
- StreamCipherFilter, HashFilter, HashVerifier, SignerFilter, VerifierFilter -
Binary to Text Encoders and Decoders
- HexEncoder, HexDecoder, Base64Encoder, Base64Decoder -
Wrappers for OS features
- Timer, Socket, WindowsHandle, WindowsReadPipe, WindowsWritePipe -
- -

This reference manual is very much a work in progress. Many classes are still lacking detailed descriptions. -

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

Thanks to Ryan Phillips for providing the Doxygen configuration file -and getting me started with this manual. -*/ - -#ifndef CRYPTOPP_CRYPTLIB_H -#define CRYPTOPP_CRYPTLIB_H - -#include "config.h" -#include -#include -#include - -NAMESPACE_BEGIN(CryptoPP) - -//! base class for all exceptions thrown by Crypto++ - -class Exception : public std::exception -{ -public: - explicit Exception(const std::string &s) : m_what(s) {} - virtual ~Exception() throw() {} - const char *what() const throw() {return (m_what.c_str());} - const std::string &GetWhat() const {return m_what;} - void SetWhat(const std::string &s) {m_what = s;} - -private: - std::string m_what; -}; - -//! used to specify a direction for a cipher to operate in (encrypt or decrypt) -enum CipherDir { - //! - ENCRYPTION, - //! - DECRYPTION}; - - -//! abstract base class for block ciphers - -/*! All classes derived from BlockTransformation are block ciphers - in ECB mode (for example the DESEncryption class), which are stateless. - These classes should not be used directly, but only in combination with - a mode class (see CipherMode). - - Note: BlockTransformation objects may assume that pointers to input and - output blocks are aligned on 32-bit word boundaries. -*/ -class BlockTransformation -{ -public: - //! - virtual ~BlockTransformation() {} - - //! encrypt or decrypt one block in place - /*! \pre size of inoutBlock == BlockSize() */ - virtual void ProcessBlock(byte *inoutBlock) const =0; - - //! encrypt or decrypt one block, may assume inBlock != outBlock - /*! \pre size of inBlock and outBlock == BlockSize() */ - virtual void ProcessBlock(const byte *inBlock, byte *outBlock) const =0; - - //! block size of the cipher in bytes - virtual unsigned int BlockSize() const =0; -}; - -//! provides an implementation of BlockSize() -template -class FixedBlockSize : public BlockTransformation -{ -public: - enum {BLOCKSIZE = N}; - virtual unsigned int BlockSize() const {return BLOCKSIZE;} -}; - -//! abstract base class for stream ciphers - -class StreamCipher -{ -public: - //! - virtual ~StreamCipher() {} - - //! encrypt or decrypt one byte - virtual byte ProcessByte(byte input) =0; - - //! encrypt or decrypt an array of bytes of specified length in place - virtual void ProcessString(byte *inoutString, unsigned int length); - //! encrypt or decrypt an array of bytes of specified length, may assume inString != outString - virtual void ProcessString(byte *outString, const byte *inString, unsigned int length); -}; - -//! abstract base class for random access stream ciphers - -class RandomAccessStreamCipher : public virtual StreamCipher -{ -public: - //! - virtual ~RandomAccessStreamCipher() {} - /*/ specify that the next byte to be processed is at absolute position n - in the plaintext/ciphertext stream */ - virtual void Seek(unsigned long n) =0; -}; - -//! abstract base class for random number generators - -/*! All return values are uniformly distributed over the range specified. -*/ -class RandomNumberGenerator -{ -public: - //! - virtual ~RandomNumberGenerator() {} - - //! generate new random byte and return it - virtual byte GenerateByte() =0; - - //! generate new random bit and return it - /*! Default implementation is to call GenerateByte() and return its parity. */ - virtual unsigned int GenerateBit(); - - //! generate a random 32 bit word in the range min to max, inclusive - virtual word32 GenerateWord32(word32 a=0, word32 b=0xffffffffL); - - //! generate random array of bytes - //* Default implementation is to call GenerateByte() size times. - virtual void GenerateBlock(byte *output, unsigned int size); - - //! randomly shuffle the specified array, resulting permutation is uniformly distributed - template void Shuffle(IT begin, IT end) - { - for (; begin != end; ++begin) - std::iter_swap(begin, begin + GenerateWord32(0, end-begin-1)); - } - - // for backwards compatibility, maybe be remove later - byte GetByte() {return GenerateByte();} - unsigned int GetBit() {return GenerateBit();} - word32 GetLong(word32 a=0, word32 b=0xffffffffL) {return GenerateWord32(a, b);} - word16 GetShort(word16 a=0, word16 b=0xffff) {return (word16)GenerateWord32(a, b);} - void GetBlock(byte *output, unsigned int size) {GenerateBlock(output, size);} -}; - -//! abstract base class for hash functions - -/*! HashModule 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(). -*/ -class HashModule -{ -public: - //! - virtual ~HashModule() {} - - //! process more input - virtual void Update(const byte *input, unsigned int length) =0; - - /*/ calculate hash for the current message (the concatenation of all - inputs passed in via Update()), then reinitialize the object */ - //* Precondition: size of digest == DigestSize(). - virtual void Final(byte *digest) =0; - - //! size of the hash returned by Final() - virtual unsigned int DigestSize() const =0; - - //! use this if your input is short and you don't want to call Update() and Final() seperately - virtual void CalculateDigest(byte *digest, const byte *input, int length) - {Update(input, length); Final(digest);} - - //! verify that digest is a valid digest for the current message, then reinitialize the object - /*! Default implementation is to call Final() and do a bitwise comparison - between its output and digest. */ - virtual bool Verify(const byte *digest); - - //! use this if your input is short and you don't want to call Update() and Verify() seperately - virtual bool VerifyDigest(const byte *digest, const byte *input, int length) - {Update(input, length); return Verify(digest);} -}; - -//! abstract base class for message authentication codes - -/*! The main differences between a MAC and an hash function (in terms of - programmatic interface) is that a MAC is keyed, and that calculating - a MAC for the same message twice may produce two different results so - verifying a MAC may not be simply recalculating it and doing a bitwise - comparison. -*/ -class MessageAuthenticationCode : public virtual HashModule -{ -public: - //! - virtual ~MessageAuthenticationCode() {} -}; - -//! abstract base class for buffered transformations - -/*! BufferedTransformation is a generalization of BlockTransformation, - StreamCipher, and HashModule. - - 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. - - Computation is generally done as soon as possible, but some buffering - on the input may be done for performance reasons. - \nosubgrouping -*/ -class BufferedTransformation -{ -public: - //! - virtual ~BufferedTransformation() {} - - //! \name INPUT - //@{ - //! input a byte for processing - virtual void Put(byte inByte) =0; - //! input multiple bytes - virtual void Put(const byte *inString, unsigned int length) =0; - - //! input a 16-bit word, big-endian or little-endian depending on highFirst - void PutWord16(word16 value, bool highFirst=true); - //! input a 32-bit word - void PutWord32(word32 value, bool highFirst=true); - //@} - - //! \name SIGNALS - //@{ - //! process everything in internal buffers and output them - /*! throws exception if completeFlush == true and it's - not possible to flush everything */ - virtual void Flush(bool completeFlush, int propagation=-1); - //! mark end of an input segment, message, or packet - /*! 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. */ - virtual void MessageEnd(int propagation=-1); - //! same as Put() followed by MessageEnd() but may be more efficient - virtual void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1); - //! mark end of a series of messages - /*! There should be a MessageEnd immediately before MessageSeriesEnd. */ - virtual void MessageSeriesEnd(int propagation=-1); - - //! set propagation of automatically generated and transfered signals - /*! propagation == 0 means do not automaticly generate signals */ - virtual void SetAutoSignalPropagation(int propagation) {} - - //! - virtual int GetAutoSignalPropagation() const {return 0;} - - // for backwards compatibility - void Close() {MessageEnd();} - //@} - - //! \name ERRORS - //@{ - //! error types - enum ErrorType { - //! received a Flush(true) signal but can't flush buffers - CANNOT_FLUSH, - //! data integerity check (such as CRC or MAC) failed - DATA_INTEGRITY_CHECK_FAILED, - //! received input data that doesn't conform to expected format - INVALID_DATA_FORMAT, - //! error reading from input device - INPUT_ERROR, - //! error writing to output device - OUTPUT_ERROR, - //! some error not belong to any of the above categories - OTHER_ERROR - }; - - //! exception thrown by BufferedTransformation - class Err : public Exception - { - public: - Err(ErrorType errorType, const std::string &s=""); - ErrorType GetErrorType() const {return m_errorType;} - void SetErrorType(ErrorType errorType) {m_errorType = errorType;} - private: - ErrorType m_errorType; - }; - //@} - - //! \name RETRIEVAL OF ONE MESSAGE - //@{ - //! returns number of bytes that is currently ready for retrieval - /*! All retrieval functions return the actual number of bytes - retrieved, which is the lesser of the request number and - MaxRetrievable(). */ - virtual unsigned long MaxRetrievable() const; - - // old mispelled name - unsigned long MaxRetrieveable() const {return MaxRetrievable();} - - //! returns whether any bytes are currently ready for retrieval - virtual bool AnyRetrievable() const; - - //! try to retrieve a single byte - virtual unsigned int Get(byte &outByte); - //! try to retrieve multiple bytes - virtual unsigned int Get(byte *outString, unsigned int getMax); - - //! peek at the next byte without removing it from the output buffer - virtual unsigned int Peek(byte &outByte) const; - //! peek at multiple bytes without removing them from the output buffer - virtual unsigned int Peek(byte *outString, unsigned int peekMax) const; - - //! try to retrieve a 16-bit word, big-endian or little-endian depending on highFirst - unsigned int GetWord16(word16 &value, bool highFirst=true); - //! try to retrieve a 32-bit word - unsigned int GetWord32(word32 &value, bool highFirst=true); - - //! try to peek at a 16-bit word, big-endian or little-endian depending on highFirst - unsigned int PeekWord16(word16 &value, bool highFirst=true); - //! try to peek at a 32-bit word - unsigned int PeekWord32(word32 &value, bool highFirst=true); - - //! move transferMax bytes of the buffered output to target as input - virtual unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX); - - //! discard skipMax bytes from the output buffer - virtual unsigned long Skip(unsigned long skipMax=ULONG_MAX); - - //! copy copyMax bytes of the buffered output to target as input - virtual unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const; - //@} - - //! \name RETRIEVAL OF MULTIPLE MESSAGES - //@{ - //! - virtual unsigned long TotalBytesRetrievable() const; - //! number of times MessageEnd() has been received minus messages retrieved or skipped - virtual unsigned int NumberOfMessages() const; - //! returns true if NumberOfMessages() > 0 - virtual bool AnyMessages() const; - //! start retrieving the next message - /*! - Returns false if no more messages exist or this message - is not completely retrieved. - */ - virtual bool GetNextMessage(); - //! skip count number of messages - virtual unsigned int SkipMessages(unsigned int count=UINT_MAX); - //! - virtual unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX); - //! - virtual unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX) const; - - //! - virtual void SkipAll(); - //! - virtual void TransferAllTo(BufferedTransformation &target); - //! - virtual void CopyAllTo(BufferedTransformation &target) const; - //@} - - //! \name CHANNELS - //@{ - virtual void ChannelPut(const std::string &channel, byte inByte); - virtual void ChannelPut(const std::string &channel, const byte *inString, unsigned int length); - - void ChannelPutWord16(const std::string &channel, word16 value, bool highFirst=true); - void ChannelPutWord32(const std::string &channel, word32 value, bool highFirst=true); - - virtual void ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1); - virtual void ChannelMessageEnd(const std::string &channel, int propagation=-1); - virtual void ChannelPutMessageEnd(const std::string &channel, const byte *inString, unsigned int length, int propagation=-1); - virtual void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1); - - virtual void SetRetrievalChannel(const std::string &channel); - - static const std::string NULL_CHANNEL; - //@} - - /*! \name ATTACHMENT - 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, - sents that output to the attached object as input. The entire - attachment chain is deleted when the anchor object is destructed. - */ - //@{ - //! returns whether this object allows attachment - virtual bool Attachable() {return false;} - //! returns the object immediately attached to this object or nullptr for no attachment - virtual BufferedTransformation *AttachedTransformation() {return 0;} - //! - virtual const BufferedTransformation *AttachedTransformation() const - {return const_cast(this)->AttachedTransformation();} - //! delete the current attachment chain and replace it with newAttachment - virtual void Detach(BufferedTransformation *newAttachment = 0) {} - //! add newAttachment to the end of attachment chain - virtual void Attach(BufferedTransformation *newAttachment); - //@} -}; - -//! abstract base class for public-key encryptors and decryptors - -/*! This class provides an interface common to encryptors and decryptors - for querying their plaintext and ciphertext lengths. -*/ -class PK_CryptoSystem -{ -public: - //! - virtual ~PK_CryptoSystem() {} - - //! maximum length of plaintext for a given ciphertext length - //* This function returns 0 if cipherTextLength is not valid (too long or too short). - virtual unsigned int MaxPlainTextLength(unsigned int cipherTextLength) const =0; - - //! calculate length of ciphertext given length of plaintext - //* This function returns 0 if plainTextLength is not valid (too long). - virtual unsigned int CipherTextLength(unsigned int plainTextLength) const =0; -}; - -//! abstract base class for public-key encryptors - -/*! An encryptor is also a public encryption key. It contains both the - key and the algorithm to perform the encryption. -*/ -class PK_Encryptor : public virtual PK_CryptoSystem -{ -public: - //! encrypt a byte string - /*! Preconditions: - \begin{itemize} - \item CipherTextLength(plainTextLength) != 0 (i.e., plainText isn't too long) - \item size of cipherText == CipherTextLength(plainTextLength) - \end{itemize} - */ - virtual void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText) =0; -}; - -//! abstract base class for public-key decryptors - -/*! An decryptor is also a private decryption key. It contains both the - key and the algorithm to perform the decryption. -*/ -class PK_Decryptor : public virtual PK_CryptoSystem -{ -public: - //! decrypt a byte string, and return the length of plaintext - /*! Precondition: size of plainText == MaxPlainTextLength(cipherTextLength) - bytes. - - The function returns the actual length of the plaintext, or 0 - if decryption fails. - */ - virtual unsigned int Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText) =0; -}; - -//! abstract base class for encryptors and decryptors with fixed length ciphertext - -/*! A simplified interface (as embodied in this - class and its subclasses) is provided for crypto systems (such - as RSA) whose ciphertext length depend only on the key, not on the length - of the plaintext. The maximum plaintext length also depend only on - the key. -*/ -class PK_FixedLengthCryptoSystem : public virtual PK_CryptoSystem -{ -public: - //! - virtual unsigned int MaxPlainTextLength() const =0; - //! - virtual unsigned int CipherTextLength() const =0; - - unsigned int MaxPlainTextLength(unsigned int cipherTextLength) const; - unsigned int CipherTextLength(unsigned int plainTextLength) const; -}; - -//! abstract base class for encryptors with fixed length ciphertext - -class PK_FixedLengthEncryptor : public virtual PK_Encryptor, public virtual PK_FixedLengthCryptoSystem -{ -}; - -//! abstract base class for decryptors with fixed length ciphertext - -class PK_FixedLengthDecryptor : public virtual PK_Decryptor, public virtual PK_FixedLengthCryptoSystem -{ -public: - //! decrypt a byte string, and return the length of plaintext - /*! Preconditions: - \begin{itemize} - \item length of cipherText == CipherTextLength() - \item size of plainText == MaxPlainTextLength() - \end{itemize} - - The function returns the actual length of the plaintext, or 0 - if decryption fails. - */ - virtual unsigned int Decrypt(const byte *cipherText, byte *plainText) =0; - - unsigned int Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText); -}; - -//! abstract base class for public-key signers and verifiers - -/*! This class provides an interface common to signers and verifiers - for querying their signature lengths and creating message - accumulators. -*/ -class PK_SignatureSystem -{ -public: - //! - virtual ~PK_SignatureSystem() {}; - - //! signature length support by this object (as either input or output) - virtual unsigned int SignatureLength() const =0; - - //! create a new HashModule to accumulate the message to be signed or verified - virtual HashModule * NewMessageAccumulator() const =0; -}; - -//! abstract base class for public-key signers - -/*! A signer is also a private signature key. It contains both the - key and the algorithm to perform the signature. -*/ -class PK_Signer : public virtual PK_SignatureSystem -{ -public: - //! key too short exception, may be thrown by Sign() or SignMessage() - class KeyTooShort : public Exception - { - public: - KeyTooShort() : Exception("PK_Signer: key too short") {} - }; - - //! sign and delete messageAccumulator - /*! Preconditions: - \begin{itemize} - \item messageAccumulator was obtained by calling NewMessageAccumulator() - \item HashModule::Final() has not been called on messageAccumulator - \item size of signature == SignatureLength() - \end{itemize} - */ - virtual void Sign(RandomNumberGenerator &rng, HashModule *messageAccumulator, byte *signature) const =0; - - //! sign a message - /*! Precondition: size of signature == SignatureLength() */ - virtual void SignMessage(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) const; -}; - -//! abstract base class for public-key verifiers - -/*! A verifier is also a public verification key. It contains both the - key and the algorithm to perform the verification. -*/ -class PK_Verifier : public virtual PK_SignatureSystem -{ -public: - //! check whether sig is a valid signature for messageAccumulator, and delete messageAccumulator - /*! Preconditions: - \begin{itemize} - \item messageAccumulator was obtained by calling NewMessageAccumulator() - \item HashModule::Final() has not been called on messageAccumulator - \item length of signature == SignatureLength() - \end{itemize} - */ - virtual bool Verify(HashModule *messageAccumulator, const byte *sig) const =0; - - //! check whether sig is a valid signature for message - /*! Precondition: size of signature == SignatureLength() */ - virtual bool VerifyMessage(const byte *message, unsigned int messageLen, const byte *sig) const; -}; - -//! abstract base class for public-key signers and verifiers with recovery - -/*! In a signature scheme with recovery, a verifier is able to extract - a message from its valid signature. -*/ -class PK_SignatureSystemWithRecovery : public virtual PK_SignatureSystem -{ -public: - //! length of longest message that can be fully recovered - virtual unsigned int MaximumRecoverableLength() const =0; - - //! whether or not messages longer than MaximumRecoverableLength() can be signed - /*! If this function returns false, any message longer than - MaximumRecoverableLength() will be truncated for signature - and will fail verification. - */ - virtual bool AllowLeftoverMessage() const =0; -}; - -//! abstract base class for public-key signers with recovery - -class PK_SignerWithRecovery : public virtual PK_SignatureSystemWithRecovery, public PK_Signer -{ -}; - -//! abstract base class for public-key verifiers with recovery - -/*! A PK_VerifierWithRecovery can also be used the same way as a PK_Verifier, - where the signature and the entire message is given to Verify() or - VerifyMessage() as input. -*/ -class PK_VerifierWithRecovery : public virtual PK_SignatureSystemWithRecovery, public PK_Verifier -{ -public: - //! create a new HashModule to accumulate leftover message - virtual HashModule * NewLeftoverMessageAccumulator(const byte *signature) const =0; - - //! partially recover a message from its signature, return length of recoverd message, or 0 if signature is invalid - /*! Preconditions: - \begin{itemize} - \item leftoverMessageAccumulator was obtained by calling NewLeftoverMessageAccumulator(signature) - \item HashModule::Final() has not been called on leftoverMessageAccumulator - \item length of signature == SignatureLength() - \item size of recoveredMessage == MaximumRecoverableLength() - \end{itemize} - */ - virtual unsigned int PartialRecover(HashModule *leftoverMessageAccumulator, byte *recoveredMessage) const =0; - - //! recover a message from its signature, return length of message, or 0 if signature is invalid - /*! This function should be equivalent to PartialRecover(NewLeftoverMessageAccumulator(signature), recoveredMessage). - Preconditions: - \begin{itemize} - \item length of signature == SignatureLength() - \item size of recoveredMessage == MaximumRecoverableLength() - \end{itemize} - */ - virtual unsigned int Recover(const byte *signature, byte *recoveredMessage) const =0; -}; - -//! abstract base class for domains of simple key agreement protocols - -/*! 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. -*/ -class PK_SimpleKeyAgreementDomain -{ -public: - virtual ~PK_SimpleKeyAgreementDomain() {} - - //! return whether the domain parameters stored in this object are valid - virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const =0; - //! return length of agreed value produced - virtual unsigned int AgreedValueLength() const =0; - //! return length of private keys in this domain - virtual unsigned int PrivateKeyLength() const =0; - //! return length of public keys in this domain - virtual unsigned int PublicKeyLength() const =0; - //! generate private/public key pair - /*! Preconditions: - \begin{itemize} - \item size of privateKey == PrivateKeyLength() - \item size of publicKey == PublicKeyLength() - \end{itemize} - */ - virtual void GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const =0; - /*! derive agreed value from your private key and couterparty's public key, return false in case of failure - //! Note: If you have previously validated the public key, use validateOtherPublicKey=false to save time. - //! Preconditions: - \begin{itemize} - \item size of agreedValue == AgreedValueLength() - \item length of privateKey == PrivateKeyLength() - \item length of otherPublicKey == PublicKeyLength() - \end{itemize} - */ - virtual bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const =0; -}; - -//! abstract base class for domains of authenticated key agreement protocols - -/*! 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. -*/ -class PK_AuthenticatedKeyAgreementDomain -{ -public: - virtual ~PK_AuthenticatedKeyAgreementDomain() {} - - //! return whether the domain parameters stored in this object are valid - virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const =0; - //! return length of agreed value produced - virtual unsigned int AgreedValueLength() const =0; - - //! return length of static private keys in this domain - virtual unsigned int StaticPrivateKeyLength() const =0; - //! return length of static public keys in this domain - virtual unsigned int StaticPublicKeyLength() const =0; - //! generate static private/public key pair - /*! Preconditions: - \begin{itemize} - \item size of privateKey == StaticPrivateKeyLength() - \item size of publicKey == StaticPublicKeyLength() - \end{itemize} - */ - virtual void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const =0; - - //! return length of ephemeral private keys in this domain - virtual unsigned int EphemeralPrivateKeyLength() const =0; - //! return length of ephemeral public keys in this domain - virtual unsigned int EphemeralPublicKeyLength() const =0; - //! generate ephemeral private/public key pair - /*! Preconditions: - \begin{itemize} - \item size of privateKey == EphemeralPrivateKeyLength() - \item size of publicKey == EphemeralPublicKeyLength() - \end{itemize} - */ - virtual void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const =0; - - //! derive agreed value from your private keys and couterparty's public keys, return false in case of failure - /*! Note: The ephemeral public key will always be validated. - If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time. - Preconditions: - \begin{itemize} - \item size of agreedValue == AgreedValueLength() - \item length of staticPrivateKey == StaticPrivateKeyLength() - \item length of ephemeralPrivateKey == EphemeralPrivateKeyLength() - \item length of staticOtherPublicKey == StaticPublicKeyLength() - \item length of ephemeralOtherPublicKey == EphemeralPublicKeyLength() - \end{itemize} - */ - virtual bool Agree(byte *agreedValue, - const byte *staticPrivateKey, const byte *ephemeralPrivateKey, - const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, - bool validateStaticOtherPublicKey=true) const =0; -}; - -//! abstract base class for all objects that support precomputation - -/*! The class defines a common interface for doing precomputation, - and loading and saving precomputation. -*/ -class PK_Precomputation -{ -public: - //! - virtual ~PK_Precomputation() {} - - //! - /*! The exact semantics of Precompute() is varies, but - typically it means calculate a table of n objects - that can be used later to speed up computation. - */ - virtual void Precompute(unsigned int n) =0; - - //! retrieve previously saved precomputation - virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation) =0; - //! save precomputation for later use - virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const =0; -}; - -//! . -template class PK_WithPrecomputation : public virtual T, public virtual PK_Precomputation -{ -}; - -NAMESPACE_END - -#endif +// 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.6 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, Tiger, RIPEMD160, RIPEMD320, RIPEMD128, 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" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4127 4189 4505 4702) +#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 +const 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 reveives 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 retreved, 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 algorthm 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 algorthm 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 prameters +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 autimatically 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 autimatically 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/external/ours/library/crypto/src/shared/original/darn.cpp b/external/ours/library/crypto/src/shared/original/darn.cpp new file mode 100755 index 000000000..7f586beae --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/darn.cpp @@ -0,0 +1,236 @@ +// darn.cpp - written and placed in public domain by Jeffrey Walton + +#include "pch.h" +#include "config.h" +#include "cryptlib.h" +#include "secblock.h" +#include "darn.h" +#include "cpu.h" + +// At the moment only GCC 7.0 (and above) seems to support __builtin_darn() +// and __builtin_darn_32(). 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 the compile. + +// Inline assembler available in GCC 3.2 or above. For practical +// purposes we check for GCC 4.0 or above. GCC impostors claim +// to be GCC 4.2.1 so it will capture them, too. We exclude the +// Apple machines because they are not Power9 and use a slightly +// different syntax in their assembler. +#if ((__GNUC__ >= 4) || defined(__IBM_GCC_ASM)) && !defined(__APPLE__) +# define GCC_DARN_ASM_AVAILABLE 1 +#endif + +// warning C4702: unreachable code +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4702) +#endif + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// + +NAMESPACE_BEGIN(CryptoPP) + +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) + +// *************************** 32-bit *************************** // + +#if (CRYPTOPP_BOOL_PPC32) + +// Fills 4 bytes, buffer must be aligned +inline void DARN32(void* output) +{ + CRYPTOPP_ASSERT(IsAlignedOn(output, GetAlignmentOf())); + word32* ptr = reinterpret_cast(output); + +#if defined(GCC_DARN_ASM_AVAILABLE) + // This is "darn r3, 0". When L=0 a 32-bit conditioned word + // is returned. On failure 0xffffffffffffffff is returned. + // The Power manual recommends only checking the low 32-bit + // word for this case. See Power ISA 3.0 specification, p. 78. + do + { + __asm__ __volatile__ ( + #if (CRYPTOPP_BIG_ENDIAN) + ".byte 0x7c, 0x60, 0x05, 0xe6 \n\t" // r3 = darn 3, 0 + "mr %0, 3 \n\t" // val = r3 + #else + ".byte 0xe6, 0x05, 0x60, 0x7c \n\t" // r3 = darn 3, 0 + "mr %0, 3 \n\t" // val = r3 + #endif + : "=r" (*ptr) : : "r3" + ); + } while (*ptr == 0xFFFFFFFFu); +#elif defined(_ARCH_PWR9) + // This is probably going to break some platforms. + // We will deal with them as we encounter them. + *ptr = __builtin_darn_32(); +#elif defined(__APPLE__) + // Nop. Apple G4 and G5 machines are too old. They will + // avoid this code path because HasPower9() returns false. + CRYPTOPP_ASSERT(0); +#else + // Catch other compile breaks + int XXX[-1]; +#endif +} +#endif // PPC32 + +// *************************** 64-bit *************************** // + +#if (CRYPTOPP_BOOL_PPC64) + +// Fills 8 bytes, buffer must be aligned +inline void DARN64(void* output) +{ + CRYPTOPP_ASSERT(IsAlignedOn(output, GetAlignmentOf())); + word64* ptr = reinterpret_cast(output); + +#if defined(GCC_DARN_ASM_AVAILABLE) + // This is "darn r3, 1". When L=1 a 64-bit conditioned word + // is returned. On failure 0xffffffffffffffff is returned. + // See Power ISA 3.0 specification, p. 78. + do + { + __asm__ __volatile__ ( + #if (CRYPTOPP_BIG_ENDIAN) + ".byte 0x7c, 0x61, 0x05, 0xe6 \n\t" // r3 = darn 3, 1 + "mr %0, 3 \n\t" // val = r3 + #else + ".byte 0xe6, 0x05, 0x61, 0x7c \n\t" // r3 = darn 3, 1 + "mr %0, 3 \n\t" // val = r3 + #endif + : "=r" (*ptr) : : "r3" + ); + } while (*ptr == 0xFFFFFFFFFFFFFFFFull); +#elif defined(_ARCH_PWR9) + // This is probably going to break some platforms. + // We will deal with them as we encounter them. + *ptr = __builtin_darn(); +#elif defined(__APPLE__) + // Nop. Apple G4 and G5 machines are too old. They will + // avoid this code path because HasPower9() returns false. + CRYPTOPP_ASSERT(0); +#else + // Catch other compile breaks + int XXX[-1]; +#endif +} +#endif // PPC64 + +// ************************ Standard C++ ************************ // + +DARN::DARN() +{ + if (!HasDARN()) + throw DARN_Err("HasDARN"); + + // Scratch buffer in case user buffers are unaligned. + m_temp.New(8); +} + +void DARN::GenerateBlock(byte *output, size_t size) +{ + CRYPTOPP_ASSERT((output && size) || !(output || size)); + if (size == 0) return; + size_t i = 0; + +#if (CRYPTOPP_BOOL_PPC64) + + // Check alignment + i = reinterpret_cast(output) & 0x7; + if (i != 0) + { + DARN64(m_temp); + std::memcpy(output, m_temp, i); + + output += i; + size -= i; + } + + // Output is aligned + for (i = 0; i < size/8; i++) + DARN64(output+i*8); + + output += i*8; + size -= i*8; + + if (size) + { + DARN64(m_temp); + std::memcpy(output, m_temp, size); + } + +#elif (CRYPTOPP_BOOL_PPC32) + + // Check alignment + i = reinterpret_cast(output) & 0x3; + if (i != 0) + { + DARN32(m_temp); + std::memcpy(output, m_temp, i); + + output += i; + size -= i; + } + + // Output is aligned + for (i = 0; i < size/4; i++) + DARN32(output+i*4); + + output += i*4; + size -= i*4; + + if (size) + { + DARN32(m_temp); + std::memcpy(output, m_temp, size); + } + +#else + // No suitable compiler found + CRYPTOPP_UNUSED(output); + throw NotImplemented("DARN: failed to find a suitable implementation"); +#endif +} + +void DARN::DiscardBytes(size_t n) +{ + // RoundUpToMultipleOf is used because a full word is read, and its cheaper + // to discard full words. There's no sense in dealing with tail bytes. + FixedSizeSecBlock discard; + n = RoundUpToMultipleOf(n, sizeof(word64)); + + size_t count = STDMIN(n, discard.SizeInBytes()); + while (count) + { + GenerateBlock(discard.BytePtr(), count); + n -= count; + count = STDMIN(n, discard.SizeInBytes()); + } +} + +#else // not PPC32 or PPC64 + +DARN::DARN() +{ + throw DARN_Err("HasDARN"); +} + +void DARN::GenerateBlock(byte *output, size_t size) +{ + // Constructor will throw, should not get here + CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(size); +} + +void DARN::DiscardBytes(size_t n) +{ + // Constructor will throw, should not get here + CRYPTOPP_UNUSED(n); +} + +#endif // PPC32 or PPC64 + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/darn.h b/external/ours/library/crypto/src/shared/original/darn.h new file mode 100755 index 000000000..8965fd04e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/datatest.cpp b/external/ours/library/crypto/src/shared/original/datatest.cpp new file mode 100755 index 000000000..f3a8766f4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/datatest.cpp @@ -0,0 +1,1358 @@ +// datatest.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017 + +#define CRYPTOPP_DEFAULT_NO_DLL +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "factory.h" +#include "integer.h" +#include "filters.h" +#include "randpool.h" +#include "files.h" +#include "trunhash.h" +#include "queue.h" +#include "smartptr.h" +#include "validate.h" +#include "stdcpp.h" +#include "misc.h" +#include "hex.h" +#include "trap.h" + +#include +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +#ifdef _MSC_VER +# define STRTOUL64 _strtoui64 +#else +# define STRTOUL64 strtoull +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +ANONYMOUS_NAMESPACE_BEGIN + +bool s_thorough = false; +typedef std::map TestData; +const TestData *s_currentTestData = NULLPTR; +const std::string testDataFilename = "cryptest.dat"; + +// Handles CR, LF, and CRLF properly +// For istream.fail() see https://stackoverflow.com/q/34395801/608639. +bool Readline(std::istream& stream, std::string& line) +{ + // Ensure old data is cleared + line.clear(); + + std::string temp; + temp.reserve(64); + + while (!stream.fail()) + { + int ch = stream.get(); + if (ch == '\r') + { + int next = stream.peek(); + if (next == '\n') + (void)stream.get(); + + break; + } + else if (ch == '\n') + { + break; + } + + // Let string class manage its own capacity. + // The string will grow as needed. + temp.push_back(static_cast(ch)); + } + +#if defined(CRYPTOPP_CXX11) + temp.shrink_to_fit(); +#else + // Non-binding shrink to fit + temp.reserve(0); +#endif + + std::swap(line, temp); + + return !stream.fail(); +} + +std::string TrimSpace(const std::string& str) +{ + if (str.empty()) return ""; + + const std::string whitespace(" \r\t\n"); + std::string::size_type beg = str.find_first_not_of(whitespace); + std::string::size_type end = str.find_last_not_of(whitespace); + + if (beg != std::string::npos && end != std::string::npos) + return str.substr(beg, end+1); + else if (beg != std::string::npos) + return str.substr(beg); + else + return ""; +} + +std::string TrimComment(const std::string& str) +{ + if (str.empty()) return ""; + + std::string::size_type first = str.find("#"); + + if (first != std::string::npos) + return TrimSpace(str.substr(0, first)); + else + return TrimSpace(str); +} + +class TestFailure : public Exception +{ +public: + TestFailure() : Exception(OTHER_ERROR, "Validation test failed") {} +}; + +void OutputTestData(const TestData &v) +{ + std::cerr << "\n"; + for (TestData::const_iterator i = v.begin(); i != v.end(); ++i) + { + std::cerr << i->first << ": " << i->second << std::endl; + } +} + +void SignalTestFailure() +{ + OutputTestData(*s_currentTestData); + throw TestFailure(); +} + +void SignalUnknownAlgorithmError(const std::string& algType) +{ + OutputTestData(*s_currentTestData); + throw Exception(Exception::OTHER_ERROR, "Unknown algorithm " + algType + " during validation test"); +} + +void SignalTestError(const char* msg = NULLPTR) +{ + OutputTestData(*s_currentTestData); + + if (msg) + throw Exception(Exception::OTHER_ERROR, msg); + else + throw Exception(Exception::OTHER_ERROR, "Unexpected error during validation test"); +} + +bool DataExists(const TestData &data, const char *name) +{ + TestData::const_iterator i = data.find(name); + return (i != data.end()); +} + +const std::string & GetRequiredDatum(const TestData &data, const char *name) +{ + TestData::const_iterator i = data.find(name); + if (i == data.end()) + { + std::string msg("Required datum \"" + std::string(name) + "\" missing"); + SignalTestError(msg.c_str()); + } + return i->second; +} + +void RandomizedTransfer(BufferedTransformation &source, BufferedTransformation &target, bool finish, const std::string &channel=DEFAULT_CHANNEL) +{ + while (source.MaxRetrievable() > (finish ? 0 : 4096)) + { + byte buf[4096+64]; + size_t start = Test::GlobalRNG().GenerateWord32(0, 63); + size_t len = Test::GlobalRNG().GenerateWord32(1, UnsignedMin(4096U, 3*source.MaxRetrievable()/2)); + len = source.Get(buf+start, len); + target.ChannelPut(channel, buf+start, len); + } +} + +void PutDecodedDatumInto(const TestData &data, const char *name, BufferedTransformation &target) +{ + std::string s1 = GetRequiredDatum(data, name), s2; + ByteQueue q; + + while (!s1.empty()) + { + std::string::size_type pos = s1.find_first_not_of(" "); + if (pos != std::string::npos) + s1.erase(0, pos); + + if (s1.empty()) + goto end; + + int repeat = 1; + if (s1[0] == 'r') + { + s1 = s1.erase(0, 1); + repeat = std::atoi(s1.c_str()); + s1 = s1.substr(s1.find(' ')+1); + } + + // Convert word32 or word64 to little endian order. Some algorithm test vectors are + // presented in the format. We probably should have named them word32le and word64le. + if (s1.length() >= 6 && (s1.substr(0,6) == "word32" || s1.substr(0,6) == "word64")) + { + std::istringstream iss(s1.substr(6)); + if (s1.substr(0,6) == "word64") + { + word64 value; + while (iss >> std::skipws >> std::hex >> value) + { + value = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, value); + q.Put(reinterpret_cast(&value), 8); + } + } + else + { + word32 value; + while (iss >> std::skipws >> std::hex >> value) + { + value = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, value); + q.Put(reinterpret_cast(&value), 4); + } + } + goto end; + } + + s2.clear(); + if (s1[0] == '\"') + { + s2 = s1.substr(1, s1.find('\"', 1)-1); + s1 = s1.substr(s2.length() + 2); + } + else if (s1.substr(0, 2) == "0x") + { + std::string::size_type n = s1.find(' '); + StringSource(s1.substr(2, n), true, new HexDecoder(new StringSink(s2))); + s1 = s1.substr(STDMIN(n, s1.length())); + } + else + { + std::string::size_type n = s1.find(' '); + StringSource(s1.substr(0, n), true, new HexDecoder(new StringSink(s2))); + s1 = s1.substr(STDMIN(n, s1.length())); + } + + while (repeat--) + { + q.Put(ConstBytePtr(s2), BytePtrSize(s2)); + RandomizedTransfer(q, target, false); + } + } + +end: + RandomizedTransfer(q, target, true); +} + +std::string GetDecodedDatum(const TestData &data, const char *name) +{ + std::string s; + PutDecodedDatumInto(data, name, StringSink(s).Ref()); + return s; +} + +std::string GetOptionalDecodedDatum(const TestData &data, const char *name) +{ + std::string s; + if (DataExists(data, name)) + PutDecodedDatumInto(data, name, StringSink(s).Ref()); + return s; +} + +class TestDataNameValuePairs : public NameValuePairs +{ +public: + TestDataNameValuePairs(const TestData &data) : m_data(data) {} + + virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + TestData::const_iterator i = m_data.find(name); + if (i == m_data.end()) + { + if (std::string(name) == Name::DigestSize() && valueType == typeid(int)) + { + i = m_data.find("MAC"); + if (i == m_data.end()) + i = m_data.find("Digest"); + if (i == m_data.end()) + return false; + + m_temp.clear(); + PutDecodedDatumInto(m_data, i->first.c_str(), StringSink(m_temp).Ref()); + *reinterpret_cast(pValue) = (int)m_temp.size(); + return true; + } + else + return false; + } + + const std::string &value = i->second; + + if (valueType == typeid(int)) + *reinterpret_cast(pValue) = atoi(value.c_str()); + else if (valueType == typeid(word64)) + { + std::string x(value.empty() ? "0" : value); + const char* beg = &x[0]; + char* end = &x[0] + value.size(); + + errno = 0; + *reinterpret_cast(pValue) = STRTOUL64(beg, &end, 0); + if (errno != 0) + return false; + } + else if (valueType == typeid(Integer)) + *reinterpret_cast(pValue) = Integer((std::string(value) + "h").c_str()); + else if (valueType == typeid(ConstByteArrayParameter)) + { + m_temp.clear(); + PutDecodedDatumInto(m_data, name, StringSink(m_temp).Ref()); + reinterpret_cast(pValue)->Assign(ConstBytePtr(m_temp), BytePtrSize(m_temp), false); + } + else + throw ValueTypeMismatch(name, typeid(std::string), valueType); + + return true; + } + +private: + const TestData &m_data; + mutable std::string m_temp; +}; + +void TestKeyPairValidAndConsistent(CryptoMaterial &pub, const CryptoMaterial &priv, unsigned int &totalTests) +{ + totalTests++; + + if (!pub.Validate(Test::GlobalRNG(), 2U+!!s_thorough)) + SignalTestFailure(); + if (!priv.Validate(Test::GlobalRNG(), 2U+!!s_thorough)) + SignalTestFailure(); + + ByteQueue bq1, bq2; + pub.Save(bq1); + pub.AssignFrom(priv); + pub.Save(bq2); + if (bq1 != bq2) + SignalTestFailure(); +} + +void TestSignatureScheme(TestData &v, unsigned int &totalTests) +{ + std::string name = GetRequiredDatum(v, "Name"); + std::string test = GetRequiredDatum(v, "Test"); + + static member_ptr signer; + static member_ptr verifier; + static std::string lastName; + + if (name != lastName) + { + signer.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + verifier.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + lastName = name; + + // Code coverage + (void)signer->AlgorithmName(); + (void)verifier->AlgorithmName(); + (void)signer->AlgorithmProvider(); + (void)verifier->AlgorithmProvider(); + } + + TestDataNameValuePairs pairs(v); + + if (test == "GenerateKey") + { + totalTests++; + + signer->AccessPrivateKey().GenerateRandom(Test::GlobalRNG(), pairs); + verifier->AccessPublicKey().AssignFrom(signer->AccessPrivateKey()); + } + else + { + std::string keyFormat = GetRequiredDatum(v, "KeyFormat"); + + totalTests++; // key format + if (keyFormat == "DER") + verifier->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref()); + else if (keyFormat == "Component") + verifier->AccessMaterial().AssignFrom(pairs); + + if (test == "Verify" || test == "NotVerify") + { + totalTests++; + + SignatureVerificationFilter verifierFilter(*verifier, NULLPTR, SignatureVerificationFilter::SIGNATURE_AT_BEGIN); + PutDecodedDatumInto(v, "Signature", verifierFilter); + PutDecodedDatumInto(v, "Message", verifierFilter); + verifierFilter.MessageEnd(); + if (verifierFilter.GetLastResult() == (test == "NotVerify")) + SignalTestFailure(); + return; + } + else if (test == "PublicKeyValid") + { + totalTests++; + + if (!verifier->GetMaterial().Validate(Test::GlobalRNG(), 3)) + SignalTestFailure(); + return; + } + + totalTests++; // key format + if (keyFormat == "DER") + signer->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref()); + else if (keyFormat == "Component") + signer->AccessMaterial().AssignFrom(pairs); + } + + if (test == "GenerateKey" || test == "KeyPairValidAndConsistent") + { + totalTests++; + + TestKeyPairValidAndConsistent(verifier->AccessMaterial(), signer->GetMaterial(),totalTests); + SignatureVerificationFilter verifierFilter(*verifier, NULLPTR, SignatureVerificationFilter::THROW_EXCEPTION); + const byte msg[3] = {'a', 'b', 'c'}; + verifierFilter.Put(msg, sizeof(msg)); + StringSource ss(msg, sizeof(msg), true, new SignerFilter(Test::GlobalRNG(), *signer, new Redirector(verifierFilter))); + } + else if (test == "Sign") + { + totalTests++; + + SignerFilter f(Test::GlobalRNG(), *signer, new HexEncoder(new FileSink(std::cout))); + StringSource ss(GetDecodedDatum(v, "Message"), true, new Redirector(f)); + SignalTestFailure(); + } + else if (test == "DeterministicSign") + { + totalTests++; + + // This test is specialized for RFC 6979. The RFC is a drop-in replacement + // for DSA and ECDSA, and access to the seed or secret is not needed. If + // additional deterministic signatures are added, then the test harness will + // likely need to be extended. + std::string signature; + SignerFilter f(Test::GlobalRNG(), *signer, new StringSink(signature)); + StringSource ss(GetDecodedDatum(v, "Message"), true, new Redirector(f)); + + if (GetDecodedDatum(v, "Signature") != signature) + SignalTestFailure(); + } + else + { + std::string msg("Unknown signature test \"" + test + "\""); + SignalTestError(msg.c_str()); + CRYPTOPP_ASSERT(false); + } +} + +// Subset of TestSignatureScheme. We picked the tests that have data that is easy to write to a file. +// Also see https://github.com/weidai11/cryptopp/issues/1010, where HIGHT broke when using FileSource. +void TestSignatureSchemeWithFileSource(TestData &v, unsigned int &totalTests) +{ + std::string name = GetRequiredDatum(v, "Name"); + std::string test = GetRequiredDatum(v, "Test"); + + if (test != "Sign" && test != "DeterministicSign") { return; } + + static member_ptr signer; + static member_ptr verifier; + static std::string lastName; + + if (name != lastName) + { + signer.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + verifier.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + name = lastName; + + // Code coverage + (void)signer->AlgorithmName(); + (void)verifier->AlgorithmName(); + (void)signer->AlgorithmProvider(); + (void)verifier->AlgorithmProvider(); + } + + TestDataNameValuePairs pairs(v); + + std::string keyFormat = GetRequiredDatum(v, "KeyFormat"); + + totalTests++; // key format + if (keyFormat == "DER") + verifier->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref()); + else if (keyFormat == "Component") + verifier->AccessMaterial().AssignFrom(pairs); + + totalTests++; // key format + if (keyFormat == "DER") + signer->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref()); + else if (keyFormat == "Component") + signer->AccessMaterial().AssignFrom(pairs); + + if (test == "Sign") + { + totalTests++; + + SignerFilter f(Test::GlobalRNG(), *signer, new HexEncoder(new FileSink(std::cout))); + StringSource ss(GetDecodedDatum(v, "Message"), true, new FileSink(testDataFilename.c_str())); + FileSource fs(testDataFilename.c_str(), true, new Redirector(f)); + SignalTestFailure(); + } + else if (test == "DeterministicSign") + { + totalTests++; + + // This test is specialized for RFC 6979. The RFC is a drop-in replacement + // for DSA and ECDSA, and access to the seed or secret is not needed. If + // additional deterministic signatures are added, then the test harness will + // likely need to be extended. + std::string signature; + SignerFilter f(Test::GlobalRNG(), *signer, new StringSink(signature)); + StringSource ss(GetDecodedDatum(v, "Message"), true, new FileSink(testDataFilename.c_str())); + FileSource fs(testDataFilename.c_str(), true, new Redirector(f)); + + if (GetDecodedDatum(v, "Signature") != signature) + SignalTestFailure(); + } +} + +void TestAsymmetricCipher(TestData &v, unsigned int &totalTests) +{ + std::string name = GetRequiredDatum(v, "Name"); + std::string test = GetRequiredDatum(v, "Test"); + + static member_ptr encryptor; + static member_ptr decryptor; + static std::string lastName; + + if (name != lastName) + { + encryptor.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + decryptor.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + lastName = name; + + // Code coverage + (void)encryptor->AlgorithmName(); + (void)decryptor->AlgorithmName(); + (void)encryptor->AlgorithmProvider(); + (void)decryptor->AlgorithmProvider(); + } + + std::string keyFormat = GetRequiredDatum(v, "KeyFormat"); + + if (keyFormat == "DER") + { + totalTests++; + + decryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref()); + encryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref()); + } + else if (keyFormat == "Component") + { + totalTests++; + + TestDataNameValuePairs pairs(v); + decryptor->AccessMaterial().AssignFrom(pairs); + encryptor->AccessMaterial().AssignFrom(pairs); + } + + if (test == "DecryptMatch") + { + totalTests++; + + std::string decrypted, expected = GetDecodedDatum(v, "Plaintext"); + StringSource ss(GetDecodedDatum(v, "Ciphertext"), true, new PK_DecryptorFilter(Test::GlobalRNG(), *decryptor, new StringSink(decrypted))); + if (decrypted != expected) + SignalTestFailure(); + } + else if (test == "KeyPairValidAndConsistent") + { + totalTests++; + + TestKeyPairValidAndConsistent(encryptor->AccessMaterial(), decryptor->GetMaterial(), totalTests); + } + else + { + std::string msg("Unknown asymmetric cipher test \"" + test + "\""); + SignalTestError(msg.c_str()); + CRYPTOPP_ASSERT(false); + } +} + +void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters, unsigned int &totalTests) +{ + std::string name = GetRequiredDatum(v, "Name"); + std::string test = GetRequiredDatum(v, "Test"); + + std::string key = GetDecodedDatum(v, "Key"); + std::string plaintext = GetDecodedDatum(v, "Plaintext"); + + TestDataNameValuePairs testDataPairs(v); + CombinedNameValuePairs pairs(overrideParameters, testDataPairs); + + if (test == "Encrypt" || test == "EncryptXorDigest" || test == "Resync" || test == "EncryptionMCT" || test == "DecryptionMCT") + { + static member_ptr encryptor, decryptor; + static std::string lastName; + + totalTests++; + + if (name != lastName) + { + encryptor.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + decryptor.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + lastName = name; + + // Code coverage + (void)encryptor->AlgorithmName(); + (void)decryptor->AlgorithmName(); + (void)encryptor->AlgorithmProvider(); + (void)decryptor->AlgorithmProvider(); + (void)encryptor->IsRandomAccess(); + (void)decryptor->IsRandomAccess(); + (void)encryptor->MinKeyLength(); + (void)decryptor->MinKeyLength(); + (void)encryptor->MaxKeyLength(); + (void)decryptor->MaxKeyLength(); + (void)encryptor->DefaultKeyLength(); + (void)decryptor->DefaultKeyLength(); + } + + ConstByteArrayParameter iv; + if (pairs.GetValue(Name::IV(), iv) && iv.size() != encryptor->IVSize()) + SignalTestFailure(); + + if (test == "Resync") + { + encryptor->Resynchronize(iv.begin(), (int)iv.size()); + decryptor->Resynchronize(iv.begin(), (int)iv.size()); + } + else + { + encryptor->SetKey(ConstBytePtr(key), BytePtrSize(key), pairs); + decryptor->SetKey(ConstBytePtr(key), BytePtrSize(key), pairs); + } + + word64 seek64 = pairs.GetWord64ValueWithDefault("Seek64", 0); + if (seek64) + { + encryptor->Seek(seek64); + decryptor->Seek(seek64); + } + else + { + int seek = pairs.GetIntValueWithDefault("Seek", 0); + if (seek) + { + encryptor->Seek(seek); + decryptor->Seek(seek); + } + } + + // Most block ciphers don't specify BlockPaddingScheme. Kalyna uses it + // in test vectors. 0 is NoPadding, 1 is ZerosPadding, 2 is PkcsPadding, + // 3 is OneAndZerosPadding, etc. Note: The machinery is wired such that + // paddingScheme is effectively latched. An old paddingScheme may be + // unintentionally used in a subsequent test. + int paddingScheme = pairs.GetIntValueWithDefault(Name::BlockPaddingScheme(), 0); + + std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest; + if (test == "EncryptionMCT" || test == "DecryptionMCT") + { + SymmetricCipher *cipher = encryptor.get(); + std::string buf(plaintext), keybuf(key); + + if (test == "DecryptionMCT") + { + cipher = decryptor.get(); + ciphertext = GetDecodedDatum(v, "Ciphertext"); + buf.assign(ciphertext.begin(), ciphertext.end()); + } + + for (int i=0; i<400; i++) + { + encrypted.reserve(10000 * plaintext.size()); + for (int j=0; j<10000; j++) + { + cipher->ProcessString(BytePtr(buf), BytePtrSize(buf)); + encrypted.append(buf.begin(), buf.end()); + } + + encrypted.erase(0, encrypted.size() - keybuf.size()); + xorbuf(BytePtr(keybuf), BytePtr(encrypted), BytePtrSize(keybuf)); + cipher->SetKey(BytePtr(keybuf), BytePtrSize(keybuf)); + } + + encrypted.assign(buf.begin(), buf.end()); + ciphertext = GetDecodedDatum(v, test == "EncryptionMCT" ? "Ciphertext" : "Plaintext"); + if (encrypted != ciphertext) + { + std::cout << "\nincorrectly encrypted: "; + StringSource ss(encrypted, false, new HexEncoder(new FileSink(std::cout))); + ss.Pump(256); ss.Flush(false); + std::cout << "\n"; + SignalTestFailure(); + } + return; + } + + StreamTransformationFilter encFilter(*encryptor, new StringSink(encrypted), + static_cast(paddingScheme)); + + StringStore pstore(plaintext); + RandomizedTransfer(pstore, encFilter, true); + encFilter.MessageEnd(); + + if (test != "EncryptXorDigest") + { + ciphertext = GetDecodedDatum(v, "Ciphertext"); + } + else + { + ciphertextXorDigest = GetDecodedDatum(v, "CiphertextXorDigest"); + xorDigest.append(encrypted, 0, 64); + for (size_t i=64; i(xorDigest[i%64] ^ encrypted[i]); + } + if (test != "EncryptXorDigest" ? encrypted != ciphertext : xorDigest != ciphertextXorDigest) + { + std::cout << "\nincorrectly encrypted: "; + StringSource ss(encrypted, false, new HexEncoder(new FileSink(std::cout))); + ss.Pump(2048); ss.Flush(false); + std::cout << "\n"; + SignalTestFailure(); + } + + std::string decrypted; + StreamTransformationFilter decFilter(*decryptor, new StringSink(decrypted), + static_cast(paddingScheme)); + + StringStore cstore(encrypted); + RandomizedTransfer(cstore, decFilter, true); + decFilter.MessageEnd(); + + if (decrypted != plaintext) + { + std::cout << "\nincorrectly decrypted: "; + StringSource ss(decrypted, false, new HexEncoder(new FileSink(std::cout))); + ss.Pump(256); ss.Flush(false); + std::cout << "\n"; + SignalTestFailure(); + } + } + else + { + std::string msg("Unknown symmetric cipher test \"" + test + "\""); + SignalTestError(msg.c_str()); + } +} + +// Subset of TestSymmetricCipher. We picked the tests that have data that is easy to write to a file. +// Also see https://github.com/weidai11/cryptopp/issues/1010, where HIGHT broke when using FileSource. +void TestSymmetricCipherWithFileSource(TestData &v, const NameValuePairs &overrideParameters, unsigned int &totalTests) +{ + std::string name = GetRequiredDatum(v, "Name"); + std::string test = GetRequiredDatum(v, "Test"); + + // Limit FileSource tests to Encrypt only. + if (test != "Encrypt") { return; } + + totalTests++; + + std::string key = GetDecodedDatum(v, "Key"); + std::string plaintext = GetDecodedDatum(v, "Plaintext"); + + TestDataNameValuePairs testDataPairs(v); + CombinedNameValuePairs pairs(overrideParameters, testDataPairs); + + static member_ptr encryptor, decryptor; + static std::string lastName; + + if (name != lastName) + { + encryptor.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + decryptor.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + lastName = name; + + // Code coverage + (void)encryptor->AlgorithmName(); + (void)decryptor->AlgorithmName(); + (void)encryptor->AlgorithmProvider(); + (void)decryptor->AlgorithmProvider(); + (void)encryptor->MinKeyLength(); + (void)decryptor->MinKeyLength(); + (void)encryptor->MaxKeyLength(); + (void)decryptor->MaxKeyLength(); + (void)encryptor->DefaultKeyLength(); + (void)decryptor->DefaultKeyLength(); + } + + ConstByteArrayParameter iv; + if (pairs.GetValue(Name::IV(), iv) && iv.size() != encryptor->IVSize()) + SignalTestFailure(); + + encryptor->SetKey(ConstBytePtr(key), BytePtrSize(key), pairs); + decryptor->SetKey(ConstBytePtr(key), BytePtrSize(key), pairs); + + word64 seek64 = pairs.GetWord64ValueWithDefault("Seek64", 0); + if (seek64) + { + encryptor->Seek(seek64); + decryptor->Seek(seek64); + } + else + { + int seek = pairs.GetIntValueWithDefault("Seek", 0); + if (seek) + { + encryptor->Seek(seek); + decryptor->Seek(seek); + } + } + + // Most block ciphers don't specify BlockPaddingScheme. Kalyna uses it + // in test vectors. 0 is NoPadding, 1 is ZerosPadding, 2 is PkcsPadding, + // 3 is OneAndZerosPadding, etc. Note: The machinery is wired such that + // paddingScheme is effectively latched. An old paddingScheme may be + // unintentionally used in a subsequent test. + int paddingScheme = pairs.GetIntValueWithDefault(Name::BlockPaddingScheme(), 0); + + std::string encrypted, ciphertext; + StreamTransformationFilter encFilter(*encryptor, new StringSink(encrypted), + static_cast(paddingScheme)); + + StringSource ss(plaintext, true, new FileSink(testDataFilename.c_str())); + FileSource pstore(testDataFilename.c_str(), true); + RandomizedTransfer(pstore, encFilter, true); + encFilter.MessageEnd(); + + ciphertext = GetDecodedDatum(v, "Ciphertext"); + + if (encrypted != ciphertext) + { + std::cout << "\nincorrectly encrypted: "; + StringSource sss(encrypted, false, new HexEncoder(new FileSink(std::cout))); + sss.Pump(2048); sss.Flush(false); + std::cout << "\n"; + SignalTestFailure(); + } + + std::string decrypted; + StreamTransformationFilter decFilter(*decryptor, new StringSink(decrypted), + static_cast(paddingScheme)); + + StringStore cstore(encrypted); + RandomizedTransfer(cstore, decFilter, true); + decFilter.MessageEnd(); + + if (decrypted != plaintext) + { + std::cout << "\nincorrectly decrypted: "; + StringSource sss(decrypted, false, new HexEncoder(new FileSink(std::cout))); + sss.Pump(256); sss.Flush(false); + std::cout << "\n"; + SignalTestFailure(); + } +} + +void TestAuthenticatedSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters, unsigned int &totalTests) +{ + std::string type = GetRequiredDatum(v, "AlgorithmType"); + std::string name = GetRequiredDatum(v, "Name"); + std::string test = GetRequiredDatum(v, "Test"); + std::string key = GetDecodedDatum(v, "Key"); + + std::string plaintext = GetOptionalDecodedDatum(v, "Plaintext"); + std::string ciphertext = GetOptionalDecodedDatum(v, "Ciphertext"); + std::string header = GetOptionalDecodedDatum(v, "Header"); + std::string footer = GetOptionalDecodedDatum(v, "Footer"); + std::string mac = GetOptionalDecodedDatum(v, "MAC"); + + TestDataNameValuePairs testDataPairs(v); + CombinedNameValuePairs pairs(overrideParameters, testDataPairs); + + if (test == "Encrypt" || test == "EncryptXorDigest" || test == "NotVerify") + { + totalTests++; + + static member_ptr encryptor; + static member_ptr decryptor; + static std::string lastName; + + if (name != lastName) + { + encryptor.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + decryptor.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + name = lastName; + + // Code coverage + (void)encryptor->AlgorithmName(); + (void)decryptor->AlgorithmName(); + (void)encryptor->AlgorithmProvider(); + (void)decryptor->AlgorithmProvider(); + (void)encryptor->MinKeyLength(); + (void)decryptor->MinKeyLength(); + (void)encryptor->MaxKeyLength(); + (void)decryptor->MaxKeyLength(); + (void)encryptor->DefaultKeyLength(); + (void)decryptor->DefaultKeyLength(); + (void)encryptor->IsRandomAccess(); + (void)decryptor->IsRandomAccess(); + (void)encryptor->IsSelfInverting(); + (void)decryptor->IsSelfInverting(); + (void)encryptor->MaxHeaderLength(); + (void)decryptor->MaxHeaderLength(); + (void)encryptor->MaxMessageLength(); + (void)decryptor->MaxMessageLength(); + (void)encryptor->MaxFooterLength(); + (void)decryptor->MaxFooterLength(); + (void)encryptor->NeedsPrespecifiedDataLengths(); + (void)decryptor->NeedsPrespecifiedDataLengths(); + } + + encryptor->SetKey(ConstBytePtr(key), BytePtrSize(key), pairs); + decryptor->SetKey(ConstBytePtr(key), BytePtrSize(key), pairs); + + std::string encrypted, decrypted; + AuthenticatedEncryptionFilter ef(*encryptor, new StringSink(encrypted)); + bool macAtBegin = !mac.empty() && !Test::GlobalRNG().GenerateBit(); // test both ways randomly + AuthenticatedDecryptionFilter df(*decryptor, new StringSink(decrypted), macAtBegin ? AuthenticatedDecryptionFilter::MAC_AT_BEGIN : 0); + + if (encryptor->NeedsPrespecifiedDataLengths()) + { + encryptor->SpecifyDataLengths(header.size(), plaintext.size(), footer.size()); + decryptor->SpecifyDataLengths(header.size(), plaintext.size(), footer.size()); + } + + StringStore sh(header), sp(plaintext), sc(ciphertext), sf(footer), sm(mac); + + if (macAtBegin) + RandomizedTransfer(sm, df, true); + sh.CopyTo(df, LWORD_MAX, AAD_CHANNEL); + RandomizedTransfer(sc, df, true); + sf.CopyTo(df, LWORD_MAX, AAD_CHANNEL); + if (!macAtBegin) + RandomizedTransfer(sm, df, true); + df.MessageEnd(); + + RandomizedTransfer(sh, ef, true, AAD_CHANNEL); + RandomizedTransfer(sp, ef, true); + RandomizedTransfer(sf, ef, true, AAD_CHANNEL); + ef.MessageEnd(); + + if (test == "Encrypt" && encrypted != ciphertext+mac) + { + std::cout << "\nincorrectly encrypted: "; + StringSource ss(encrypted, false, new HexEncoder(new FileSink(std::cout))); + ss.Pump(2048); ss.Flush(false); + std::cout << "\n"; + SignalTestFailure(); + } + if (test == "Encrypt" && decrypted != plaintext) + { + std::cout << "\nincorrectly decrypted: "; + StringSource ss(decrypted, false, new HexEncoder(new FileSink(std::cout))); + ss.Pump(256); ss.Flush(false); + std::cout << "\n"; + SignalTestFailure(); + } + + if (ciphertext.size()+mac.size()-plaintext.size() != encryptor->DigestSize()) + { + std::cout << "\nbad MAC size\n"; + SignalTestFailure(); + } + if (df.GetLastResult() != (test == "Encrypt")) + { + std::cout << "\nMAC incorrectly verified\n"; + SignalTestFailure(); + } + } + else + { + std::string msg("Unknown authenticated symmetric cipher test \"" + test + "\""); + SignalTestError(msg.c_str()); + } +} + +void TestDigestOrMAC(TestData &v, bool testDigest, unsigned int &totalTests) +{ + std::string name = GetRequiredDatum(v, "Name"); + std::string test = GetRequiredDatum(v, "Test"); + const char *digestName = testDigest ? "Digest" : "MAC"; + + member_ptr mac; + member_ptr hash; + HashTransformation *pHash = NULLPTR; + + TestDataNameValuePairs pairs(v); + + if (testDigest) + { + hash.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + pHash = hash.get(); + + // Code coverage + (void)hash->AlgorithmName(); + (void)hash->AlgorithmProvider(); + (void)hash->TagSize(); + (void)hash->DigestSize(); + (void)hash->Restart(); + } + else + { + mac.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + pHash = mac.get(); + std::string key = GetDecodedDatum(v, "Key"); + mac->SetKey(ConstBytePtr(key), BytePtrSize(key), pairs); + + // Code coverage + (void)mac->AlgorithmName(); + (void)mac->AlgorithmProvider(); + (void)mac->TagSize(); + (void)mac->DigestSize(); + (void)mac->Restart(); + (void)mac->MinKeyLength(); + (void)mac->MaxKeyLength(); + (void)mac->DefaultKeyLength(); + } + + if (test == "Verify" || test == "VerifyTruncated" || test == "NotVerify") + { + totalTests++; + + int digestSize = -1; + if (test == "VerifyTruncated") + digestSize = pairs.GetIntValueWithDefault(Name::DigestSize(), digestSize); + HashVerificationFilter verifierFilter(*pHash, NULLPTR, HashVerificationFilter::HASH_AT_BEGIN, digestSize); + PutDecodedDatumInto(v, digestName, verifierFilter); + PutDecodedDatumInto(v, "Message", verifierFilter); + verifierFilter.MessageEnd(); + if (verifierFilter.GetLastResult() == (test == "NotVerify")) + SignalTestFailure(); + } + else + { + std::string msg("Unknown digest or mac test \"" + test + "\""); + SignalTestError(msg.c_str()); + } +} + +void TestKeyDerivationFunction(TestData &v, unsigned int &totalTests) +{ + totalTests++; + + std::string name = GetRequiredDatum(v, "Name"); + std::string test = GetRequiredDatum(v, "Test"); + + if(test == "Skip") return; + + std::string secret = GetDecodedDatum(v, "Secret"); + std::string expected = GetDecodedDatum(v, "DerivedKey"); + + TestDataNameValuePairs pairs(v); + + static member_ptr kdf; + static std::string lastName; + + if (name != lastName) + { + kdf.reset(ObjectFactoryRegistry::Registry().CreateObject(name.c_str())); + name = lastName; + + // Code coverage + (void)kdf->AlgorithmName(); + (void)kdf->AlgorithmProvider(); + (void)kdf->MinDerivedKeyLength(); + (void)kdf->MaxDerivedKeyLength(); + } + + std::string calculated; calculated.resize(expected.size()); + kdf->DeriveKey(BytePtr(calculated), BytePtrSize(calculated), BytePtr(secret), BytePtrSize(secret), pairs); + + if(calculated != expected) + { + std::cerr << "Calculated: "; + StringSource(calculated, true, new HexEncoder(new FileSink(std::cerr))); + std::cerr << std::endl; + + SignalTestFailure(); + } +} + +inline char FirstChar(const std::string& str) { + if (str.empty()) return 0; + return str[0]; +} + +inline char LastChar(const std::string& str) { + if (str.empty()) return 0; + return str[str.length()-1]; +} + +// GetField parses the name/value pairs. If this function is modified, +// then run 'cryptest.exe tv all' to ensure parsing still works. +bool GetField(std::istream &is, std::string &name, std::string &value) +{ + std::string line; + name.clear(); value.clear(); + + // ***** Name ***** + while (Readline(is, line)) + { + // Eat empty lines and comments gracefully + line = TrimSpace(line); + if (line.empty() || line[0] == '#') + continue; + + std::string::size_type pos = line.find(':'); + if (pos == std::string::npos) + SignalTestError("Unable to parse name/value pair"); + + name = TrimSpace(line.substr(0, pos)); + line = TrimSpace(line.substr(pos +1)); + + // Empty name is bad + if (name.empty()) + return false; + + // Empty value is ok + if (line.empty()) + return true; + + break; + } + + // ***** Value ***** + bool continueLine = true; + + do + { + continueLine = false; + + // Trim leading and trailing whitespace. Don't parse comments + // here because there may be a line continuation at the end. + line = TrimSpace(line); + + if (line.empty()) + continue; + + // Check for continuation. The slash must be the last character. + if (LastChar(line) == '\\') { + continueLine = true; + line.erase(line.end()-1); + } + + // Re-trim after parsing + line = TrimComment(line); + line = TrimSpace(line); + + if (line.empty()) + continue; + + // Finally... the value + value += line; + + if (continueLine) + value += ' '; + } + while (continueLine && Readline(is, line)); + + return true; +} + +void OutputPair(const NameValuePairs &v, const char *name) +{ + Integer x; + bool b = v.GetValue(name, x); + CRYPTOPP_UNUSED(b); CRYPTOPP_ASSERT(b); + std::cout << name << ": \\\n "; + x.Encode(HexEncoder(new FileSink(std::cout), false, 64, "\\\n ").Ref(), x.MinEncodedSize()); + std::cout << std::endl; +} + +void OutputNameValuePairs(const NameValuePairs &v) +{ + std::string names = v.GetValueNames(); + std::string::size_type i = 0; + while (i < names.size()) + { + std::string::size_type j = names.find_first_of (';', i); + + if (j == std::string::npos) + return; + else + { + std::string name = names.substr(i, j-i); + if (name.find(':') == std::string::npos) + OutputPair(v, name.c_str()); + } + + i = j + 1; + } +} + +void TestDataFile(std::string filename, const NameValuePairs &overrideParameters, unsigned int &totalTests, unsigned int &failedTests) +{ + std::ifstream file(DataDir(filename).c_str()); + if (!file.good()) + throw Exception(Exception::OTHER_ERROR, "Can not open file " + DataDir(filename) + " for reading"); + + TestData v; + s_currentTestData = &v; + std::string name, value, lastAlgName; + + while (file) + { + if (!GetField(file, name, value)) + break; + + if (name == "AlgorithmType") + v.clear(); + + // Can't assert value. Plaintext is sometimes empty. + // CRYPTOPP_ASSERT(!value.empty()); + v[name] = value; + + // The name "Test" is special. It tells the framework + // to run the test. Otherwise, name/value pairs are + // parsed and added to TestData 'v'. + if (name == "Test" && (s_thorough || v["SlowTest"] != "1")) + { + bool failed = false; + std::string algType = GetRequiredDatum(v, "AlgorithmType"); + std::string algName = GetRequiredDatum(v, "Name"); + + if (lastAlgName != algName) + { + std::cout << "\nTesting " << algType << " algorithm " << algName << ".\n"; + lastAlgName = algName; + } + + // In the old days each loop ran one test. Later, things were modified to run the + // the same test twice. Some tests are run with both a StringSource and a FileSource + // to catch FileSource specific errors. currentTests and deltaTests (below) keep + // the book keeping in order. + unsigned int currentTests = totalTests; + + try + { + if (algType == "Signature") + { + TestSignatureScheme(v, totalTests); + TestSignatureSchemeWithFileSource(v, totalTests); + } + else if (algType == "SymmetricCipher") + { + TestSymmetricCipher(v, overrideParameters, totalTests); + TestSymmetricCipherWithFileSource(v, overrideParameters, totalTests); + } + else if (algType == "AuthenticatedSymmetricCipher") + TestAuthenticatedSymmetricCipher(v, overrideParameters, totalTests); + else if (algType == "AsymmetricCipher") + TestAsymmetricCipher(v, totalTests); + else if (algType == "MessageDigest") + TestDigestOrMAC(v, true, totalTests); + else if (algType == "MAC") + TestDigestOrMAC(v, false, totalTests); + else if (algType == "KDF") + TestKeyDerivationFunction(v, totalTests); + else if (algType == "FileList") + TestDataFile(GetRequiredDatum(v, "Test"), g_nullNameValuePairs, totalTests, failedTests); + else + SignalUnknownAlgorithmError(algType); + } + catch (const TestFailure &) + { + failed = true; + std::cout << "\nTest FAILED.\n"; + } + catch (const Exception &e) + { + failed = true; + std::cout << "\nCryptoPP::Exception caught: " << e.what() << std::endl; + } + catch (const std::exception &e) + { + failed = true; + std::cout << "\nstd::exception caught: " << e.what() << std::endl; + } + + if (failed) + { + std::cout << "Skipping to next test." << std::endl; + failedTests++; + } + else + { + if (algType != "FileList") + { + unsigned int deltaTests = totalTests-currentTests; + if (deltaTests) + { + std::string progress(deltaTests, '.'); + std::cout << progress; + if (currentTests % 4 == 0) + std::cout << std::flush; + } + } + } + + // Most tests fully specify parameters, like key and iv. Each test gets + // its own unique value. Since each test gets a new value for each test + // case, latching a value in 'TestData v' does not matter. The old key + // or iv will get overwritten on the next test. + // + // If a per-test vector parameter was set for a test, like BlockPadding, + // BlockSize or Tweak, then it becomes latched in 'TestData v'. The old + // value is used in subsequent tests, and it could cause a self test + // failure in the next test. The behavior surfaced under Kalyna and + // Threefish. The Kalyna test vectors use NO_PADDING for all tests except + // one. Threefish occasionally uses a Tweak. + // + // Unlatch BlockPadding, BlockSize and Tweak now, after the test has been + // run. Also note we only unlatch from 'TestData v'. If overrideParameters + // are specified, the caller is responsible for managing the parameter. + v.erase("Tweak"); v.erase("InitialBlock"); + v.erase("BlockSize"); v.erase("BlockPaddingScheme"); + } + } +} + +ANONYMOUS_NAMESPACE_END + +bool RunTestDataFile(const char *filename, const NameValuePairs &overrideParameters, bool thorough) +{ + s_thorough = thorough; + unsigned int totalTests = 0, failedTests = 0; + TestDataFile((filename ? filename : ""), overrideParameters, totalTests, failedTests); + + std::cout << std::dec << "\nTests complete. Total tests = " << totalTests << ". Failed tests = " << failedTests << "." << std::endl; + if (failedTests != 0) + std::cout << "SOME TESTS FAILED!\n"; + + CRYPTOPP_ASSERT(failedTests == 0); + return failedTests == 0; +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/default.cpp b/external/ours/library/crypto/src/shared/original/default.cpp new file mode 100755 index 000000000..1723a0156 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/default.cpp @@ -0,0 +1,307 @@ +// default.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4127 4189) +#endif + +#include "cryptlib.h" +#include "filters.h" +#include "smartptr.h" +#include "default.h" +#include "queue.h" + +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +// The purpose of this function Mash() is to take an arbitrary length input +// string and *deterministicly* 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. + +template +static void Mash(const byte *in, size_t inLen, byte *out, size_t outLen, int iterations) +{ + if (BytePrecision(outLen) > 2) + throw InvalidArgument("Mash: output legnth too large"); + + size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)H::DIGESTSIZE); + byte b[2]; + SecByteBlock buf(bufSize); + SecByteBlock outBuf(bufSize); + H hash; + + unsigned int i; + for(i=0; i> 8); + b[1] = (byte) i; + hash.Update(b, 2); + hash.Update(in, inLen); + hash.Final(outBuf+i); + } + + while (iterations-- > 1) + { + memcpy(buf, outBuf, bufSize); + for (i=0; i> 8); + b[1] = (byte) i; + hash.Update(b, 2); + hash.Update(buf, bufSize); + hash.Final(outBuf+i); + } + } + + memcpy(out, outBuf, outLen); +} + +template +static void GenerateKeyIV(const byte *passphrase, size_t passphraseLength, const byte *salt, size_t saltLength, unsigned int iterations, byte *key, byte *IV) +{ + // UBsan. User supplied params, may be NULL + SecByteBlock temp(passphraseLength+saltLength); + if (passphrase != NULLPTR) + memcpy(temp, passphrase, passphraseLength); + if (salt != NULLPTR) + memcpy(temp+passphraseLength, salt, saltLength); + + // OK. Derived params, cannot be NULL + SecByteBlock keyIV(EnumToInt(Info::KEYLENGTH)+EnumToInt(+Info::BLOCKSIZE)); + Mash(temp, passphraseLength + saltLength, keyIV, EnumToInt(Info::KEYLENGTH)+EnumToInt(+Info::BLOCKSIZE), iterations); + memcpy(key, keyIV, Info::KEYLENGTH); + memcpy(IV, keyIV+Info::KEYLENGTH, Info::BLOCKSIZE); +} + +// ******************************************************** + +template +DataEncryptor::DataEncryptor(const char *passphrase, BufferedTransformation *attachment) + : ProxyFilter(NULLPTR, 0, 0, attachment), m_passphrase((const byte *)passphrase, strlen(passphrase)) +{ + CRYPTOPP_COMPILE_ASSERT((int)SALTLENGTH <= DIGESTSIZE); + CRYPTOPP_COMPILE_ASSERT((int)BLOCKSIZE <= (int)DIGESTSIZE); +} + +template +DataEncryptor::DataEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment) + : ProxyFilter(NULLPTR, 0, 0, attachment), m_passphrase(passphrase, passphraseLength) +{ + CRYPTOPP_COMPILE_ASSERT((int)SALTLENGTH <= (int)DIGESTSIZE); + CRYPTOPP_COMPILE_ASSERT((int)BLOCKSIZE <= (int)DIGESTSIZE); +} + +template +void DataEncryptor::FirstPut(const byte *) +{ + SecByteBlock salt(DIGESTSIZE), keyCheck(DIGESTSIZE); + H hash; + + // use hash(passphrase | time | clock) as salt + hash.Update(m_passphrase, m_passphrase.size()); + time_t t=time(NULLPTR); + hash.Update((byte *)&t, sizeof(t)); + clock_t c=clock(); + hash.Update((byte *)&c, sizeof(c)); + hash.Final(salt); + + // use hash(passphrase | salt) as key check + hash.Update(m_passphrase, m_passphrase.size()); + hash.Update(salt, SALTLENGTH); + hash.Final(keyCheck); + + AttachedTransformation()->Put(salt, SALTLENGTH); + + // mash passphrase and salt together into key and IV + SecByteBlock key(KEYLENGTH); + SecByteBlock IV(BLOCKSIZE); + GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, ITERATIONS, key, IV); + + m_cipher.SetKeyWithIV(key, key.size(), IV); + SetFilter(new StreamTransformationFilter(m_cipher)); + + m_filter->Put(keyCheck, BLOCKSIZE); +} + +template +void DataEncryptor::LastPut(const byte *inString, size_t length) +{ + CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length); + m_filter->MessageEnd(); +} + +// ******************************************************** + +template +DataDecryptor::DataDecryptor(const char *p, BufferedTransformation *attachment, bool throwException) + : ProxyFilter(NULLPTR, EnumToInt(SALTLENGTH)+EnumToInt(BLOCKSIZE), 0, attachment) + , m_state(WAITING_FOR_KEYCHECK) + , m_passphrase((const byte *)p, strlen(p)) + , m_throwException(throwException) +{ + CRYPTOPP_COMPILE_ASSERT((int)SALTLENGTH <= (int)DIGESTSIZE); + CRYPTOPP_COMPILE_ASSERT((int)BLOCKSIZE <= (int)DIGESTSIZE); +} + +template +DataDecryptor::DataDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException) + : ProxyFilter(NULLPTR, EnumToInt(SALTLENGTH)+EnumToInt(BLOCKSIZE), 0, attachment) + , m_state(WAITING_FOR_KEYCHECK) + , m_passphrase(passphrase, passphraseLength) + , m_throwException(throwException) +{ + CRYPTOPP_COMPILE_ASSERT((int)SALTLENGTH <= (int)DIGESTSIZE); + CRYPTOPP_COMPILE_ASSERT((int)BLOCKSIZE <= (int)DIGESTSIZE); +} + +template +void DataDecryptor::FirstPut(const byte *inString) +{ + CheckKey(inString, inString+SALTLENGTH); +} + +template +void DataDecryptor::LastPut(const byte *inString, size_t length) +{ + CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length); + if (m_filter.get() == NULLPTR) + { + m_state = KEY_BAD; + if (m_throwException) + throw KeyBadErr(); + } + else + { + m_filter->MessageEnd(); + m_state = WAITING_FOR_KEYCHECK; + } +} + +template +void DataDecryptor::CheckKey(const byte *salt, const byte *keyCheck) +{ + SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DIGESTSIZE)); + + H hash; + hash.Update(m_passphrase, m_passphrase.size()); + hash.Update(salt, SALTLENGTH); + hash.Final(check); + + SecByteBlock key(KEYLENGTH); + SecByteBlock IV(BLOCKSIZE); + GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, ITERATIONS, key, IV); + + m_cipher.SetKeyWithIV(key, key.size(), IV); + member_ptr decryptor(new StreamTransformationFilter(m_cipher)); + + decryptor->Put(keyCheck, BLOCKSIZE); + decryptor->ForceNextPut(); + decryptor->Get(check+EnumToInt(BLOCKSIZE), BLOCKSIZE); + + SetFilter(decryptor.release()); + + if (!VerifyBufsEqual(check, check+EnumToInt(BLOCKSIZE), BLOCKSIZE)) + { + m_state = KEY_BAD; + if (m_throwException) + throw KeyBadErr(); + } + else + m_state = KEY_GOOD; +} + +// ******************************************************** + +template +static MAC* NewDataEncryptorMAC(const byte *passphrase, size_t passphraseLength) +{ + size_t macKeyLength = MAC::StaticGetValidKeyLength(16); + SecByteBlock macKey(macKeyLength); + // since the MAC is encrypted there is no reason to mash the passphrase for many iterations + Mash(passphrase, passphraseLength, macKey, macKeyLength, 1); + return new MAC(macKey, macKeyLength); +} + +template +DataEncryptorWithMAC::DataEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment) + : ProxyFilter(NULLPTR, 0, 0, attachment) + , m_mac(NewDataEncryptorMAC((const byte *)passphrase, strlen(passphrase))) +{ + SetFilter(new HashFilter(*m_mac, new DataEncryptor(passphrase), true)); +} + +template +DataEncryptorWithMAC::DataEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment) + : ProxyFilter(NULLPTR, 0, 0, attachment) + , m_mac(NewDataEncryptorMAC(passphrase, passphraseLength)) +{ + SetFilter(new HashFilter(*m_mac, new DataEncryptor(passphrase, passphraseLength), true)); +} + +template +void DataEncryptorWithMAC::LastPut(const byte *inString, size_t length) +{ + CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length); + m_filter->MessageEnd(); +} + +// ******************************************************** + +template +DataDecryptorWithMAC::DataDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment, bool throwException) + : ProxyFilter(NULLPTR, 0, 0, attachment) + , m_mac(NewDataEncryptorMAC((const byte *)passphrase, strlen(passphrase))) + , m_throwException(throwException) +{ + SetFilter(new DataDecryptor(passphrase, m_hashVerifier=new HashVerificationFilter(*m_mac, NULLPTR, HashVerificationFilter::PUT_MESSAGE), throwException)); +} + +template +DataDecryptorWithMAC::DataDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException) + : ProxyFilter(NULLPTR, 0, 0, attachment) + , m_mac(NewDataEncryptorMAC(passphrase, passphraseLength)) + , m_throwException(throwException) +{ + SetFilter(new DataDecryptor(passphrase, passphraseLength, m_hashVerifier=new HashVerificationFilter(*m_mac, NULLPTR, HashVerificationFilter::PUT_MESSAGE), throwException)); +} + +template +typename DataDecryptor::State DataDecryptorWithMAC::CurrentState() const +{ + return static_cast *>(m_filter.get())->CurrentState(); +} + +template +bool DataDecryptorWithMAC::CheckLastMAC() const +{ + return m_hashVerifier->GetLastResult(); +} + +template +void DataDecryptorWithMAC::LastPut(const byte *inString, size_t length) +{ + CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length); + m_filter->MessageEnd(); + if (m_throwException && !CheckLastMAC()) + throw MACBadErr(); +} + +template struct DataParametersInfo; +template struct DataParametersInfo; + +template class DataEncryptor; +template class DataDecryptor; +template class DataEncryptor; +template class DataDecryptor; +template class DataEncryptorWithMAC; +template class DataDecryptorWithMAC; +template class DataEncryptorWithMAC; +template class DataDecryptorWithMAC; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/default.h b/external/ours/library/crypto/src/shared/original/default.h new file mode 100755 index 000000000..7fe443f2a --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/des.cpp b/external/ours/library/crypto/src/shared/original/des.cpp new file mode 100755 index 000000000..2a130aa4a --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/des.cpp @@ -0,0 +1,465 @@ +// des.cpp - modified by Wei Dai from Phil Karn's des.c +// The original code and all modifications are in the public domain. + +/* + * This is a major rewrite of my old public domain DES code written + * circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977 + * public domain code. I pretty much kept my key scheduling code, but + * the actual encrypt/decrypt routines are taken from from Richard + * Outerbridge's DES code as printed in Schneier's "Applied Cryptography." + * + * This code is in the public domain. I would appreciate bug reports and + * enhancements. + * + * Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994. + */ + +#include "pch.h" +#include "misc.h" +#include "des.h" + +NAMESPACE_BEGIN(CryptoPP) + +typedef BlockGetAndPut Block; + +// Richard Outerbridge's initial permutation algorithm +/* +inline void IPERM(word32 &left, word32 &right) +{ + word32 work; + + work = ((left >> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= work << 4; + work = ((left >> 16) ^ right) & 0xffff; + right ^= work; + left ^= work << 16; + work = ((right >> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ left) & 0xff00ff; + left ^= work; + right ^= (work << 8); + right = rotl(right, 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = rotl(left, 1); +} +inline void FPERM(word32 &left, word32 &right) +{ + word32 work; + + right = rotr(right, 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = rotr(left, 1); + work = ((left >> 8) ^ right) & 0xff00ff; + right ^= work; + left ^= work << 8; + work = ((left >> 2) ^ right) & 0x33333333; + right ^= work; + left ^= work << 2; + work = ((right >> 16) ^ left) & 0xffff; + left ^= work; + right ^= work << 16; + work = ((right >> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= work << 4; +} +*/ + +// Wei Dai's modification to Richard Outerbridge's initial permutation +// algorithm, this one is faster if you have access to rotate instructions +// (like in MSVC) +static inline void IPERM(word32 &left, word32 &right) +{ + word32 work; + + right = rotlConstant<4>(right); + work = (left ^ right) & 0xf0f0f0f0; + left ^= work; + right = rotrConstant<20>(right^work); + work = (left ^ right) & 0xffff0000; + left ^= work; + right = rotrConstant<18>(right^work); + work = (left ^ right) & 0x33333333; + left ^= work; + right = rotrConstant<6>(right^work); + work = (left ^ right) & 0x00ff00ff; + left ^= work; + right = rotlConstant<9>(right^work); + work = (left ^ right) & 0xaaaaaaaa; + left = rotlConstant<1>(left^work); + right ^= work; +} + +static inline void FPERM(word32 &left, word32 &right) +{ + word32 work; + + right = rotrConstant<1>(right); + work = (left ^ right) & 0xaaaaaaaa; + right ^= work; + left = rotrConstant<9>(left^work); + work = (left ^ right) & 0x00ff00ff; + right ^= work; + left = rotlConstant<6>(left^work); + work = (left ^ right) & 0x33333333; + right ^= work; + left = rotlConstant<18>(left^work); + work = (left ^ right) & 0xffff0000; + right ^= work; + left = rotlConstant<20>(left^work); + work = (left ^ right) & 0xf0f0f0f0; + right ^= work; + left = rotrConstant<4>(left^work); +} + +void DES::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + RawSetKey(GetCipherDirection(), userKey); +} + +#ifndef CRYPTOPP_IMPORTS + +/* Tables defined in the Data Encryption Standard documents + * Three of these tables, the initial permutation, the final + * permutation and the expansion operator, are regular enough that + * for speed, we hard-code them. They're here for reference only. + * Also, the S and P boxes are used by a separate program, gensp.c, + * to build the combined SP box, Spbox[]. They're also here just + * for reference. + */ +#ifdef notdef +/* initial permutation IP */ +static byte ip[] = { + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 +}; + +/* final permutation IP^-1 */ +static byte fp[] = { + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 +}; +/* expansion operation matrix */ +static byte ei[] = { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 +}; +/* The (in)famous S-boxes */ +static byte sbox[8][64] = { + /* S1 */ + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, + + /* S2 */ + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, + + /* S3 */ + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, + + /* S4 */ + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, + + /* S5 */ + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, + + /* S6 */ + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, + + /* S7 */ + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, + + /* S8 */ + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 +}; + +/* 32-bit permutation function P used on the output of the S-boxes */ +namespace { + const byte p32i[] = { + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 + }; +} +#endif + +/* permuted choice table (key) */ +namespace { + const byte pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 + }; +} + +/* number left rotations of pc1 */ +namespace { + const byte totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 + }; +} + +/* permuted choice key (table) */ +namespace { + const byte pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + }; +} + +/* End of DES-defined tables */ + +/* bit 0 is left-most in byte */ +namespace { + const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 + }; +} + +/* Set key (initialize key schedule array) */ +void RawDES::RawSetKey(CipherDir dir, const byte *key) +{ +#if (_MSC_VER >= 1600) || (__cplusplus >= 201103L) +# define REGISTER /* Define to nothing for C++11 and above */ +#else +# define REGISTER register +#endif + + SecByteBlock buffer(56+56+8); + byte *const pc1m=buffer; /* place to modify pc1 into */ + byte *const pcr=pc1m+56; /* place to rotate pc1 into */ + byte *const ks=pcr+56; + REGISTER int i,j,l; + int m; + + for (j=0; j<56; j++) { /* convert pc1 to bits of key */ + l=pc1[j]-1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j]=(key[l>>3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + for (i=0; i<16; i++) { /* key chunk for each iteration */ + memset(ks,0,8); /* Clear key schedule */ + for (j=0; j<56; j++) /* rotate pc1 the right amount */ + pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28]; + /* rotate left and right halves independently */ + for (j=0; j<48; j++){ /* select bits individually */ + /* check bit that goes to ks[j] */ + if (pcr[pc2[j]-1]){ + /* mask it in if it's there */ + l= j % 6; + ks[j/6] |= bytebit[l] >> 2; + } + } + /* Now convert to odd/even interleaved form for use in F */ + k[2*i] = ((word32)ks[0] << 24) + | ((word32)ks[2] << 16) + | ((word32)ks[4] << 8) + | ((word32)ks[6]); + k[2*i+1] = ((word32)ks[1] << 24) + | ((word32)ks[3] << 16) + | ((word32)ks[5] << 8) + | ((word32)ks[7]); + } + + if (dir==DECRYPTION) // reverse key schedule order + for (i=0; i<16; i+=2) + { + std::swap(k[i], k[32-2-i]); + std::swap(k[i+1], k[32-1-i]); + } +} + +void RawDES::RawProcessBlock(word32 &l_, word32 &r_) const +{ + word32 l = l_, r = r_; + const word32 *kptr=k; + + for (unsigned i=0; i<8; i++) + { + word32 work = rotrConstant<4>(r) ^ kptr[4 * i + 0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ kptr[4*i+1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + work = rotrConstant<4>(l) ^ kptr[4 * i + 2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ kptr[4*i+3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + } + + l_ = l; r_ = r; +} + +void DES_EDE2::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + m_des1.RawSetKey(GetCipherDirection(), userKey); + m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey+8); +} + +void DES_EDE2::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 l,r; + Block::Get(inBlock)(l)(r); + IPERM(l,r); + m_des1.RawProcessBlock(l, r); + m_des2.RawProcessBlock(r, l); + m_des1.RawProcessBlock(l, r); + FPERM(l,r); + Block::Put(xorBlock, outBlock)(r)(l); +} + +void DES_EDE3::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + m_des1.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 0 : 16)); + m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey + 8); + m_des3.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 16 : 0)); +} + +void DES_EDE3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 l,r; + Block::Get(inBlock)(l)(r); + IPERM(l,r); + m_des1.RawProcessBlock(l, r); + m_des2.RawProcessBlock(r, l); + m_des3.RawProcessBlock(l, r); + FPERM(l,r); + Block::Put(xorBlock, outBlock)(r)(l); +} + +#endif // #ifndef CRYPTOPP_IMPORTS + +static inline bool CheckParity(byte b) +{ + unsigned int a = b ^ (b >> 4); + return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1; +} + +bool DES::CheckKeyParityBits(const byte *key) +{ + for (unsigned int i=0; i<8; i++) + if (!CheckParity(key[i])) + return false; + return true; +} + +void DES::CorrectKeyParityBits(byte *key) +{ + for (unsigned int i=0; i<8; i++) + if (!CheckParity(key[i])) + key[i] ^= 1; +} + +// Encrypt or decrypt a block of data in ECB mode +void DES::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 l,r; + Block::Get(inBlock)(l)(r); + IPERM(l,r); + RawProcessBlock(l, r); + FPERM(l,r); + Block::Put(xorBlock, outBlock)(r)(l); +} + +void DES_XEX3::Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + if (!m_des.get()) + m_des.reset(new DES::Encryption); + + memcpy(m_x1, key + (IsForwardTransformation() ? 0 : 16), BLOCKSIZE); + m_des->RawSetKey(GetCipherDirection(), key + 8); + memcpy(m_x3, key + (IsForwardTransformation() ? 16 : 0), BLOCKSIZE); +} + +void DES_XEX3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + xorbuf(outBlock, inBlock, m_x1, BLOCKSIZE); + m_des->ProcessAndXorBlock(outBlock, xorBlock, outBlock); + xorbuf(outBlock, m_x3, BLOCKSIZE); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/des.h b/external/ours/library/crypto/src/shared/original/des.h new file mode 100755 index 000000000..ece7b378d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/dessp.cpp b/external/ours/library/crypto/src/shared/original/dessp.cpp new file mode 100755 index 000000000..46ca7aaf7 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/dessp.cpp @@ -0,0 +1,88 @@ +// This file is mostly generated by Phil Karn's gensp.c + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "des.h" + +NAMESPACE_BEGIN(CryptoPP) + +const word32 RawDES::Spbox[8][64] = { +{ +0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000, +0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004, +0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404, +0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000, +0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400, +0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404, +0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400, +0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004}, +{ +0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020, +0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020, +0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000, +0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020, +0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000, +0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000, +0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020, +0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000}, +{ +0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200, +0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208, +0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208, +0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000, +0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000, +0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008, +0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008, +0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200}, +{ +0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001, +0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001, +0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080, +0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081, +0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000, +0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080, +0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081, +0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080}, +{ +0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000, +0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000, +0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100, +0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100, +0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100, +0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000, +0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000, +0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100}, +{ +0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000, +0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010, +0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010, +0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000, +0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010, +0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000, +0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010, +0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010}, +{ +0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800, +0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802, +0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002, +0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800, +0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002, +0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800, +0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802, +0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002}, +{ +0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000, +0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040, +0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000, +0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000, +0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040, +0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040, +0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000, +0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000} +}; + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/dh.cpp b/external/ours/library/crypto/src/shared/original/dh.cpp new file mode 100755 index 000000000..5a0e7d1d3 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/dh.cpp @@ -0,0 +1,21 @@ +// dh.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "dh.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void DH_TestInstantiations() +{ + DH dh1; + DH dh2(NullRNG(), 10); +} +#endif + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/dh.h b/external/ours/library/crypto/src/shared/original/dh.h new file mode 100755 index 000000000..4f462e48c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/dh2.cpp b/external/ours/library/crypto/src/shared/original/dh2.cpp new file mode 100755 index 000000000..4c062d4e3 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/dh2.cpp @@ -0,0 +1,69 @@ +// dh2.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "cryptlib.h" +#include "misc.h" +#include "dh2.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +struct NullCryptoParameters : public CryptoParameters +{ + void AssignFrom(const NameValuePairs &source) { + CRYPTOPP_UNUSED(source); + } + bool Validate(RandomNumberGenerator &rng, unsigned int level) const { + CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(level); + return false; + } + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const { + CRYPTOPP_UNUSED(name); CRYPTOPP_UNUSED(valueType); CRYPTOPP_UNUSED(pValue); + return false; + } +}; + +struct NullSimpleKeyAgreementDomain : public TwoBases +{ + CryptoParameters & AccessCryptoParameters() { + return *this; + } + unsigned int AgreedValueLength() const { + return 1; + } + unsigned int PrivateKeyLength() const { + return 1; + } + unsigned int PublicKeyLength() const { + return 1; + } + void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const { + CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(privateKey); + } + void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const { + CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(privateKey); CRYPTOPP_UNUSED(publicKey); + } + bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const { + CRYPTOPP_UNUSED(agreedValue); CRYPTOPP_UNUSED(privateKey); + CRYPTOPP_UNUSED(otherPublicKey); CRYPTOPP_UNUSED(validateOtherPublicKey); + return false; + } +}; + +void DH2_TestInstantiations() +{ + NullSimpleKeyAgreementDomain dom; + DH2 dh(dom); +} +#endif + +bool DH2::Agree(byte *agreedValue, + const byte *staticSecretKey, const byte *ephemeralSecretKey, + const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, + bool validateStaticOtherPublicKey) const +{ + return d1.Agree(agreedValue, staticSecretKey, staticOtherPublicKey, validateStaticOtherPublicKey) + && d2.Agree(agreedValue+d1.AgreedValueLength(), ephemeralSecretKey, ephemeralOtherPublicKey, true); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/dh2.h b/external/ours/library/crypto/src/shared/original/dh2.h new file mode 100755 index 000000000..b86161d79 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/dll.cpp b/external/ours/library/crypto/src/shared/original/dll.cpp new file mode 100755 index 000000000..2115f9f58 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/dll.cpp @@ -0,0 +1,169 @@ +// dll.cpp - originally written and placed in the public domain by Wei Dai + +#define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#define CRYPTOPP_DEFAULT_NO_DLL + +#include "dll.h" +#include "config.h" +#include "iterhash.h" +#include "pkcspad.h" +#include "emsa2.h" + +#if defined(CRYPTOPP_MSC_VERSION) +// Cast from FARPROC to funcptr with args, http://stackoverflow.com/q/4192058/608639 +# pragma warning(disable: 4191) +#endif + +#if defined(CRYPTOPP_EXPORTS) && defined(CRYPTOPP_WIN32_AVAILABLE) +# include +#endif + +#ifndef CRYPTOPP_IMPORTS + +NAMESPACE_BEGIN(CryptoPP) + +// Guarding based on DLL due to Clang, http://github.com/weidai11/cryptopp/issues/300 +#ifdef CRYPTOPP_IS_DLL +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1c}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +// http://github.com/weidai11/cryptopp/issues/517. OIDs and encoded prefixes found at +// http://www.ietf.org/archive/id/draft-jivsov-openpgp-sha3-01.txt +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x31,0x30,0x0d, 0x06,0x09,0x60,0x86, 0x48,0x01,0x65,0x03, 0x04,0x02,0x08,0x05, 0x00,0x04,0x20}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x41,0x30,0x0d, 0x06,0x09,0x60,0x86, 0x48,0x01,0x65,0x03, 0x04,0x02,0x09,0x05, 0x00,0x04,0x30}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x51,0x30,0x0d, 0x06,0x09,0x60,0x86, 0x48,0x01,0x65,0x03, 0x04,0x02,0x0a,0x05, 0x00,0x04,0x40}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte EMSA2HashId::id = 0x33; +template<> const byte EMSA2HashId::id = 0x38; +template<> const byte EMSA2HashId::id = 0x34; +template<> const byte EMSA2HashId::id = 0x36; +template<> const byte EMSA2HashId::id = 0x35; + +#endif // CRYPTOPP_IS_DLL + +NAMESPACE_END + +#endif + +#ifdef CRYPTOPP_EXPORTS + +USING_NAMESPACE(CryptoPP) + +using std::set_new_handler; + +static PNew s_pNew = NULLPTR; +static PDelete s_pDelete = NULLPTR; + +static void * New (size_t size) +{ + void *p; + while ((p = malloc(size)) == NULLPTR) + CallNewHandler(); + + return p; +} + +static void SetNewAndDeleteFunctionPointers() +{ + void *p = NULLPTR; + HMODULE hModule = NULLPTR; + MEMORY_BASIC_INFORMATION mbi; + + while (true) + { + VirtualQuery(p, &mbi, sizeof(mbi)); + + if (p >= (char *)mbi.BaseAddress + mbi.RegionSize) + break; + + p = (char *)mbi.BaseAddress + mbi.RegionSize; + + if (!mbi.AllocationBase || mbi.AllocationBase == hModule) + continue; + + hModule = HMODULE(mbi.AllocationBase); + PGetNewAndDelete pGetNewAndDelete = (PGetNewAndDelete)GetProcAddress(hModule, "GetNewAndDeleteForCryptoPP"); + if (pGetNewAndDelete) + { + pGetNewAndDelete(s_pNew, s_pDelete); + return; + } + + PSetNewAndDelete pSetNewAndDelete = (PSetNewAndDelete)GetProcAddress(hModule, "SetNewAndDeleteFromCryptoPP"); + if (pSetNewAndDelete) + { + s_pNew = &New; + s_pDelete = &free; + pSetNewAndDelete(s_pNew, s_pDelete, &set_new_handler); + return; + } + } + + // try getting these directly using mangled names of new and delete operators + + hModule = GetModuleHandle("msvcrtd"); + if (!hModule) + hModule = GetModuleHandle("msvcrt"); + if (hModule) + { + // 32-bit versions + s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPAXI@Z"); + s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPAX@Z"); + if (s_pNew && s_pDelete) + return; + + // 64-bit versions + s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPEAX_K@Z"); + s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPEAX@Z"); + if (s_pNew && s_pDelete) + return; + } + + OutputDebugStringA("Crypto++ DLL was not able to obtain new and delete function pointers.\n"); + throw 0; +} + +// Cast from FARPROC to funcptr with args +#pragma warning(default: 4191) + +void * operator new (size_t size) +{ + if (!s_pNew) + SetNewAndDeleteFunctionPointers(); + + return s_pNew(size); +} + +void operator delete (void * p) +{ + s_pDelete(p); +} + +void * operator new [] (size_t size) +{ + return operator new (size); +} + +void operator delete [] (void * p) +{ + operator delete (p); +} + +#endif // CRYPTOPP_EXPORTS diff --git a/external/ours/library/crypto/src/shared/original/dll.h b/external/ours/library/crypto/src/shared/original/dll.h new file mode 100755 index 000000000..f923026cb --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/dlltest.cpp b/external/ours/library/crypto/src/shared/original/dlltest.cpp new file mode 100755 index 000000000..addced553 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/dlltest.cpp @@ -0,0 +1,212 @@ +#ifndef CRYPTOPP_DLL_ONLY +# define CRYPTOPP_DEFAULT_NO_DLL +#endif + +#include "dll.h" +#include "cryptlib.h" +#include "filters.h" +#include "pkcspad.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +USING_NAMESPACE(CryptoPP) + +void FIPS140_SampleApplication() +{ + if (!FIPS_140_2_ComplianceEnabled()) + { + std::cerr << "FIPS 140-2 compliance was turned off at compile time.\n"; + abort(); + } + + // check self test status + if (GetPowerUpSelfTestStatus() != POWER_UP_SELF_TEST_PASSED) + { + std::cerr << "Automatic power-up self test failed.\n"; + abort(); + } + std::cout << "0. Automatic power-up self test passed.\n"; + + // simulate a power-up self test error + SimulatePowerUpSelfTestFailure(); + try + { + // trying to use a crypto algorithm after power-up self test error will result in an exception + AES::Encryption aes; + + // should not be here + std::cerr << "Use of AES failed to cause an exception after power-up self test error.\n"; + abort(); + } + catch (SelfTestFailure &e) + { + std::cout << "1. Caught expected exception when simulating self test failure. Exception message follows: "; + std::cout << e.what() << std::endl; + } + + // clear the self test error state and redo power-up self test + DoDllPowerUpSelfTest(); + if (GetPowerUpSelfTestStatus() != POWER_UP_SELF_TEST_PASSED) + { + std::cerr << "Re-do power-up self test failed.\n"; + abort(); + } + std::cout << "2. Re-do power-up self test passed.\n"; + + // encrypt and decrypt + const byte key[] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; + const byte iv[] = {0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; + const byte plaintext[] = { // "Now is the time for all " without tailing 0 + 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20}; + byte ciphertext[24]; + byte decrypted[24]; + + CFB_FIPS_Mode::Encryption encryption_DES_EDE3_CFB; + encryption_DES_EDE3_CFB.SetKeyWithIV(key, sizeof(key), iv); + encryption_DES_EDE3_CFB.ProcessString(ciphertext, plaintext, 24); + + CFB_FIPS_Mode::Decryption decryption_DES_EDE3_CFB; + decryption_DES_EDE3_CFB.SetKeyWithIV(key, sizeof(key), iv); + decryption_DES_EDE3_CFB.ProcessString(decrypted, ciphertext, 24); + + if (memcmp(plaintext, decrypted, 24) != 0) + { + std::cerr << "DES-EDE3-CFB Encryption/decryption failed.\n"; + abort(); + } + std::cout << "3. DES-EDE3-CFB Encryption/decryption succeeded.\n"; + + // hash + const byte message[] = {'a', 'b', 'c'}; + const byte expectedDigest[] = {0xA9,0x99,0x3E,0x36,0x47,0x06,0x81,0x6A,0xBA,0x3E,0x25,0x71,0x78,0x50,0xC2,0x6C,0x9C,0xD0,0xD8,0x9D}; + byte digest[20]; + + SHA1 sha; + sha.Update(message, 3); + sha.Final(digest); + + if (memcmp(digest, expectedDigest, 20) != 0) + { + std::cerr << "SHA-1 hash failed.\n"; + abort(); + } + std::cout << "4. SHA-1 hash succeeded.\n"; + + // create auto-seeded X9.17 RNG object, if available +#ifdef OS_RNG_AVAILABLE + AutoSeededX917RNG rng; +#else + // this is used to allow this function to compile on platforms that don't have auto-seeded RNGs + RandomNumberGenerator &rng(NullRNG()); +#endif + + // generate DSA key + DSA::PrivateKey dsaPrivateKey; + dsaPrivateKey.GenerateRandomWithKeySize(rng, 1024); + DSA::PublicKey dsaPublicKey; + dsaPublicKey.AssignFrom(dsaPrivateKey); + if (!dsaPrivateKey.Validate(rng, 3) || !dsaPublicKey.Validate(rng, 3)) + { + std::cerr << "DSA key generation failed.\n"; + abort(); + } + std::cout << "5. DSA key generation succeeded.\n"; + + // encode DSA key + std::string encodedDsaPublicKey, encodedDsaPrivateKey; + dsaPublicKey.DEREncode(StringSink(encodedDsaPublicKey).Ref()); + dsaPrivateKey.DEREncode(StringSink(encodedDsaPrivateKey).Ref()); + + // decode DSA key + DSA::PrivateKey decodedDsaPrivateKey; + decodedDsaPrivateKey.BERDecode(StringStore(encodedDsaPrivateKey).Ref()); + DSA::PublicKey decodedDsaPublicKey; + decodedDsaPublicKey.BERDecode(StringStore(encodedDsaPublicKey).Ref()); + + if (!decodedDsaPrivateKey.Validate(rng, 3) || !decodedDsaPublicKey.Validate(rng, 3)) + { + std::cerr << "DSA key encode/decode failed.\n"; + abort(); + } + std::cout << "6. DSA key encode/decode succeeded.\n"; + + // sign and verify + byte signature[40]; + DSA::Signer signer(dsaPrivateKey); + CRYPTOPP_ASSERT(signer.SignatureLength() == 40); + signer.SignMessage(rng, message, 3, signature); + + DSA::Verifier verifier(dsaPublicKey); + if (!verifier.VerifyMessage(message, 3, signature, sizeof(signature))) + { + std::cerr << "DSA signature and verification failed.\n"; + abort(); + } + std::cout << "7. DSA signature and verification succeeded.\n"; + + + // try to verify an invalid signature + signature[0] ^= 1; + if (verifier.VerifyMessage(message, 3, signature, sizeof(signature))) + { + std::cerr << "DSA signature verification failed to detect bad signature.\n"; + abort(); + } + std::cout << "8. DSA signature verification successfully detected bad signature.\n"; + + // try to use an invalid key length + try + { + ECB_Mode::Encryption encryption_DES_EDE3_ECB; + encryption_DES_EDE3_ECB.SetKey(key, 5); + + // should not be here + std::cerr << "DES-EDE3 implementation did not detect use of invalid key length.\n"; + abort(); + } + catch (InvalidArgument &e) + { + std::cout << "9. Caught expected exception when using invalid key length. Exception message follows: "; + std::cout << e.what() << std::endl; + } + + std::cout << "\nFIPS 140-2 Sample Application completed normally.\n"; +} + +#ifdef CRYPTOPP_IMPORTS + +static PNew s_pNew = NULLPTR; +static PDelete s_pDelete = NULLPTR; + +extern "C" __declspec(dllexport) void __cdecl SetNewAndDeleteFromCryptoPP(PNew pNew, PDelete pDelete, PSetNewHandler pSetNewHandler) +{ + (void)(pSetNewHandler); + s_pNew = pNew; + s_pDelete = pDelete; +} + +void * __cdecl operator new (size_t size) +{ + return s_pNew(size); +} + +void __cdecl operator delete (void * p) +{ + s_pDelete(p); +} + +#endif + +#ifdef CRYPTOPP_DLL_ONLY + +int __cdecl main() +{ + FIPS140_SampleApplication(); + return 0; +} + +#endif diff --git a/external/ours/library/crypto/src/shared/original/dmac.h b/external/ours/library/crypto/src/shared/original/dmac.h new file mode 100755 index 000000000..9d911708c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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); + 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); + 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/external/ours/library/crypto/src/shared/original/donna.h b/external/ours/library/crypto/src/shared/original/donna.h new file mode 100755 index 000000000..2f3365389 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/donna.h @@ -0,0 +1,178 @@ +// 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 "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(_MSC_VER) && 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 (CRYPTOPP_SSE2_INTRIN_AVAILABLE) && defined(_MSC_VER) +# 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/external/ours/library/crypto/src/shared/original/donna_32.cpp b/external/ours/library/crypto/src/shared/original/donna_32.cpp new file mode 100755 index 000000000..51f0ae0ce --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/donna_32.cpp @@ -0,0 +1,2102 @@ +// donna_32.cpp - 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. + +// A fair amount of duplication happens below, but we could not directly +// use curve25519 for both x25519 and ed25519. A close examination reveals +// slight differences in the implementation. For example, look at the +// two curve25519_sub functions. + +// If needed, see Moon's commit "Go back to ignoring 256th bit [sic]", +// https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658 + +#include "pch.h" + +#include "config.h" +#include "donna.h" +#include "secblock.h" +#include "sha.h" +#include "misc.h" +#include "cpu.h" + +#include +#include + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4244) +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char DONNA32_FNAME[] = __FILE__; + +ANONYMOUS_NAMESPACE_BEGIN + +// Can't use GetAlignmentOf() because of C++11 and constexpr +// Can use 'const unsigned int' because of MSVC 2013 +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +# define ALIGN_SPEC 16 +#else +# define ALIGN_SPEC 4 +#endif + +ANONYMOUS_NAMESPACE_END + +#if defined(CRYPTOPP_CURVE25519_32BIT) + +#include "donna_32.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::GetWord; +using CryptoPP::PutWord; +using CryptoPP::LITTLE_ENDIAN_ORDER; + +inline word32 U8TO32_LE(const byte* p) +{ + return GetWord(false, LITTLE_ENDIAN_ORDER, p); +} + +inline void U32TO8_LE(byte* p, word32 w) +{ + PutWord(false, LITTLE_ENDIAN_ORDER, p, w); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Donna) +NAMESPACE_BEGIN(X25519) +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::sword32; +using CryptoPP::word64; +using CryptoPP::sword64; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; + +// Bring in all the symbols from the 32-bit header +using namespace CryptoPP::Donna::Arch32; + +/* out = in */ +inline void +curve25519_copy(bignum25519 out, const bignum25519 in) { + out[0] = in[0]; out[1] = in[1]; + out[2] = in[2]; out[3] = in[3]; + out[4] = in[4]; out[5] = in[5]; + out[6] = in[6]; out[7] = in[7]; + out[8] = in[8]; out[9] = in[9]; +} + +/* out = a + b */ +inline void +curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) { + out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; + out[4] = a[4] + b[4]; out[5] = a[5] + b[5]; + out[6] = a[6] + b[6]; out[7] = a[7] + b[7]; + out[8] = a[8] + b[8]; out[9] = a[9] + b[9]; +} + +/* out = a - b */ +inline void +curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word32 c; + out[0] = 0x7ffffda + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; + out[1] = 0x3fffffe + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; + out[2] = 0x7fffffe + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; + out[3] = 0x3fffffe + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; + out[4] = 0x7fffffe + a[4] - b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; + out[5] = 0x3fffffe + a[5] - b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; + out[6] = 0x7fffffe + a[6] - b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; + out[7] = 0x3fffffe + a[7] - b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; + out[8] = 0x7fffffe + a[8] - b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; + out[9] = 0x3fffffe + a[9] - b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; + out[0] += 19 * c; +} + +/* out = in * scalar */ +inline void +curve25519_scalar_product(bignum25519 out, const bignum25519 in, const word32 scalar) { + word64 a; + word32 c; + a = mul32x32_64(in[0], scalar); out[0] = (word32)a & reduce_mask_26; c = (word32)(a >> 26); + a = mul32x32_64(in[1], scalar) + c; out[1] = (word32)a & reduce_mask_25; c = (word32)(a >> 25); + a = mul32x32_64(in[2], scalar) + c; out[2] = (word32)a & reduce_mask_26; c = (word32)(a >> 26); + a = mul32x32_64(in[3], scalar) + c; out[3] = (word32)a & reduce_mask_25; c = (word32)(a >> 25); + a = mul32x32_64(in[4], scalar) + c; out[4] = (word32)a & reduce_mask_26; c = (word32)(a >> 26); + a = mul32x32_64(in[5], scalar) + c; out[5] = (word32)a & reduce_mask_25; c = (word32)(a >> 25); + a = mul32x32_64(in[6], scalar) + c; out[6] = (word32)a & reduce_mask_26; c = (word32)(a >> 26); + a = mul32x32_64(in[7], scalar) + c; out[7] = (word32)a & reduce_mask_25; c = (word32)(a >> 25); + a = mul32x32_64(in[8], scalar) + c; out[8] = (word32)a & reduce_mask_26; c = (word32)(a >> 26); + a = mul32x32_64(in[9], scalar) + c; out[9] = (word32)a & reduce_mask_25; c = (word32)(a >> 25); + out[0] += c * 19; +} + +/* out = a * b */ +inline void +curve25519_mul(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word32 r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; + word32 s0,s1,s2,s3,s4,s5,s6,s7,s8,s9; + word64 m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c; + word32 p; + + r0 = b[0]; r1 = b[1]; r2 = b[2]; r3 = b[3]; r4 = b[4]; + r5 = b[5]; r6 = b[6]; r7 = b[7]; r8 = b[8]; r9 = b[9]; + + s0 = a[0]; s1 = a[1]; s2 = a[2]; s3 = a[3]; s4 = a[4]; + s5 = a[5]; s6 = a[6]; s7 = a[7]; s8 = a[8]; s9 = a[9]; + + m1 = mul32x32_64(r0, s1) + mul32x32_64(r1, s0); + m3 = mul32x32_64(r0, s3) + mul32x32_64(r1, s2) + mul32x32_64(r2, s1) + mul32x32_64(r3, s0); + m5 = mul32x32_64(r0, s5) + mul32x32_64(r1, s4) + mul32x32_64(r2, s3) + mul32x32_64(r3, s2) + mul32x32_64(r4, s1) + mul32x32_64(r5, s0); + m7 = mul32x32_64(r0, s7) + mul32x32_64(r1, s6) + mul32x32_64(r2, s5) + mul32x32_64(r3, s4) + mul32x32_64(r4, s3) + mul32x32_64(r5, s2) + mul32x32_64(r6, s1) + mul32x32_64(r7, s0); + m9 = mul32x32_64(r0, s9) + mul32x32_64(r1, s8) + mul32x32_64(r2, s7) + mul32x32_64(r3, s6) + mul32x32_64(r4, s5) + mul32x32_64(r5, s4) + mul32x32_64(r6, s3) + mul32x32_64(r7, s2) + mul32x32_64(r8, s1) + mul32x32_64(r9, s0); + + r1 *= 2; r3 *= 2; r5 *= 2; r7 *= 2; + + m0 = mul32x32_64(r0, s0); + m2 = mul32x32_64(r0, s2) + mul32x32_64(r1, s1) + mul32x32_64(r2, s0); + m4 = mul32x32_64(r0, s4) + mul32x32_64(r1, s3) + mul32x32_64(r2, s2) + mul32x32_64(r3, s1) + mul32x32_64(r4, s0); + m6 = mul32x32_64(r0, s6) + mul32x32_64(r1, s5) + mul32x32_64(r2, s4) + mul32x32_64(r3, s3) + mul32x32_64(r4, s2) + mul32x32_64(r5, s1) + mul32x32_64(r6, s0); + m8 = mul32x32_64(r0, s8) + mul32x32_64(r1, s7) + mul32x32_64(r2, s6) + mul32x32_64(r3, s5) + mul32x32_64(r4, s4) + mul32x32_64(r5, s3) + mul32x32_64(r6, s2) + mul32x32_64(r7, s1) + mul32x32_64(r8, s0); + + r1 *= 19; r2 *= 19; + r3 = (r3 / 2) * 19; + r4 *= 19; + r5 = (r5 / 2) * 19; + r6 *= 19; + r7 = (r7 / 2) * 19; + r8 *= 19; r9 *= 19; + + m1 += (mul32x32_64(r9, s2) + mul32x32_64(r8, s3) + mul32x32_64(r7, s4) + mul32x32_64(r6, s5) + mul32x32_64(r5, s6) + mul32x32_64(r4, s7) + mul32x32_64(r3, s8) + mul32x32_64(r2, s9)); + m3 += (mul32x32_64(r9, s4) + mul32x32_64(r8, s5) + mul32x32_64(r7, s6) + mul32x32_64(r6, s7) + mul32x32_64(r5, s8) + mul32x32_64(r4, s9)); + m5 += (mul32x32_64(r9, s6) + mul32x32_64(r8, s7) + mul32x32_64(r7, s8) + mul32x32_64(r6, s9)); + m7 += (mul32x32_64(r9, s8) + mul32x32_64(r8, s9)); + + r3 *= 2; r5 *= 2; r7 *= 2; r9 *= 2; + + m0 += (mul32x32_64(r9, s1) + mul32x32_64(r8, s2) + mul32x32_64(r7, s3) + mul32x32_64(r6, s4) + mul32x32_64(r5, s5) + mul32x32_64(r4, s6) + mul32x32_64(r3, s7) + mul32x32_64(r2, s8) + mul32x32_64(r1, s9)); + m2 += (mul32x32_64(r9, s3) + mul32x32_64(r8, s4) + mul32x32_64(r7, s5) + mul32x32_64(r6, s6) + mul32x32_64(r5, s7) + mul32x32_64(r4, s8) + mul32x32_64(r3, s9)); + m4 += (mul32x32_64(r9, s5) + mul32x32_64(r8, s6) + mul32x32_64(r7, s7) + mul32x32_64(r6, s8) + mul32x32_64(r5, s9)); + m6 += (mul32x32_64(r9, s7) + mul32x32_64(r8, s8) + mul32x32_64(r7, s9)); + m8 += (mul32x32_64(r9, s9)); + + r0 = (word32)m0 & reduce_mask_26; c = (m0 >> 26); + m1 += c; r1 = (word32)m1 & reduce_mask_25; c = (m1 >> 25); + m2 += c; r2 = (word32)m2 & reduce_mask_26; c = (m2 >> 26); + m3 += c; r3 = (word32)m3 & reduce_mask_25; c = (m3 >> 25); + m4 += c; r4 = (word32)m4 & reduce_mask_26; c = (m4 >> 26); + m5 += c; r5 = (word32)m5 & reduce_mask_25; c = (m5 >> 25); + m6 += c; r6 = (word32)m6 & reduce_mask_26; c = (m6 >> 26); + m7 += c; r7 = (word32)m7 & reduce_mask_25; c = (m7 >> 25); + m8 += c; r8 = (word32)m8 & reduce_mask_26; c = (m8 >> 26); + m9 += c; r9 = (word32)m9 & reduce_mask_25; p = (word32)(m9 >> 25); + m0 = r0 + mul32x32_64(p,19); r0 = (word32)m0 & reduce_mask_26; p = (word32)(m0 >> 26); + r1 += p; + + out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4; + out[5] = r5; out[6] = r6; out[7] = r7; out[8] = r8; out[9] = r9; +} + +/* out = in * in */ +inline void +curve25519_square(bignum25519 out, const bignum25519 in) { + word32 r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; + word32 d6,d7,d8,d9; + word64 m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c; + word32 p; + + r0 = in[0]; r1 = in[1]; r2 = in[2]; r3 = in[3]; r4 = in[4]; + r5 = in[5]; r6 = in[6]; r7 = in[7]; r8 = in[8]; r9 = in[9]; + + m0 = mul32x32_64(r0, r0); + r0 *= 2; + m1 = mul32x32_64(r0, r1); + m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2); + r1 *= 2; + m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2 ); + m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2); + r2 *= 2; + m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4 ) + mul32x32_64(r2, r3); + m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) + mul32x32_64(r3, r3 * 2); + r3 *= 2; + m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6 ) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4 ); + m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) + mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4 ); + m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8 ) + mul32x32_64(r2, r7) + mul32x32_64(r3, r6 ) + mul32x32_64(r4, r5 * 2); + + d6 = r6 * 19; d7 = r7 * 2 * 19; + d8 = r8 * 19; d9 = r9 * 2 * 19; + + m0 += (mul32x32_64(d9, r1 ) + mul32x32_64(d8, r2 ) + mul32x32_64(d7, r3 ) + mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19)); + m1 += (mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3 ) + mul32x32_64(d7, r4 ) + mul32x32_64(d6, r5 * 2)); + m2 += (mul32x32_64(d9, r3 ) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) + mul32x32_64(d6, r6 )); + m3 += (mul32x32_64(d9, r4 ) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6 )); + m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7 )); + m5 += (mul32x32_64(d9, r6 ) + mul32x32_64(d8, r7 * 2)); + m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8 )); + m7 += (mul32x32_64(d9, r8 )); + m8 += (mul32x32_64(d9, r9 )); + + r0 = (word32)m0 & reduce_mask_26; c = (m0 >> 26); + m1 += c; r1 = (word32)m1 & reduce_mask_25; c = (m1 >> 25); + m2 += c; r2 = (word32)m2 & reduce_mask_26; c = (m2 >> 26); + m3 += c; r3 = (word32)m3 & reduce_mask_25; c = (m3 >> 25); + m4 += c; r4 = (word32)m4 & reduce_mask_26; c = (m4 >> 26); + m5 += c; r5 = (word32)m5 & reduce_mask_25; c = (m5 >> 25); + m6 += c; r6 = (word32)m6 & reduce_mask_26; c = (m6 >> 26); + m7 += c; r7 = (word32)m7 & reduce_mask_25; c = (m7 >> 25); + m8 += c; r8 = (word32)m8 & reduce_mask_26; c = (m8 >> 26); + m9 += c; r9 = (word32)m9 & reduce_mask_25; p = (word32)(m9 >> 25); + m0 = r0 + mul32x32_64(p,19); r0 = (word32)m0 & reduce_mask_26; p = (word32)(m0 >> 26); + r1 += p; + + out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4; + out[5] = r5; out[6] = r6; out[7] = r7; out[8] = r8; out[9] = r9; +} + +/* out = in^(2 * count) */ +void +curve25519_square_times(bignum25519 out, const bignum25519 in, int count) { + word32 r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; + word32 d6,d7,d8,d9; + word64 m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c; + word32 p; + + r0 = in[0]; r1 = in[1]; r2 = in[2]; r3 = in[3]; r4 = in[4]; + r5 = in[5]; r6 = in[6]; r7 = in[7]; r8 = in[8]; r9 = in[9]; + + do { + m0 = mul32x32_64(r0, r0); + r0 *= 2; + m1 = mul32x32_64(r0, r1); + m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2); + r1 *= 2; + m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2 ); + m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2); + r2 *= 2; + m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4 ) + mul32x32_64(r2, r3); + m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) + mul32x32_64(r3, r3 * 2); + r3 *= 2; + m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6 ) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4 ); + m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) + mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4 ); + m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8 ) + mul32x32_64(r2, r7) + mul32x32_64(r3, r6 ) + mul32x32_64(r4, r5 * 2); + + d6 = r6 * 19; d7 = r7 * 2 * 19; + d8 = r8 * 19; d9 = r9 * 2 * 19; + + m0 += (mul32x32_64(d9, r1 ) + mul32x32_64(d8, r2 ) + mul32x32_64(d7, r3 ) + mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19)); + m1 += (mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3 ) + mul32x32_64(d7, r4 ) + mul32x32_64(d6, r5 * 2)); + m2 += (mul32x32_64(d9, r3 ) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) + mul32x32_64(d6, r6 )); + m3 += (mul32x32_64(d9, r4 ) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6 )); + m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7 )); + m5 += (mul32x32_64(d9, r6 ) + mul32x32_64(d8, r7 * 2)); + m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8 )); + m7 += (mul32x32_64(d9, r8 )); + m8 += (mul32x32_64(d9, r9 )); + + r0 = (word32)m0 & reduce_mask_26; c = (m0 >> 26); + m1 += c; r1 = (word32)m1 & reduce_mask_25; c = (m1 >> 25); + m2 += c; r2 = (word32)m2 & reduce_mask_26; c = (m2 >> 26); + m3 += c; r3 = (word32)m3 & reduce_mask_25; c = (m3 >> 25); + m4 += c; r4 = (word32)m4 & reduce_mask_26; c = (m4 >> 26); + m5 += c; r5 = (word32)m5 & reduce_mask_25; c = (m5 >> 25); + m6 += c; r6 = (word32)m6 & reduce_mask_26; c = (m6 >> 26); + m7 += c; r7 = (word32)m7 & reduce_mask_25; c = (m7 >> 25); + m8 += c; r8 = (word32)m8 & reduce_mask_26; c = (m8 >> 26); + m9 += c; r9 = (word32)m9 & reduce_mask_25; p = (word32)(m9 >> 25); + m0 = r0 + mul32x32_64(p,19); r0 = (word32)m0 & reduce_mask_26; p = (word32)(m0 >> 26); + r1 += p; + } while (--count); + + out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4; + out[5] = r5; out[6] = r6; out[7] = r7; out[8] = r8; out[9] = r9; +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +void +curve25519_expand(bignum25519 out, const byte in[32]) { + word32 x0,x1,x2,x3,x4,x5,x6,x7; + GetBlock block(in); + block(x0)(x1)(x2)(x3)(x4)(x5)(x6)(x7); + + out[0] = ( x0 ) & reduce_mask_26; + out[1] = ((((word64)x1 << 32) | x0) >> 26) & reduce_mask_25; + out[2] = ((((word64)x2 << 32) | x1) >> 19) & reduce_mask_26; + out[3] = ((((word64)x3 << 32) | x2) >> 13) & reduce_mask_25; + out[4] = (( x3) >> 6) & reduce_mask_26; + out[5] = ( x4 ) & reduce_mask_25; + out[6] = ((((word64)x5 << 32) | x4) >> 25) & reduce_mask_26; + out[7] = ((((word64)x6 << 32) | x5) >> 19) & reduce_mask_25; + out[8] = ((((word64)x7 << 32) | x6) >> 12) & reduce_mask_26; + out[9] = (( x7) >> 6) & reduce_mask_25; /* ignore the top bit */ +} + +/* Take a fully reduced polynomial form number and contract it into a little-endian, 32-byte array */ +void +curve25519_contract(byte out[32], const bignum25519 in) { + bignum25519 f; + curve25519_copy(f, in); + + #define carry_pass() \ + f[1] += f[0] >> 26; f[0] &= reduce_mask_26; \ + f[2] += f[1] >> 25; f[1] &= reduce_mask_25; \ + f[3] += f[2] >> 26; f[2] &= reduce_mask_26; \ + f[4] += f[3] >> 25; f[3] &= reduce_mask_25; \ + f[5] += f[4] >> 26; f[4] &= reduce_mask_26; \ + f[6] += f[5] >> 25; f[5] &= reduce_mask_25; \ + f[7] += f[6] >> 26; f[6] &= reduce_mask_26; \ + f[8] += f[7] >> 25; f[7] &= reduce_mask_25; \ + f[9] += f[8] >> 26; f[8] &= reduce_mask_26; + + #define carry_pass_full() \ + carry_pass() \ + f[0] += 19 * (f[9] >> 25); f[9] &= reduce_mask_25; + + #define carry_pass_final() \ + carry_pass() \ + f[9] &= reduce_mask_25; + + carry_pass_full() + carry_pass_full() + + /* now t is between 0 and 2^255-1, properly carried. */ + /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ + f[0] += 19; + carry_pass_full() + + /* now between 19 and 2^255-1 in both cases, and offset by 19. */ + f[0] += (1 << 26) - 19; + f[1] += (1 << 25) - 1; + f[2] += (1 << 26) - 1; + f[3] += (1 << 25) - 1; + f[4] += (1 << 26) - 1; + f[5] += (1 << 25) - 1; + f[6] += (1 << 26) - 1; + f[7] += (1 << 25) - 1; + f[8] += (1 << 26) - 1; + f[9] += (1 << 25) - 1; + + /* now between 2^255 and 2^256-20, and offset by 2^255. */ + carry_pass_final() + + #undef carry_pass + #undef carry_full + #undef carry_final + + f[1] <<= 2; + f[2] <<= 3; + f[3] <<= 5; + f[4] <<= 6; + f[6] <<= 1; + f[7] <<= 3; + f[8] <<= 4; + f[9] <<= 6; + + #define F(i, s) \ + out[s+0] |= (byte)( f[i] & 0xff); \ + out[s+1] = (byte)((f[i] >> 8) & 0xff); \ + out[s+2] = (byte)((f[i] >> 16) & 0xff); \ + out[s+3] = (byte)((f[i] >> 24) & 0xff); + + out[0] = out[16] = 0; + F(0,0); F(1,3); + F(2,6); F(3,9); + F(4,12); F(5,16); + F(6,19); F(7,22); + F(8,25); F(9,28); + #undef F +} + +inline void +curve25519_swap_conditional(bignum25519 x, bignum25519 qpx, word32 iswap) { + const word32 swap = (word32)(-(sword32)iswap); + word32 x0,x1,x2,x3,x4,x5,x6,x7,x8,x9; + + x0 = swap & (x[0] ^ qpx[0]); x[0] ^= x0; qpx[0] ^= x0; + x1 = swap & (x[1] ^ qpx[1]); x[1] ^= x1; qpx[1] ^= x1; + x2 = swap & (x[2] ^ qpx[2]); x[2] ^= x2; qpx[2] ^= x2; + x3 = swap & (x[3] ^ qpx[3]); x[3] ^= x3; qpx[3] ^= x3; + x4 = swap & (x[4] ^ qpx[4]); x[4] ^= x4; qpx[4] ^= x4; + x5 = swap & (x[5] ^ qpx[5]); x[5] ^= x5; qpx[5] ^= x5; + x6 = swap & (x[6] ^ qpx[6]); x[6] ^= x6; qpx[6] ^= x6; + x7 = swap & (x[7] ^ qpx[7]); x[7] ^= x7; qpx[7] ^= x7; + x8 = swap & (x[8] ^ qpx[8]); x[8] ^= x8; qpx[8] ^= x8; + x9 = swap & (x[9] ^ qpx[9]); x[9] ^= x9; qpx[9] ^= x9; +} + +/* + * In: b = 2^5 - 2^0 + * Out: b = 2^250 - 2^0 + */ +void +curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) { + ALIGN(ALIGN_SPEC) bignum25519 t0,c; + + /* 2^5 - 2^0 */ /* b */ + /* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5); + /* 2^10 - 2^0 */ curve25519_mul(b, t0, b); + /* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10); + /* 2^20 - 2^0 */ curve25519_mul(c, t0, b); + /* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20); + /* 2^40 - 2^0 */ curve25519_mul(t0, t0, c); + /* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10); + /* 2^50 - 2^0 */ curve25519_mul(b, t0, b); + /* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50); + /* 2^100 - 2^0 */ curve25519_mul(c, t0, b); + /* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100); + /* 2^200 - 2^0 */ curve25519_mul(t0, t0, c); + /* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50); + /* 2^250 - 2^0 */ curve25519_mul(b, t0, b); +} + +/* + * z^(p - 2) = z(2^255 - 21) + */ +void +curve25519_recip(bignum25519 out, const bignum25519 z) { + ALIGN(ALIGN_SPEC) bignum25519 a, t0, b; + + /* 2 */ curve25519_square(a, z); /* a = 2 */ + /* 8 */ curve25519_square_times(t0, a, 2); + /* 9 */ curve25519_mul(b, t0, z); /* b = 9 */ + /* 11 */ curve25519_mul(a, b, a); /* a = 11 */ + /* 22 */ curve25519_square(t0, a); + /* 2^5 - 2^0 = 31 */ curve25519_mul(b, t0, b); + /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b); + /* 2^255 - 2^5 */ curve25519_square_times(b, b, 5); + /* 2^255 - 21 */ curve25519_mul(out, b, a); +} + +ANONYMOUS_NAMESPACE_END +NAMESPACE_END // X25519 +NAMESPACE_END // Donna +NAMESPACE_END // CryptoPP + +//******************************* ed25519 *******************************// + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Donna) +NAMESPACE_BEGIN(Ed25519) +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::sword32; +using CryptoPP::word64; +using CryptoPP::sword64; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; + +using CryptoPP::SHA512; + +// Bring in all the symbols from the 32-bit header +using namespace CryptoPP::Donna::Arch32; + +/* out = in */ +inline void +curve25519_copy(bignum25519 out, const bignum25519 in) { + out[0] = in[0]; out[1] = in[1]; + out[2] = in[2]; out[3] = in[3]; + out[4] = in[4]; out[5] = in[5]; + out[6] = in[6]; out[7] = in[7]; + out[8] = in[8]; out[9] = in[9]; +} + +/* out = a + b */ +inline void +curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) { + out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; + out[4] = a[4] + b[4]; out[5] = a[5] + b[5]; + out[6] = a[6] + b[6]; out[7] = a[7] + b[7]; + out[8] = a[8] + b[8]; out[9] = a[9] + b[9]; +} + +inline void +curve25519_add_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word32 c; + out[0] = a[0] + b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; + out[1] = a[1] + b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; + out[2] = a[2] + b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; + out[3] = a[3] + b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; + out[4] = a[4] + b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; + out[5] = a[5] + b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; + out[6] = a[6] + b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; + out[7] = a[7] + b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; + out[8] = a[8] + b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; + out[9] = a[9] + b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; + out[0] += 19 * c; +} + +inline void +curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word32 c; + out[0] = a[0] + b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; + out[1] = a[1] + b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; + out[2] = a[2] + b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; + out[3] = a[3] + b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; + out[4] = a[4] + b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; + out[5] = a[5] + b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; + out[6] = a[6] + b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; + out[7] = a[7] + b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; + out[8] = a[8] + b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; + out[9] = a[9] + b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; + out[0] += 19 * c; +} + +/* out = a - b */ +inline void +curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word32 c; + out[0] = twoP0 + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; + out[1] = twoP13579 + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; + out[2] = twoP2468 + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; + out[3] = twoP13579 + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; + out[4] = twoP2468 + a[4] - b[4] + c; + out[5] = twoP13579 + a[5] - b[5] ; + out[6] = twoP2468 + a[6] - b[6] ; + out[7] = twoP13579 + a[7] - b[7] ; + out[8] = twoP2468 + a[8] - b[8] ; + out[9] = twoP13579 + a[9] - b[9] ; +} + +/* out = a - b, where a is the result of a basic op (add,sub) */ +inline void +curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word32 c; + out[0] = fourP0 + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; + out[1] = fourP13579 + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; + out[2] = fourP2468 + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; + out[3] = fourP13579 + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; + out[4] = fourP2468 + a[4] - b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; + out[5] = fourP13579 + a[5] - b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; + out[6] = fourP2468 + a[6] - b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; + out[7] = fourP13579 + a[7] - b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; + out[8] = fourP2468 + a[8] - b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; + out[9] = fourP13579 + a[9] - b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; + out[0] += 19 * c; +} + +inline void +curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word32 c; + out[0] = fourP0 + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; + out[1] = fourP13579 + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; + out[2] = fourP2468 + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; + out[3] = fourP13579 + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; + out[4] = fourP2468 + a[4] - b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; + out[5] = fourP13579 + a[5] - b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; + out[6] = fourP2468 + a[6] - b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; + out[7] = fourP13579 + a[7] - b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; + out[8] = fourP2468 + a[8] - b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; + out[9] = fourP13579 + a[9] - b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; + out[0] += 19 * c; +} + +/* out = -a */ +inline void +curve25519_neg(bignum25519 out, const bignum25519 a) { + word32 c; + out[0] = twoP0 - a[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; + out[1] = twoP13579 - a[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; + out[2] = twoP2468 - a[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; + out[3] = twoP13579 - a[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; + out[4] = twoP2468 - a[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; + out[5] = twoP13579 - a[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; + out[6] = twoP2468 - a[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; + out[7] = twoP13579 - a[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; + out[8] = twoP2468 - a[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; + out[9] = twoP13579 - a[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; + out[0] += 19 * c; +} + +/* out = a * b */ +void +curve25519_mul(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word32 r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; + word32 s0,s1,s2,s3,s4,s5,s6,s7,s8,s9; + word64 m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c; + word32 p; + + r0 = b[0]; r1 = b[1]; + r2 = b[2]; r3 = b[3]; + r4 = b[4]; r5 = b[5]; + r6 = b[6]; r7 = b[7]; + r8 = b[8]; r9 = b[9]; + + s0 = a[0]; s1 = a[1]; + s2 = a[2]; s3 = a[3]; + s4 = a[4]; s5 = a[5]; + s6 = a[6]; s7 = a[7]; + s8 = a[8]; s9 = a[9]; + + m1 = mul32x32_64(r0, s1) + mul32x32_64(r1, s0); + m3 = mul32x32_64(r0, s3) + mul32x32_64(r1, s2) + mul32x32_64(r2, s1) + mul32x32_64(r3, s0); + m5 = mul32x32_64(r0, s5) + mul32x32_64(r1, s4) + mul32x32_64(r2, s3) + mul32x32_64(r3, s2) + mul32x32_64(r4, s1) + mul32x32_64(r5, s0); + m7 = mul32x32_64(r0, s7) + mul32x32_64(r1, s6) + mul32x32_64(r2, s5) + mul32x32_64(r3, s4) + mul32x32_64(r4, s3) + mul32x32_64(r5, s2) + mul32x32_64(r6, s1) + mul32x32_64(r7, s0); + m9 = mul32x32_64(r0, s9) + mul32x32_64(r1, s8) + mul32x32_64(r2, s7) + mul32x32_64(r3, s6) + mul32x32_64(r4, s5) + mul32x32_64(r5, s4) + mul32x32_64(r6, s3) + mul32x32_64(r7, s2) + mul32x32_64(r8, s1) + mul32x32_64(r9, s0); + + r1 *= 2; r3 *= 2; + r5 *= 2; r7 *= 2; + + m0 = mul32x32_64(r0, s0); + m2 = mul32x32_64(r0, s2) + mul32x32_64(r1, s1) + mul32x32_64(r2, s0); + m4 = mul32x32_64(r0, s4) + mul32x32_64(r1, s3) + mul32x32_64(r2, s2) + mul32x32_64(r3, s1) + mul32x32_64(r4, s0); + m6 = mul32x32_64(r0, s6) + mul32x32_64(r1, s5) + mul32x32_64(r2, s4) + mul32x32_64(r3, s3) + mul32x32_64(r4, s2) + mul32x32_64(r5, s1) + mul32x32_64(r6, s0); + m8 = mul32x32_64(r0, s8) + mul32x32_64(r1, s7) + mul32x32_64(r2, s6) + mul32x32_64(r3, s5) + mul32x32_64(r4, s4) + mul32x32_64(r5, s3) + mul32x32_64(r6, s2) + mul32x32_64(r7, s1) + mul32x32_64(r8, s0); + + r1 *= 19; r2 *= 19; + r3 = (r3 / 2) * 19; + r4 *= 19; + r5 = (r5 / 2) * 19; + r6 *= 19; + r7 = (r7 / 2) * 19; + r8 *= 19; r9 *= 19; + + m1 += (mul32x32_64(r9, s2) + mul32x32_64(r8, s3) + mul32x32_64(r7, s4) + mul32x32_64(r6, s5) + mul32x32_64(r5, s6) + mul32x32_64(r4, s7) + mul32x32_64(r3, s8) + mul32x32_64(r2, s9)); + m3 += (mul32x32_64(r9, s4) + mul32x32_64(r8, s5) + mul32x32_64(r7, s6) + mul32x32_64(r6, s7) + mul32x32_64(r5, s8) + mul32x32_64(r4, s9)); + m5 += (mul32x32_64(r9, s6) + mul32x32_64(r8, s7) + mul32x32_64(r7, s8) + mul32x32_64(r6, s9)); + m7 += (mul32x32_64(r9, s8) + mul32x32_64(r8, s9)); + + r3 *= 2; r5 *= 2; + r7 *= 2; r9 *= 2; + + m0 += (mul32x32_64(r9, s1) + mul32x32_64(r8, s2) + mul32x32_64(r7, s3) + mul32x32_64(r6, s4) + mul32x32_64(r5, s5) + mul32x32_64(r4, s6) + mul32x32_64(r3, s7) + mul32x32_64(r2, s8) + mul32x32_64(r1, s9)); + m2 += (mul32x32_64(r9, s3) + mul32x32_64(r8, s4) + mul32x32_64(r7, s5) + mul32x32_64(r6, s6) + mul32x32_64(r5, s7) + mul32x32_64(r4, s8) + mul32x32_64(r3, s9)); + m4 += (mul32x32_64(r9, s5) + mul32x32_64(r8, s6) + mul32x32_64(r7, s7) + mul32x32_64(r6, s8) + mul32x32_64(r5, s9)); + m6 += (mul32x32_64(r9, s7) + mul32x32_64(r8, s8) + mul32x32_64(r7, s9)); + m8 += (mul32x32_64(r9, s9)); + + r0 = (word32)m0 & reduce_mask_26; c = (m0 >> 26); + m1 += c; r1 = (word32)m1 & reduce_mask_25; c = (m1 >> 25); + m2 += c; r2 = (word32)m2 & reduce_mask_26; c = (m2 >> 26); + m3 += c; r3 = (word32)m3 & reduce_mask_25; c = (m3 >> 25); + m4 += c; r4 = (word32)m4 & reduce_mask_26; c = (m4 >> 26); + m5 += c; r5 = (word32)m5 & reduce_mask_25; c = (m5 >> 25); + m6 += c; r6 = (word32)m6 & reduce_mask_26; c = (m6 >> 26); + m7 += c; r7 = (word32)m7 & reduce_mask_25; c = (m7 >> 25); + m8 += c; r8 = (word32)m8 & reduce_mask_26; c = (m8 >> 26); + m9 += c; r9 = (word32)m9 & reduce_mask_25; p = (word32)(m9 >> 25); + m0 = r0 + mul32x32_64(p,19); r0 = (word32)m0 & reduce_mask_26; p = (word32)(m0 >> 26); + r1 += p; + + out[0] = r0; out[1] = r1; + out[2] = r2; out[3] = r3; + out[4] = r4; out[5] = r5; + out[6] = r6; out[7] = r7; + out[8] = r8; out[9] = r9; +} + +/* out = in*in */ +void +curve25519_square(bignum25519 out, const bignum25519 in) { + word32 r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; + word32 d6,d7,d8,d9; + word64 m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c; + word32 p; + + r0 = in[0]; r1 = in[1]; + r2 = in[2]; r3 = in[3]; + r4 = in[4]; r5 = in[5]; + r6 = in[6]; r7 = in[7]; + r8 = in[8]; r9 = in[9]; + + m0 = mul32x32_64(r0, r0); + r0 *= 2; + m1 = mul32x32_64(r0, r1); + m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2); + r1 *= 2; + m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2 ); + m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2); + r2 *= 2; + m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4 ) + mul32x32_64(r2, r3); + m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) + mul32x32_64(r3, r3 * 2); + r3 *= 2; + m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6 ) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4 ); + m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) + mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4 ); + m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8 ) + mul32x32_64(r2, r7) + mul32x32_64(r3, r6 ) + mul32x32_64(r4, r5 * 2); + + d6 = r6 * 19; + d7 = r7 * 2 * 19; + d8 = r8 * 19; + d9 = r9 * 2 * 19; + + m0 += (mul32x32_64(d9, r1 ) + mul32x32_64(d8, r2 ) + mul32x32_64(d7, r3 ) + mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19)); + m1 += (mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3 ) + mul32x32_64(d7, r4 ) + mul32x32_64(d6, r5 * 2)); + m2 += (mul32x32_64(d9, r3 ) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) + mul32x32_64(d6, r6 )); + m3 += (mul32x32_64(d9, r4 ) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6 )); + m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7 )); + m5 += (mul32x32_64(d9, r6 ) + mul32x32_64(d8, r7 * 2)); + m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8 )); + m7 += (mul32x32_64(d9, r8 )); + m8 += (mul32x32_64(d9, r9 )); + + r0 = (word32)m0 & reduce_mask_26; c = (m0 >> 26); + m1 += c; r1 = (word32)m1 & reduce_mask_25; c = (m1 >> 25); + m2 += c; r2 = (word32)m2 & reduce_mask_26; c = (m2 >> 26); + m3 += c; r3 = (word32)m3 & reduce_mask_25; c = (m3 >> 25); + m4 += c; r4 = (word32)m4 & reduce_mask_26; c = (m4 >> 26); + m5 += c; r5 = (word32)m5 & reduce_mask_25; c = (m5 >> 25); + m6 += c; r6 = (word32)m6 & reduce_mask_26; c = (m6 >> 26); + m7 += c; r7 = (word32)m7 & reduce_mask_25; c = (m7 >> 25); + m8 += c; r8 = (word32)m8 & reduce_mask_26; c = (m8 >> 26); + m9 += c; r9 = (word32)m9 & reduce_mask_25; p = (word32)(m9 >> 25); + m0 = r0 + mul32x32_64(p,19); r0 = (word32)m0 & reduce_mask_26; p = (word32)(m0 >> 26); + r1 += p; + + out[0] = r0; out[1] = r1; + out[2] = r2; out[3] = r3; + out[4] = r4; out[5] = r5; + out[6] = r6; out[7] = r7; + out[8] = r8; out[9] = r9; +} + +/* out = in ^ (2 * count) */ +void +curve25519_square_times(bignum25519 out, const bignum25519 in, int count) { + word32 r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; + word32 d6,d7,d8,d9,p; + word64 m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c; + + r0 = in[0]; r1 = in[1]; + r2 = in[2]; r3 = in[3]; + r4 = in[4]; r5 = in[5]; + r6 = in[6]; r7 = in[7]; + r8 = in[8]; r9 = in[9]; + + do { + m0 = mul32x32_64(r0, r0); + r0 *= 2; + m1 = mul32x32_64(r0, r1); + m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2); + r1 *= 2; + m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2 ); + m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2); + r2 *= 2; + m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4 ) + mul32x32_64(r2, r3); + m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) + mul32x32_64(r3, r3 * 2); + r3 *= 2; + m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6 ) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4 ); + m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) + mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4 ); + m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8 ) + mul32x32_64(r2, r7) + mul32x32_64(r3, r6 ) + mul32x32_64(r4, r5 * 2); + + d6 = r6 * 19; + d7 = r7 * 2 * 19; + d8 = r8 * 19; + d9 = r9 * 2 * 19; + + m0 += (mul32x32_64(d9, r1 ) + mul32x32_64(d8, r2 ) + mul32x32_64(d7, r3 ) + mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19)); + m1 += (mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3 ) + mul32x32_64(d7, r4 ) + mul32x32_64(d6, r5 * 2)); + m2 += (mul32x32_64(d9, r3 ) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) + mul32x32_64(d6, r6 )); + m3 += (mul32x32_64(d9, r4 ) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6 )); + m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7 )); + m5 += (mul32x32_64(d9, r6 ) + mul32x32_64(d8, r7 * 2)); + m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8 )); + m7 += (mul32x32_64(d9, r8 )); + m8 += (mul32x32_64(d9, r9 )); + + r0 = (word32)m0 & reduce_mask_26; c = (m0 >> 26); + m1 += c; r1 = (word32)m1 & reduce_mask_25; c = (m1 >> 25); + m2 += c; r2 = (word32)m2 & reduce_mask_26; c = (m2 >> 26); + m3 += c; r3 = (word32)m3 & reduce_mask_25; c = (m3 >> 25); + m4 += c; r4 = (word32)m4 & reduce_mask_26; c = (m4 >> 26); + m5 += c; r5 = (word32)m5 & reduce_mask_25; c = (m5 >> 25); + m6 += c; r6 = (word32)m6 & reduce_mask_26; c = (m6 >> 26); + m7 += c; r7 = (word32)m7 & reduce_mask_25; c = (m7 >> 25); + m8 += c; r8 = (word32)m8 & reduce_mask_26; c = (m8 >> 26); + m9 += c; r9 = (word32)m9 & reduce_mask_25; p = (word32)(m9 >> 25); + m0 = r0 + mul32x32_64(p,19); r0 = (word32)m0 & reduce_mask_26; p = (word32)(m0 >> 26); + r1 += p; + } while (--count); + + out[0] = r0; out[1] = r1; + out[2] = r2; out[3] = r3; + out[4] = r4; out[5] = r5; + out[6] = r6; out[7] = r7; + out[8] = r8; out[9] = r9; +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +void +curve25519_expand(bignum25519 out, const byte in[32]) { + word32 x0,x1,x2,x3,x4,x5,x6,x7; + GetBlock block(in); + block(x0)(x1)(x2)(x3)(x4)(x5)(x6)(x7); + + out[0] = ( x0 ) & 0x3ffffff; + out[1] = ((((word64)x1 << 32) | x0) >> 26) & 0x1ffffff; + out[2] = ((((word64)x2 << 32) | x1) >> 19) & 0x3ffffff; + out[3] = ((((word64)x3 << 32) | x2) >> 13) & 0x1ffffff; + out[4] = (( x3) >> 6) & 0x3ffffff; + out[5] = ( x4 ) & 0x1ffffff; + out[6] = ((((word64)x5 << 32) | x4) >> 25) & 0x3ffffff; + out[7] = ((((word64)x6 << 32) | x5) >> 19) & 0x1ffffff; + out[8] = ((((word64)x7 << 32) | x6) >> 12) & 0x3ffffff; + out[9] = (( x7) >> 6) & 0x1ffffff; +} + +/* Take a fully reduced polynomial form number and contract it into a + * little-endian, 32-byte array + */ +void +curve25519_contract(byte out[32], const bignum25519 in) { + bignum25519 f; + curve25519_copy(f, in); + + #define carry_pass() \ + f[1] += f[0] >> 26; f[0] &= reduce_mask_26; \ + f[2] += f[1] >> 25; f[1] &= reduce_mask_25; \ + f[3] += f[2] >> 26; f[2] &= reduce_mask_26; \ + f[4] += f[3] >> 25; f[3] &= reduce_mask_25; \ + f[5] += f[4] >> 26; f[4] &= reduce_mask_26; \ + f[6] += f[5] >> 25; f[5] &= reduce_mask_25; \ + f[7] += f[6] >> 26; f[6] &= reduce_mask_26; \ + f[8] += f[7] >> 25; f[7] &= reduce_mask_25; \ + f[9] += f[8] >> 26; f[8] &= reduce_mask_26; + + #define carry_pass_full() \ + carry_pass() \ + f[0] += 19 * (f[9] >> 25); f[9] &= reduce_mask_25; + + #define carry_pass_final() \ + carry_pass() \ + f[9] &= reduce_mask_25; + + carry_pass_full() + carry_pass_full() + + /* now t is between 0 and 2^255-1, properly carried. */ + /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ + f[0] += 19; + carry_pass_full() + + /* now between 19 and 2^255-1 in both cases, and offset by 19. */ + f[0] += (reduce_mask_26 + 1) - 19; + f[1] += (reduce_mask_25 + 1) - 1; + f[2] += (reduce_mask_26 + 1) - 1; + f[3] += (reduce_mask_25 + 1) - 1; + f[4] += (reduce_mask_26 + 1) - 1; + f[5] += (reduce_mask_25 + 1) - 1; + f[6] += (reduce_mask_26 + 1) - 1; + f[7] += (reduce_mask_25 + 1) - 1; + f[8] += (reduce_mask_26 + 1) - 1; + f[9] += (reduce_mask_25 + 1) - 1; + + /* now between 2^255 and 2^256-20, and offset by 2^255. */ + carry_pass_final() + + #undef carry_pass + #undef carry_full + #undef carry_final + + f[1] <<= 2; f[2] <<= 3; + f[3] <<= 5; f[4] <<= 6; + f[6] <<= 1; f[7] <<= 3; + f[8] <<= 4; f[9] <<= 6; + + #define F(i, s) \ + out[s+0] |= (byte)( f[i] & 0xff); \ + out[s+1] = (byte)((f[i] >> 8) & 0xff); \ + out[s+2] = (byte)((f[i] >> 16) & 0xff); \ + out[s+3] = (byte)((f[i] >> 24) & 0xff); + + out[0] = out[16] = 0; + F(0,0); F(1,3); + F(2,6); F(3,9); + F(4,12); F(5,16); + F(6,19); F(7,22); + F(8,25); F(9,28); + #undef F +} + +/* out = (flag) ? in : out */ +inline void +curve25519_move_conditional_bytes(byte out[96], const byte in[96], word32 flag) +{ + // TODO: enable this code path once we can test and benchmark it. + // It is about 48 insns shorter, it avoids punning which may be UB, + // and it is guaranteed constant time. +#if defined(__GNUC__) && defined(__i686__) && 0 + const word32 iter = 96/sizeof(word32); + word32* outl = reinterpret_cast(out); + const word32* inl = reinterpret_cast(in); + word32 idx=0, val; + + __asm__ __volatile__ ( + ".att_syntax ;\n" + "cmpl $0, %[flag] ;\n" // compare, set ZERO flag + "movl %[iter], %%ecx ;\n" // load iteration count + "1: ;\n" + " movl (%[idx],%[out]), %[val] ;\n" // val = out[idx] + " cmovnzl (%[idx],%[in]), %[val] ;\n" // copy in[idx] to val if NZ + " movl %[val], (%[idx],%[out]) ;\n" // out[idx] = val + " leal 4(%[idx]), %[idx] ;\n" // increment index + " loopnz 1b ;\n" // does not affect flags + : [out] "+S" (outl), [in] "+D" (inl), + [idx] "+b" (idx), [val] "=r" (val) + : [flag] "g" (flag), [iter] "I" (iter) + : "ecx", "memory", "cc" + ); +#else + const word32 nb = flag - 1, b = ~nb; + const word32 *inl = (const word32 *)in; + word32 *outl = (word32 *)out; + outl[0] = (outl[0] & nb) | (inl[0] & b); + outl[1] = (outl[1] & nb) | (inl[1] & b); + outl[2] = (outl[2] & nb) | (inl[2] & b); + outl[3] = (outl[3] & nb) | (inl[3] & b); + outl[4] = (outl[4] & nb) | (inl[4] & b); + outl[5] = (outl[5] & nb) | (inl[5] & b); + outl[6] = (outl[6] & nb) | (inl[6] & b); + outl[7] = (outl[7] & nb) | (inl[7] & b); + outl[8] = (outl[8] & nb) | (inl[8] & b); + outl[9] = (outl[9] & nb) | (inl[9] & b); + outl[10] = (outl[10] & nb) | (inl[10] & b); + outl[11] = (outl[11] & nb) | (inl[11] & b); + outl[12] = (outl[12] & nb) | (inl[12] & b); + outl[13] = (outl[13] & nb) | (inl[13] & b); + outl[14] = (outl[14] & nb) | (inl[14] & b); + outl[15] = (outl[15] & nb) | (inl[15] & b); + outl[16] = (outl[16] & nb) | (inl[16] & b); + outl[17] = (outl[17] & nb) | (inl[17] & b); + outl[18] = (outl[18] & nb) | (inl[18] & b); + outl[19] = (outl[19] & nb) | (inl[19] & b); + outl[20] = (outl[20] & nb) | (inl[20] & b); + outl[21] = (outl[21] & nb) | (inl[21] & b); + outl[22] = (outl[22] & nb) | (inl[22] & b); + outl[23] = (outl[23] & nb) | (inl[23] & b); +#endif +} + +/* if (iswap) swap(a, b) */ +inline void +curve25519_swap_conditional(bignum25519 a, bignum25519 b, word32 iswap) { + const word32 swap = (word32)(-(sword32)iswap); + word32 x0,x1,x2,x3,x4,x5,x6,x7,x8,x9; + + x0 = swap & (a[0] ^ b[0]); a[0] ^= x0; b[0] ^= x0; + x1 = swap & (a[1] ^ b[1]); a[1] ^= x1; b[1] ^= x1; + x2 = swap & (a[2] ^ b[2]); a[2] ^= x2; b[2] ^= x2; + x3 = swap & (a[3] ^ b[3]); a[3] ^= x3; b[3] ^= x3; + x4 = swap & (a[4] ^ b[4]); a[4] ^= x4; b[4] ^= x4; + x5 = swap & (a[5] ^ b[5]); a[5] ^= x5; b[5] ^= x5; + x6 = swap & (a[6] ^ b[6]); a[6] ^= x6; b[6] ^= x6; + x7 = swap & (a[7] ^ b[7]); a[7] ^= x7; b[7] ^= x7; + x8 = swap & (a[8] ^ b[8]); a[8] ^= x8; b[8] ^= x8; + x9 = swap & (a[9] ^ b[9]); a[9] ^= x9; b[9] ^= x9; +} + +/* + * In: b = 2^5 - 2^0 + * Out: b = 2^250 - 2^0 + */ +void +curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) { + ALIGN(ALIGN_SPEC) bignum25519 t0,c; + + /* 2^5 - 2^0 */ /* b */ + /* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5); + /* 2^10 - 2^0 */ curve25519_mul(b, t0, b); + /* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10); + /* 2^20 - 2^0 */ curve25519_mul(c, t0, b); + /* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20); + /* 2^40 - 2^0 */ curve25519_mul(t0, t0, c); + /* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10); + /* 2^50 - 2^0 */ curve25519_mul(b, t0, b); + /* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50); + /* 2^100 - 2^0 */ curve25519_mul(c, t0, b); + /* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100); + /* 2^200 - 2^0 */ curve25519_mul(t0, t0, c); + /* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50); + /* 2^250 - 2^0 */ curve25519_mul(b, t0, b); +} + +/* + * z^(p - 2) = z(2^255 - 21) + */ +void +curve25519_recip(bignum25519 out, const bignum25519 z) { + ALIGN(ALIGN_SPEC) bignum25519 a,t0,b; + + /* 2 */ curve25519_square_times(a, z, 1); /* a = 2 */ + /* 8 */ curve25519_square_times(t0, a, 2); + /* 9 */ curve25519_mul(b, t0, z); /* b = 9 */ + /* 11 */ curve25519_mul(a, b, a); /* a = 11 */ + /* 22 */ curve25519_square_times(t0, a, 1); + /* 2^5 - 2^0 = 31 */ curve25519_mul(b, t0, b); + /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b); + /* 2^255 - 2^5 */ curve25519_square_times(b, b, 5); + /* 2^255 - 21 */ curve25519_mul(out, b, a); +} + +/* + * z^((p-5)/8) = z^(2^252 - 3) + */ +void +curve25519_pow_two252m3(bignum25519 two252m3, const bignum25519 z) { + ALIGN(ALIGN_SPEC) bignum25519 b,c,t0; + + /* 2 */ curve25519_square_times(c, z, 1); /* c = 2 */ + /* 8 */ curve25519_square_times(t0, c, 2); /* t0 = 8 */ + /* 9 */ curve25519_mul(b, t0, z); /* b = 9 */ + /* 11 */ curve25519_mul(c, b, c); /* c = 11 */ + /* 22 */ curve25519_square_times(t0, c, 1); + /* 2^5 - 2^0 = 31 */ curve25519_mul(b, t0, b); + /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b); + /* 2^252 - 2^2 */ curve25519_square_times(b, b, 2); + /* 2^252 - 3 */ curve25519_mul(two252m3, b, z); +} + +inline void +ed25519_hash(byte *hash, const byte *in, size_t inlen) { + SHA512().CalculateDigest(hash, in, inlen); +} + +inline void +ed25519_extsk(hash_512bits extsk, const byte sk[32]) { + ed25519_hash(extsk, sk, 32); + extsk[0] &= 248; + extsk[31] &= 127; + extsk[31] |= 64; +} + +void +UpdateFromStream(HashTransformation& hash, std::istream& stream) +{ + SecByteBlock block(4096); + while (stream.read((char*)block.begin(), block.size())) + hash.Update(block, block.size()); + + std::streamsize rem = stream.gcount(); + if (rem) + hash.Update(block, (size_t)rem); + + block.SetMark(0); +} + +void +ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], const byte *m, size_t mlen) { + SHA512 hash; + hash.Update(RS, 32); + hash.Update(pk, 32); + hash.Update(m, mlen); + hash.Final(hram); +} + +void +ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], std::istream& stream) { + SHA512 hash; + hash.Update(RS, 32); + hash.Update(pk, 32); + UpdateFromStream(hash, stream); + hash.Final(hram); +} + +inline bignum256modm_element_t +lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) { + return (a - b) >> 31; +} + +/* see HAC, Alg. 14.42 Step 4 */ +void +reduce256_modm(bignum256modm r) { + bignum256modm t; + bignum256modm_element_t b = 0, pb, mask; + + /* t = r - m */ + pb = 0; + pb += modm_m[0]; b = lt_modm(r[0], pb); t[0] = (r[0] - pb + (b << 30)); pb = b; + pb += modm_m[1]; b = lt_modm(r[1], pb); t[1] = (r[1] - pb + (b << 30)); pb = b; + pb += modm_m[2]; b = lt_modm(r[2], pb); t[2] = (r[2] - pb + (b << 30)); pb = b; + pb += modm_m[3]; b = lt_modm(r[3], pb); t[3] = (r[3] - pb + (b << 30)); pb = b; + pb += modm_m[4]; b = lt_modm(r[4], pb); t[4] = (r[4] - pb + (b << 30)); pb = b; + pb += modm_m[5]; b = lt_modm(r[5], pb); t[5] = (r[5] - pb + (b << 30)); pb = b; + pb += modm_m[6]; b = lt_modm(r[6], pb); t[6] = (r[6] - pb + (b << 30)); pb = b; + pb += modm_m[7]; b = lt_modm(r[7], pb); t[7] = (r[7] - pb + (b << 30)); pb = b; + pb += modm_m[8]; b = lt_modm(r[8], pb); t[8] = (r[8] - pb + (b << 16)); + + /* keep r if r was smaller than m */ + mask = b - 1; + r[0] ^= mask & (r[0] ^ t[0]); + r[1] ^= mask & (r[1] ^ t[1]); + r[2] ^= mask & (r[2] ^ t[2]); + r[3] ^= mask & (r[3] ^ t[3]); + r[4] ^= mask & (r[4] ^ t[4]); + r[5] ^= mask & (r[5] ^ t[5]); + r[6] ^= mask & (r[6] ^ t[6]); + r[7] ^= mask & (r[7] ^ t[7]); + r[8] ^= mask & (r[8] ^ t[8]); +} + +/* Barrett reduction, see HAC, Alg. 14.42 */ +void +barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256modm r1) { + bignum256modm q3, r2; + word64 c; + bignum256modm_element_t f, b, pb; + + /* q1 = x >> 248 = 264 bits = 9 30 bit elements + q2 = mu * q1 + q3 = (q2 / 256(32+1)) = q2 / (2^8)^(32+1) = q2 >> 264 + */ + c = mul32x32_64(modm_mu[0], q1[7]) + mul32x32_64(modm_mu[1], q1[6]) + mul32x32_64(modm_mu[2], q1[5]) + mul32x32_64(modm_mu[3], q1[4]) + mul32x32_64(modm_mu[4], q1[3]) + mul32x32_64(modm_mu[5], q1[2]) + mul32x32_64(modm_mu[6], q1[1]) + mul32x32_64(modm_mu[7], q1[0]); + c >>= 30; + c += mul32x32_64(modm_mu[0], q1[8]) + mul32x32_64(modm_mu[1], q1[7]) + mul32x32_64(modm_mu[2], q1[6]) + mul32x32_64(modm_mu[3], q1[5]) + mul32x32_64(modm_mu[4], q1[4]) + mul32x32_64(modm_mu[5], q1[3]) + mul32x32_64(modm_mu[6], q1[2]) + mul32x32_64(modm_mu[7], q1[1]) + mul32x32_64(modm_mu[8], q1[0]); + f = (bignum256modm_element_t)c; q3[0] = (f >> 24) & 0x3f; c >>= 30; + c += mul32x32_64(modm_mu[1], q1[8]) + mul32x32_64(modm_mu[2], q1[7]) + mul32x32_64(modm_mu[3], q1[6]) + mul32x32_64(modm_mu[4], q1[5]) + mul32x32_64(modm_mu[5], q1[4]) + mul32x32_64(modm_mu[6], q1[3]) + mul32x32_64(modm_mu[7], q1[2]) + mul32x32_64(modm_mu[8], q1[1]); + f = (bignum256modm_element_t)c; q3[0] |= (f << 6) & 0x3fffffff; q3[1] = (f >> 24) & 0x3f; c >>= 30; + c += mul32x32_64(modm_mu[2], q1[8]) + mul32x32_64(modm_mu[3], q1[7]) + mul32x32_64(modm_mu[4], q1[6]) + mul32x32_64(modm_mu[5], q1[5]) + mul32x32_64(modm_mu[6], q1[4]) + mul32x32_64(modm_mu[7], q1[3]) + mul32x32_64(modm_mu[8], q1[2]); + f = (bignum256modm_element_t)c; q3[1] |= (f << 6) & 0x3fffffff; q3[2] = (f >> 24) & 0x3f; c >>= 30; + c += mul32x32_64(modm_mu[3], q1[8]) + mul32x32_64(modm_mu[4], q1[7]) + mul32x32_64(modm_mu[5], q1[6]) + mul32x32_64(modm_mu[6], q1[5]) + mul32x32_64(modm_mu[7], q1[4]) + mul32x32_64(modm_mu[8], q1[3]); + f = (bignum256modm_element_t)c; q3[2] |= (f << 6) & 0x3fffffff; q3[3] = (f >> 24) & 0x3f; c >>= 30; + c += mul32x32_64(modm_mu[4], q1[8]) + mul32x32_64(modm_mu[5], q1[7]) + mul32x32_64(modm_mu[6], q1[6]) + mul32x32_64(modm_mu[7], q1[5]) + mul32x32_64(modm_mu[8], q1[4]); + f = (bignum256modm_element_t)c; q3[3] |= (f << 6) & 0x3fffffff; q3[4] = (f >> 24) & 0x3f; c >>= 30; + c += mul32x32_64(modm_mu[5], q1[8]) + mul32x32_64(modm_mu[6], q1[7]) + mul32x32_64(modm_mu[7], q1[6]) + mul32x32_64(modm_mu[8], q1[5]); + f = (bignum256modm_element_t)c; q3[4] |= (f << 6) & 0x3fffffff; q3[5] = (f >> 24) & 0x3f; c >>= 30; + c += mul32x32_64(modm_mu[6], q1[8]) + mul32x32_64(modm_mu[7], q1[7]) + mul32x32_64(modm_mu[8], q1[6]); + f = (bignum256modm_element_t)c; q3[5] |= (f << 6) & 0x3fffffff; q3[6] = (f >> 24) & 0x3f; c >>= 30; + c += mul32x32_64(modm_mu[7], q1[8]) + mul32x32_64(modm_mu[8], q1[7]); + f = (bignum256modm_element_t)c; q3[6] |= (f << 6) & 0x3fffffff; q3[7] = (f >> 24) & 0x3f; c >>= 30; + c += mul32x32_64(modm_mu[8], q1[8]); + f = (bignum256modm_element_t)c; q3[7] |= (f << 6) & 0x3fffffff; q3[8] = (bignum256modm_element_t)(c >> 24); + + /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) + r2 = (q3 * m) mod (256^(32+1)) = (q3 * m) & ((1 << 264) - 1) + */ + c = mul32x32_64(modm_m[0], q3[0]); + r2[0] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; + c += mul32x32_64(modm_m[0], q3[1]) + mul32x32_64(modm_m[1], q3[0]); + r2[1] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; + c += mul32x32_64(modm_m[0], q3[2]) + mul32x32_64(modm_m[1], q3[1]) + mul32x32_64(modm_m[2], q3[0]); + r2[2] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; + c += mul32x32_64(modm_m[0], q3[3]) + mul32x32_64(modm_m[1], q3[2]) + mul32x32_64(modm_m[2], q3[1]) + mul32x32_64(modm_m[3], q3[0]); + r2[3] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; + c += mul32x32_64(modm_m[0], q3[4]) + mul32x32_64(modm_m[1], q3[3]) + mul32x32_64(modm_m[2], q3[2]) + mul32x32_64(modm_m[3], q3[1]) + mul32x32_64(modm_m[4], q3[0]); + r2[4] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; + c += mul32x32_64(modm_m[0], q3[5]) + mul32x32_64(modm_m[1], q3[4]) + mul32x32_64(modm_m[2], q3[3]) + mul32x32_64(modm_m[3], q3[2]) + mul32x32_64(modm_m[4], q3[1]) + mul32x32_64(modm_m[5], q3[0]); + r2[5] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; + c += mul32x32_64(modm_m[0], q3[6]) + mul32x32_64(modm_m[1], q3[5]) + mul32x32_64(modm_m[2], q3[4]) + mul32x32_64(modm_m[3], q3[3]) + mul32x32_64(modm_m[4], q3[2]) + mul32x32_64(modm_m[5], q3[1]) + mul32x32_64(modm_m[6], q3[0]); + r2[6] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; + c += mul32x32_64(modm_m[0], q3[7]) + mul32x32_64(modm_m[1], q3[6]) + mul32x32_64(modm_m[2], q3[5]) + mul32x32_64(modm_m[3], q3[4]) + mul32x32_64(modm_m[4], q3[3]) + mul32x32_64(modm_m[5], q3[2]) + mul32x32_64(modm_m[6], q3[1]) + mul32x32_64(modm_m[7], q3[0]); + r2[7] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; + c += mul32x32_64(modm_m[0], q3[8]) + mul32x32_64(modm_m[1], q3[7]) + mul32x32_64(modm_m[2], q3[6]) + mul32x32_64(modm_m[3], q3[5]) + mul32x32_64(modm_m[4], q3[4]) + mul32x32_64(modm_m[5], q3[3]) + mul32x32_64(modm_m[6], q3[2]) + mul32x32_64(modm_m[7], q3[1]) + mul32x32_64(modm_m[8], q3[0]); + r2[8] = (bignum256modm_element_t)(c & 0xffffff); + + /* r = r1 - r2 + if (r < 0) r += (1 << 264) */ + pb = 0; + pb += r2[0]; b = lt_modm(r1[0], pb); r[0] = (r1[0] - pb + (b << 30)); pb = b; + pb += r2[1]; b = lt_modm(r1[1], pb); r[1] = (r1[1] - pb + (b << 30)); pb = b; + pb += r2[2]; b = lt_modm(r1[2], pb); r[2] = (r1[2] - pb + (b << 30)); pb = b; + pb += r2[3]; b = lt_modm(r1[3], pb); r[3] = (r1[3] - pb + (b << 30)); pb = b; + pb += r2[4]; b = lt_modm(r1[4], pb); r[4] = (r1[4] - pb + (b << 30)); pb = b; + pb += r2[5]; b = lt_modm(r1[5], pb); r[5] = (r1[5] - pb + (b << 30)); pb = b; + pb += r2[6]; b = lt_modm(r1[6], pb); r[6] = (r1[6] - pb + (b << 30)); pb = b; + pb += r2[7]; b = lt_modm(r1[7], pb); r[7] = (r1[7] - pb + (b << 30)); pb = b; + pb += r2[8]; b = lt_modm(r1[8], pb); r[8] = (r1[8] - pb + (b << 24)); + + reduce256_modm(r); + reduce256_modm(r); +} + +/* addition modulo m */ +void +add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) { + bignum256modm_element_t c; + + c = x[0] + y[0]; r[0] = c & 0x3fffffff; c >>= 30; + c += x[1] + y[1]; r[1] = c & 0x3fffffff; c >>= 30; + c += x[2] + y[2]; r[2] = c & 0x3fffffff; c >>= 30; + c += x[3] + y[3]; r[3] = c & 0x3fffffff; c >>= 30; + c += x[4] + y[4]; r[4] = c & 0x3fffffff; c >>= 30; + c += x[5] + y[5]; r[5] = c & 0x3fffffff; c >>= 30; + c += x[6] + y[6]; r[6] = c & 0x3fffffff; c >>= 30; + c += x[7] + y[7]; r[7] = c & 0x3fffffff; c >>= 30; + c += x[8] + y[8]; r[8] = c; + + reduce256_modm(r); +} + +/* multiplication modulo m */ +void +mul256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) { + bignum256modm r1, q1; + word64 c; + bignum256modm_element_t f; + + c = mul32x32_64(x[0], y[0]); + f = (bignum256modm_element_t)c; r1[0] = (f & 0x3fffffff); c >>= 30; + c += mul32x32_64(x[0], y[1]) + mul32x32_64(x[1], y[0]); + f = (bignum256modm_element_t)c; r1[1] = (f & 0x3fffffff); c >>= 30; + c += mul32x32_64(x[0], y[2]) + mul32x32_64(x[1], y[1]) + mul32x32_64(x[2], y[0]); + f = (bignum256modm_element_t)c; r1[2] = (f & 0x3fffffff); c >>= 30; + c += mul32x32_64(x[0], y[3]) + mul32x32_64(x[1], y[2]) + mul32x32_64(x[2], y[1]) + mul32x32_64(x[3], y[0]); + f = (bignum256modm_element_t)c; r1[3] = (f & 0x3fffffff); c >>= 30; + c += mul32x32_64(x[0], y[4]) + mul32x32_64(x[1], y[3]) + mul32x32_64(x[2], y[2]) + mul32x32_64(x[3], y[1]) + mul32x32_64(x[4], y[0]); + f = (bignum256modm_element_t)c; r1[4] = (f & 0x3fffffff); c >>= 30; + c += mul32x32_64(x[0], y[5]) + mul32x32_64(x[1], y[4]) + mul32x32_64(x[2], y[3]) + mul32x32_64(x[3], y[2]) + mul32x32_64(x[4], y[1]) + mul32x32_64(x[5], y[0]); + f = (bignum256modm_element_t)c; r1[5] = (f & 0x3fffffff); c >>= 30; + c += mul32x32_64(x[0], y[6]) + mul32x32_64(x[1], y[5]) + mul32x32_64(x[2], y[4]) + mul32x32_64(x[3], y[3]) + mul32x32_64(x[4], y[2]) + mul32x32_64(x[5], y[1]) + mul32x32_64(x[6], y[0]); + f = (bignum256modm_element_t)c; r1[6] = (f & 0x3fffffff); c >>= 30; + c += mul32x32_64(x[0], y[7]) + mul32x32_64(x[1], y[6]) + mul32x32_64(x[2], y[5]) + mul32x32_64(x[3], y[4]) + mul32x32_64(x[4], y[3]) + mul32x32_64(x[5], y[2]) + mul32x32_64(x[6], y[1]) + mul32x32_64(x[7], y[0]); + f = (bignum256modm_element_t)c; r1[7] = (f & 0x3fffffff); c >>= 30; + c += mul32x32_64(x[0], y[8]) + mul32x32_64(x[1], y[7]) + mul32x32_64(x[2], y[6]) + mul32x32_64(x[3], y[5]) + mul32x32_64(x[4], y[4]) + mul32x32_64(x[5], y[3]) + mul32x32_64(x[6], y[2]) + mul32x32_64(x[7], y[1]) + mul32x32_64(x[8], y[0]); + f = (bignum256modm_element_t)c; r1[8] = (f & 0x00ffffff); q1[0] = (f >> 8) & 0x3fffff; c >>= 30; + c += mul32x32_64(x[1], y[8]) + mul32x32_64(x[2], y[7]) + mul32x32_64(x[3], y[6]) + mul32x32_64(x[4], y[5]) + mul32x32_64(x[5], y[4]) + mul32x32_64(x[6], y[3]) + mul32x32_64(x[7], y[2]) + mul32x32_64(x[8], y[1]); + f = (bignum256modm_element_t)c; q1[0] = (q1[0] | (f << 22)) & 0x3fffffff; q1[1] = (f >> 8) & 0x3fffff; c >>= 30; + c += mul32x32_64(x[2], y[8]) + mul32x32_64(x[3], y[7]) + mul32x32_64(x[4], y[6]) + mul32x32_64(x[5], y[5]) + mul32x32_64(x[6], y[4]) + mul32x32_64(x[7], y[3]) + mul32x32_64(x[8], y[2]); + f = (bignum256modm_element_t)c; q1[1] = (q1[1] | (f << 22)) & 0x3fffffff; q1[2] = (f >> 8) & 0x3fffff; c >>= 30; + c += mul32x32_64(x[3], y[8]) + mul32x32_64(x[4], y[7]) + mul32x32_64(x[5], y[6]) + mul32x32_64(x[6], y[5]) + mul32x32_64(x[7], y[4]) + mul32x32_64(x[8], y[3]); + f = (bignum256modm_element_t)c; q1[2] = (q1[2] | (f << 22)) & 0x3fffffff; q1[3] = (f >> 8) & 0x3fffff; c >>= 30; + c += mul32x32_64(x[4], y[8]) + mul32x32_64(x[5], y[7]) + mul32x32_64(x[6], y[6]) + mul32x32_64(x[7], y[5]) + mul32x32_64(x[8], y[4]); + f = (bignum256modm_element_t)c; q1[3] = (q1[3] | (f << 22)) & 0x3fffffff; q1[4] = (f >> 8) & 0x3fffff; c >>= 30; + c += mul32x32_64(x[5], y[8]) + mul32x32_64(x[6], y[7]) + mul32x32_64(x[7], y[6]) + mul32x32_64(x[8], y[5]); + f = (bignum256modm_element_t)c; q1[4] = (q1[4] | (f << 22)) & 0x3fffffff; q1[5] = (f >> 8) & 0x3fffff; c >>= 30; + c += mul32x32_64(x[6], y[8]) + mul32x32_64(x[7], y[7]) + mul32x32_64(x[8], y[6]); + f = (bignum256modm_element_t)c; q1[5] = (q1[5] | (f << 22)) & 0x3fffffff; q1[6] = (f >> 8) & 0x3fffff; c >>= 30; + c += mul32x32_64(x[7], y[8]) + mul32x32_64(x[8], y[7]); + f = (bignum256modm_element_t)c; q1[6] = (q1[6] | (f << 22)) & 0x3fffffff; q1[7] = (f >> 8) & 0x3fffff; c >>= 30; + c += mul32x32_64(x[8], y[8]); + f = (bignum256modm_element_t)c; q1[7] = (q1[7] | (f << 22)) & 0x3fffffff; q1[8] = (f >> 8) & 0x3fffff; + + barrett_reduce256_modm(r, q1, r1); +} + +void +expand256_modm(bignum256modm out, const byte *in, size_t len) { + byte work[64] = {0}; + bignum256modm_element_t x[16]; + bignum256modm q1; + + memcpy(work, in, len); + x[0] = U8TO32_LE(work + 0); + x[1] = U8TO32_LE(work + 4); + x[2] = U8TO32_LE(work + 8); + x[3] = U8TO32_LE(work + 12); + x[4] = U8TO32_LE(work + 16); + x[5] = U8TO32_LE(work + 20); + x[6] = U8TO32_LE(work + 24); + x[7] = U8TO32_LE(work + 28); + x[8] = U8TO32_LE(work + 32); + x[9] = U8TO32_LE(work + 36); + x[10] = U8TO32_LE(work + 40); + x[11] = U8TO32_LE(work + 44); + x[12] = U8TO32_LE(work + 48); + x[13] = U8TO32_LE(work + 52); + x[14] = U8TO32_LE(work + 56); + x[15] = U8TO32_LE(work + 60); + + /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) */ + out[0] = ( x[0]) & 0x3fffffff; + out[1] = ((x[ 0] >> 30) | (x[ 1] << 2)) & 0x3fffffff; + out[2] = ((x[ 1] >> 28) | (x[ 2] << 4)) & 0x3fffffff; + out[3] = ((x[ 2] >> 26) | (x[ 3] << 6)) & 0x3fffffff; + out[4] = ((x[ 3] >> 24) | (x[ 4] << 8)) & 0x3fffffff; + out[5] = ((x[ 4] >> 22) | (x[ 5] << 10)) & 0x3fffffff; + out[6] = ((x[ 5] >> 20) | (x[ 6] << 12)) & 0x3fffffff; + out[7] = ((x[ 6] >> 18) | (x[ 7] << 14)) & 0x3fffffff; + out[8] = ((x[ 7] >> 16) | (x[ 8] << 16)) & 0x00ffffff; + + /* 8*31 = 248 bits, no need to reduce */ + if (len < 32) + return; + + /* q1 = x >> 248 = 264 bits = 9 30 bit elements */ + q1[0] = ((x[ 7] >> 24) | (x[ 8] << 8)) & 0x3fffffff; + q1[1] = ((x[ 8] >> 22) | (x[ 9] << 10)) & 0x3fffffff; + q1[2] = ((x[ 9] >> 20) | (x[10] << 12)) & 0x3fffffff; + q1[3] = ((x[10] >> 18) | (x[11] << 14)) & 0x3fffffff; + q1[4] = ((x[11] >> 16) | (x[12] << 16)) & 0x3fffffff; + q1[5] = ((x[12] >> 14) | (x[13] << 18)) & 0x3fffffff; + q1[6] = ((x[13] >> 12) | (x[14] << 20)) & 0x3fffffff; + q1[7] = ((x[14] >> 10) | (x[15] << 22)) & 0x3fffffff; + q1[8] = ((x[15] >> 8) ); + + barrett_reduce256_modm(out, q1, out); +} + +void +expand_raw256_modm(bignum256modm out, const byte in[32]) { + bignum256modm_element_t x[8]; + + x[0] = U8TO32_LE(in + 0); + x[1] = U8TO32_LE(in + 4); + x[2] = U8TO32_LE(in + 8); + x[3] = U8TO32_LE(in + 12); + x[4] = U8TO32_LE(in + 16); + x[5] = U8TO32_LE(in + 20); + x[6] = U8TO32_LE(in + 24); + x[7] = U8TO32_LE(in + 28); + + out[0] = ( x[0]) & 0x3fffffff; + out[1] = ((x[ 0] >> 30) | (x[ 1] << 2)) & 0x3fffffff; + out[2] = ((x[ 1] >> 28) | (x[ 2] << 4)) & 0x3fffffff; + out[3] = ((x[ 2] >> 26) | (x[ 3] << 6)) & 0x3fffffff; + out[4] = ((x[ 3] >> 24) | (x[ 4] << 8)) & 0x3fffffff; + out[5] = ((x[ 4] >> 22) | (x[ 5] << 10)) & 0x3fffffff; + out[6] = ((x[ 5] >> 20) | (x[ 6] << 12)) & 0x3fffffff; + out[7] = ((x[ 6] >> 18) | (x[ 7] << 14)) & 0x3fffffff; + out[8] = ((x[ 7] >> 16) ) & 0x0000ffff; +} + +void +contract256_modm(byte out[32], const bignum256modm in) { + U32TO8_LE(out + 0, (in[0] ) | (in[1] << 30)); + U32TO8_LE(out + 4, (in[1] >> 2) | (in[2] << 28)); + U32TO8_LE(out + 8, (in[2] >> 4) | (in[3] << 26)); + U32TO8_LE(out + 12, (in[3] >> 6) | (in[4] << 24)); + U32TO8_LE(out + 16, (in[4] >> 8) | (in[5] << 22)); + U32TO8_LE(out + 20, (in[5] >> 10) | (in[6] << 20)); + U32TO8_LE(out + 24, (in[6] >> 12) | (in[7] << 18)); + U32TO8_LE(out + 28, (in[7] >> 14) | (in[8] << 16)); +} + +void +contract256_window4_modm(signed char r[64], const bignum256modm in) { + char carry; + signed char *quads = r; + bignum256modm_element_t i, j, v; + + for (i = 0; i < 8; i += 2) { + v = in[i]; + for (j = 0; j < 7; j++) { + *quads++ = (v & 15); + v >>= 4; + } + v |= (in[i+1] << 2); + for (j = 0; j < 8; j++) { + *quads++ = (v & 15); + v >>= 4; + } + } + + v = in[8]; + *quads++ = (v & 15); v >>= 4; + *quads++ = (v & 15); v >>= 4; + *quads++ = (v & 15); v >>= 4; + *quads++ = (v & 15); v >>= 4; + + /* making it signed */ + carry = 0; + for(i = 0; i < 63; i++) { + r[i] += carry; + r[i+1] += (r[i] >> 4); + r[i] &= 15; + carry = (r[i] >> 3); + r[i] -= (carry << 4); + } + r[63] += carry; +} + +void +contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int windowsize) { + int i,j,k,b; + int m = (1 << (windowsize - 1)) - 1, soplen = 256; + signed char *bits = r; + bignum256modm_element_t v; + + /* first put the binary expansion into r */ + for (i = 0; i < 8; i++) { + v = s[i]; + for (j = 0; j < 30; j++, v >>= 1) + *bits++ = (v & 1); + } + v = s[8]; + for (j = 0; j < 16; j++, v >>= 1) + *bits++ = (v & 1); + + /* Making it sliding window */ + for (j = 0; j < soplen; j++) { + if (!r[j]) + continue; + + for (b = 1; (b < (soplen - j)) && (b <= 6); b++) { + if ((r[j] + (r[j + b] << b)) <= m) { + r[j] += r[j + b] << b; + r[j + b] = 0; + } else if ((r[j] - (r[j + b] << b)) >= -m) { + r[j] -= r[j + b] << b; + for (k = j + b; k < soplen; k++) { + if (!r[k]) { + r[k] = 1; + break; + } + r[k] = 0; + } + } else if (r[j + b]) { + break; + } + } + } +} + +inline void +ge25519_p1p1_to_partial(ge25519 *r, const ge25519_p1p1 *p) { + curve25519_mul(r->x, p->x, p->t); + curve25519_mul(r->y, p->y, p->z); + curve25519_mul(r->z, p->z, p->t); +} + +inline void +ge25519_p1p1_to_full(ge25519 *r, const ge25519_p1p1 *p) { + curve25519_mul(r->x, p->x, p->t); + curve25519_mul(r->y, p->y, p->z); + curve25519_mul(r->z, p->z, p->t); + curve25519_mul(r->t, p->x, p->y); +} + +void +ge25519_full_to_pniels(ge25519_pniels *p, const ge25519 *r) { + curve25519_sub(p->ysubx, r->y, r->x); + curve25519_add(p->xaddy, r->y, r->x); + curve25519_copy(p->z, r->z); + curve25519_mul(p->t2d, r->t, ge25519_ec2d); +} + +void +ge25519_add_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519 *q) { + bignum25519 a,b,c,d,t,u; + + curve25519_sub(a, p->y, p->x); + curve25519_add(b, p->y, p->x); + curve25519_sub(t, q->y, q->x); + curve25519_add(u, q->y, q->x); + curve25519_mul(a, a, t); + curve25519_mul(b, b, u); + curve25519_mul(c, p->t, q->t); + curve25519_mul(c, c, ge25519_ec2d); + curve25519_mul(d, p->z, q->z); + curve25519_add(d, d, d); + curve25519_sub(r->x, b, a); + curve25519_add(r->y, b, a); + curve25519_add_after_basic(r->z, d, c); + curve25519_sub_after_basic(r->t, d, c); +} + +void +ge25519_double_p1p1(ge25519_p1p1 *r, const ge25519 *p) { + bignum25519 a,b,c; + + curve25519_square(a, p->x); + curve25519_square(b, p->y); + curve25519_square(c, p->z); + curve25519_add_reduce(c, c, c); + curve25519_add(r->x, p->x, p->y); + curve25519_square(r->x, r->x); + curve25519_add(r->y, b, a); + curve25519_sub(r->z, b, a); + curve25519_sub_after_basic(r->x, r->x, r->y); + curve25519_sub_after_basic(r->t, c, r->z); +} + +void +ge25519_nielsadd2_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_niels *q, byte signbit) { + const bignum25519 *qb = (const bignum25519 *)q; + bignum25519 *rb = (bignum25519 *)r; + bignum25519 a,b,c; + + curve25519_sub(a, p->y, p->x); + curve25519_add(b, p->y, p->x); + curve25519_mul(a, a, qb[signbit]); /* x for +, y for - */ + curve25519_mul(r->x, b, qb[signbit^1]); /* y for +, x for - */ + curve25519_add(r->y, r->x, a); + curve25519_sub(r->x, r->x, a); + curve25519_mul(c, p->t, q->t2d); + curve25519_add_reduce(r->t, p->z, p->z); + curve25519_copy(r->z, r->t); + curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */ + curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */ +} + +void +ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_pniels *q, byte signbit) { + const bignum25519 *qb = (const bignum25519 *)q; + bignum25519 *rb = (bignum25519 *)r; + bignum25519 a,b,c; + + curve25519_sub(a, p->y, p->x); + curve25519_add(b, p->y, p->x); + curve25519_mul(a, a, qb[signbit]); /* ysubx for +, xaddy for - */ + curve25519_mul(r->x, b, qb[signbit^1]); /* xaddy for +, ysubx for - */ + curve25519_add(r->y, r->x, a); + curve25519_sub(r->x, r->x, a); + curve25519_mul(c, p->t, q->t2d); + curve25519_mul(r->t, p->z, q->z); + curve25519_add_reduce(r->t, r->t, r->t); + curve25519_copy(r->z, r->t); + curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */ + curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */ +} + +void +ge25519_double_partial(ge25519 *r, const ge25519 *p) { + ge25519_p1p1 t; + ge25519_double_p1p1(&t, p); + ge25519_p1p1_to_partial(r, &t); +} + +void +ge25519_double(ge25519 *r, const ge25519 *p) { + ge25519_p1p1 t; + ge25519_double_p1p1(&t, p); + ge25519_p1p1_to_full(r, &t); +} + +void +ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q) { + ge25519_p1p1 t; + ge25519_add_p1p1(&t, p, q); + ge25519_p1p1_to_full(r, &t); +} + +void +ge25519_nielsadd2(ge25519 *r, const ge25519_niels *q) { + bignum25519 a,b,c,e,f,g,h; + + curve25519_sub(a, r->y, r->x); + curve25519_add(b, r->y, r->x); + curve25519_mul(a, a, q->ysubx); + curve25519_mul(e, b, q->xaddy); + curve25519_add(h, e, a); + curve25519_sub(e, e, a); + curve25519_mul(c, r->t, q->t2d); + curve25519_add(f, r->z, r->z); + curve25519_add_after_basic(g, f, c); + curve25519_sub_after_basic(f, f, c); + curve25519_mul(r->x, e, f); + curve25519_mul(r->y, h, g); + curve25519_mul(r->z, g, f); + curve25519_mul(r->t, e, h); +} + +void +ge25519_pnielsadd(ge25519_pniels *r, const ge25519 *p, const ge25519_pniels *q) { + bignum25519 a,b,c,x,y,z,t; + + curve25519_sub(a, p->y, p->x); + curve25519_add(b, p->y, p->x); + curve25519_mul(a, a, q->ysubx); + curve25519_mul(x, b, q->xaddy); + curve25519_add(y, x, a); + curve25519_sub(x, x, a); + curve25519_mul(c, p->t, q->t2d); + curve25519_mul(t, p->z, q->z); + curve25519_add(t, t, t); + curve25519_add_after_basic(z, t, c); + curve25519_sub_after_basic(t, t, c); + curve25519_mul(r->xaddy, x, t); + curve25519_mul(r->ysubx, y, z); + curve25519_mul(r->z, z, t); + curve25519_mul(r->t2d, x, y); + curve25519_copy(y, r->ysubx); + curve25519_sub(r->ysubx, r->ysubx, r->xaddy); + curve25519_add(r->xaddy, r->xaddy, y); + curve25519_mul(r->t2d, r->t2d, ge25519_ec2d); +} + +void +ge25519_pack(byte r[32], const ge25519 *p) { + bignum25519 tx, ty, zi; + byte parity[32]; + curve25519_recip(zi, p->z); + curve25519_mul(tx, p->x, zi); + curve25519_mul(ty, p->y, zi); + curve25519_contract(r, ty); + curve25519_contract(parity, tx); + r[31] ^= ((parity[0] & 1) << 7); +} + +int +ed25519_verify(const byte *x, const byte *y, size_t len) { + size_t differentbits = 0; + while (len--) + differentbits |= (*x++ ^ *y++); + return (int) (1 & ((differentbits - 1) >> 8)); +} + +int +ge25519_unpack_negative_vartime(ge25519 *r, const byte p[32]) { + const byte zero[32] = {0}; + const bignum25519 one = {1}; + byte parity = p[31] >> 7; + byte check[32]; + bignum25519 t, root, num, den, d3; + + curve25519_expand(r->y, p); + curve25519_copy(r->z, one); + curve25519_square(num, r->y); /* x = y^2 */ + curve25519_mul(den, num, ge25519_ecd); /* den = dy^2 */ + curve25519_sub_reduce(num, num, r->z); /* x = y^1 - 1 */ + curve25519_add(den, den, r->z); /* den = dy^2 + 1 */ + + /* Computation of sqrt(num/den) */ + /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ + curve25519_square(t, den); + curve25519_mul(d3, t, den); + curve25519_square(r->x, d3); + curve25519_mul(r->x, r->x, den); + curve25519_mul(r->x, r->x, num); + curve25519_pow_two252m3(r->x, r->x); + + /* 2. computation of r->x = num * den^3 * (num*den^7)^((p-5)/8) */ + curve25519_mul(r->x, r->x, d3); + curve25519_mul(r->x, r->x, num); + + /* 3. Check if either of the roots works: */ + curve25519_square(t, r->x); + curve25519_mul(t, t, den); + curve25519_sub_reduce(root, t, num); + curve25519_contract(check, root); + if (!ed25519_verify(check, zero, 32)) { + curve25519_add_reduce(t, t, num); + curve25519_contract(check, t); + if (!ed25519_verify(check, zero, 32)) + return 0; + curve25519_mul(r->x, r->x, ge25519_sqrtneg1); + } + + curve25519_contract(check, r->x); + if ((check[0] & 1) == parity) { + curve25519_copy(t, r->x); + curve25519_neg(r->x, t); + } + curve25519_mul(r->t, r->x, r->y); + return 1; +} + +/* computes [s1]p1 + [s2]basepoint */ +void +ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const bignum256modm s2) { + signed char slide1[256], slide2[256]; + ge25519_pniels pre1[S1_TABLE_SIZE]; + ge25519 d1; + ge25519_p1p1 t; + sword32 i; + + contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE); + contract256_slidingwindow_modm(slide2, s2, S2_SWINDOWSIZE); + + ge25519_double(&d1, p1); + ge25519_full_to_pniels(pre1, p1); + for (i = 0; i < S1_TABLE_SIZE - 1; i++) + ge25519_pnielsadd(&pre1[i+1], &d1, &pre1[i]); + + /* set neutral */ + memset(r, 0, sizeof(ge25519)); + r->y[0] = 1; + r->z[0] = 1; + + i = 255; + while ((i >= 0) && !(slide1[i] | slide2[i])) + i--; + + for (; i >= 0; i--) { + ge25519_double_p1p1(&t, r); + + if (slide1[i]) { + ge25519_p1p1_to_full(r, &t); + ge25519_pnielsadd_p1p1(&t, r, &pre1[abs(slide1[i]) / 2], (byte)slide1[i] >> 7); + } + + if (slide2[i]) { + ge25519_p1p1_to_full(r, &t); + ge25519_nielsadd2_p1p1(&t, r, &ge25519_niels_sliding_multiples[abs(slide2[i]) / 2], (byte)slide2[i] >> 7); + } + + ge25519_p1p1_to_partial(r, &t); + } +} + +#if !defined(HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS) + +word32 +ge25519_windowb_equal(word32 b, word32 c) { + return ((b ^ c) - 1) >> 31; +} + +void +ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const byte table[256][96], word32 pos, signed char b) { + bignum25519 neg; + word32 sign = (word32)((byte)b >> 7); + word32 mask = ~(sign - 1); + word32 u = (b + mask) ^ mask; + word32 i; + + /* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */ + byte packed[96] = {0}; + packed[0] = 1; + packed[32] = 1; + + for (i = 0; i < 8; i++) + curve25519_move_conditional_bytes(packed, table[(pos * 8) + i], ge25519_windowb_equal(u, i + 1)); + + /* expand in to t */ + curve25519_expand(t->ysubx, packed + 0); + curve25519_expand(t->xaddy, packed + 32); + curve25519_expand(t->t2d , packed + 64); + + /* adjust for sign */ + curve25519_swap_conditional(t->ysubx, t->xaddy, sign); + curve25519_neg(neg, t->t2d); + curve25519_swap_conditional(t->t2d, neg, sign); +} + +#endif /* HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS */ + +/* computes [s]basepoint */ +void +ge25519_scalarmult_base_niels(ge25519 *r, const byte basepoint_table[256][96], const bignum256modm s) { + signed char b[64]; + word32 i; + ge25519_niels t; + + contract256_window4_modm(b, s); + + ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[1]); + curve25519_sub_reduce(r->x, t.xaddy, t.ysubx); + curve25519_add_reduce(r->y, t.xaddy, t.ysubx); + memset(r->z, 0, sizeof(bignum25519)); + curve25519_copy(r->t, t.t2d); + r->z[0] = 2; + for (i = 3; i < 64; i += 2) { + ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]); + ge25519_nielsadd2(r, &t); + } + ge25519_double_partial(r, r); + ge25519_double_partial(r, r); + ge25519_double_partial(r, r); + ge25519_double(r, r); + ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[0]); + curve25519_mul(t.t2d, t.t2d, ge25519_ecd); + ge25519_nielsadd2(r, &t); + for(i = 2; i < 64; i += 2) { + ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]); + ge25519_nielsadd2(r, &t); + } +} + +ANONYMOUS_NAMESPACE_END +NAMESPACE_END // Ed25519 +NAMESPACE_END // Donna +NAMESPACE_END // CryptoPP + +//***************************** curve25519 *****************************// + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Donna) + +int curve25519_mult_CXX(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]) +{ + using namespace CryptoPP::Donna::X25519; + + FixedSizeSecBlock e; + for (size_t i = 0; i < 32; ++i) + e[i] = secretKey[i]; + e[0] &= 0xf8; e[31] &= 0x7f; e[31] |= 0x40; + + bignum25519 nqpqx = {1}, nqpqz = {0}, nqz = {1}, nqx; + bignum25519 q, qx, qpqx, qqx, zzz, zmone; + size_t bit, lastbit; + + curve25519_expand(q, othersKey); + curve25519_copy(nqx, q); + + /* bit 255 is always 0, and bit 254 is always 1, so skip bit 255 and + start pre-swapped on bit 254 */ + lastbit = 1; + + /* we are doing bits 254..3 in the loop, but are swapping in bits 253..2 */ + for (int i = 253; i >= 2; i--) { + curve25519_add(qx, nqx, nqz); + curve25519_sub(nqz, nqx, nqz); + curve25519_add(qpqx, nqpqx, nqpqz); + curve25519_sub(nqpqz, nqpqx, nqpqz); + curve25519_mul(nqpqx, qpqx, nqz); + curve25519_mul(nqpqz, qx, nqpqz); + curve25519_add(qqx, nqpqx, nqpqz); + curve25519_sub(nqpqz, nqpqx, nqpqz); + curve25519_square(nqpqz, nqpqz); + curve25519_square(nqpqx, qqx); + curve25519_mul(nqpqz, nqpqz, q); + curve25519_square(qx, qx); + curve25519_square(nqz, nqz); + curve25519_mul(nqx, qx, nqz); + curve25519_sub(nqz, qx, nqz); + curve25519_scalar_product(zzz, nqz, 121665); + curve25519_add(zzz, zzz, qx); + curve25519_mul(nqz, nqz, zzz); + + bit = (e[i/8] >> (i & 7)) & 1; + curve25519_swap_conditional(nqx, nqpqx, (word32)(bit ^ lastbit)); + curve25519_swap_conditional(nqz, nqpqz, (word32)(bit ^ lastbit)); + lastbit = bit; + } + + /* the final 3 bits are always zero, so we only need to double */ + for (int i = 0; i < 3; i++) { + curve25519_add(qx, nqx, nqz); + curve25519_sub(nqz, nqx, nqz); + curve25519_square(qx, qx); + curve25519_square(nqz, nqz); + curve25519_mul(nqx, qx, nqz); + curve25519_sub(nqz, qx, nqz); + curve25519_scalar_product(zzz, nqz, 121665); + curve25519_add(zzz, zzz, qx); + curve25519_mul(nqz, nqz, zzz); + } + + curve25519_recip(zmone, nqz); + curve25519_mul(nqz, nqx, zmone); + curve25519_contract(sharedKey, nqz); + + return 0; +} + +int curve25519_mult(byte publicKey[32], const byte secretKey[32]) +{ + using namespace CryptoPP::Donna::X25519; + +#if (CRYPTOPP_CURVE25519_SSE2) + if (HasSSE2()) + return curve25519_mult_SSE2(publicKey, secretKey, basePoint); + else +#endif + + return curve25519_mult_CXX(publicKey, secretKey, basePoint); +} + +int curve25519_mult(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]) +{ +#if (CRYPTOPP_CURVE25519_SSE2) + if (HasSSE2()) + return curve25519_mult_SSE2(sharedKey, secretKey, othersKey); + else +#endif + + return curve25519_mult_CXX(sharedKey, secretKey, othersKey); +} + +NAMESPACE_END // Donna +NAMESPACE_END // CryptoPP + +//******************************* ed25519 *******************************// + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Donna) + +int +ed25519_publickey_CXX(byte publicKey[32], const byte secretKey[32]) +{ + using namespace CryptoPP::Donna::Ed25519; + + bignum256modm a; + ALIGN(ALIGN_SPEC) ge25519 A; + hash_512bits extsk; + + /* A = aB */ + ed25519_extsk(extsk, secretKey); + expand256_modm(a, extsk, 32); + ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a); + ge25519_pack(publicKey, &A); + + return 0; +} + +int +ed25519_publickey(byte publicKey[32], const byte secretKey[32]) +{ + return ed25519_publickey_CXX(publicKey, secretKey); +} + +int +ed25519_sign_CXX(std::istream& stream, const byte sk[32], const byte pk[32], byte RS[64]) +{ + using namespace CryptoPP::Donna::Ed25519; + + bignum256modm r, S, a; + ALIGN(ALIGN_SPEC) ge25519 R; + hash_512bits extsk, hashr, hram; + + // Unfortunately we need to read the stream twice. The fisrt time calculates + // 'r = H(aExt[32..64], m)'. The second time calculates 'S = H(R,A,m)'. There + // is a data dependency due to hashing 'RS' with 'R = [r]B' that does not + // allow us to read the stream once. + std::streampos where = stream.tellg(); + + ed25519_extsk(extsk, sk); + + /* r = H(aExt[32..64], m) */ + SHA512 hash; + hash.Update(extsk + 32, 32); + UpdateFromStream(hash, stream); + hash.Final(hashr); + expand256_modm(r, hashr, 64); + + /* R = rB */ + ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r); + ge25519_pack(RS, &R); + + // Reset stream for the second digest + stream.clear(); + stream.seekg(where); + + /* S = H(R,A,m).. */ + ed25519_hram(hram, RS, pk, stream); + expand256_modm(S, hram, 64); + + /* S = H(R,A,m)a */ + expand256_modm(a, extsk, 32); + mul256_modm(S, S, a); + + /* S = (r + H(R,A,m)a) */ + add256_modm(S, S, r); + + /* S = (r + H(R,A,m)a) mod L */ + contract256_modm(RS + 32, S); + + return 0; +} + +int +ed25519_sign_CXX(const byte *m, size_t mlen, const byte sk[32], const byte pk[32], byte RS[64]) +{ + using namespace CryptoPP::Donna::Ed25519; + + bignum256modm r, S, a; + ALIGN(ALIGN_SPEC) ge25519 R; + hash_512bits extsk, hashr, hram; + + ed25519_extsk(extsk, sk); + + /* r = H(aExt[32..64], m) */ + SHA512 hash; + hash.Update(extsk + 32, 32); + hash.Update(m, mlen); + hash.Final(hashr); + expand256_modm(r, hashr, 64); + + /* R = rB */ + ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r); + ge25519_pack(RS, &R); + + /* S = H(R,A,m).. */ + ed25519_hram(hram, RS, pk, m, mlen); + expand256_modm(S, hram, 64); + + /* S = H(R,A,m)a */ + expand256_modm(a, extsk, 32); + mul256_modm(S, S, a); + + /* S = (r + H(R,A,m)a) */ + add256_modm(S, S, r); + + /* S = (r + H(R,A,m)a) mod L */ + contract256_modm(RS + 32, S); + + return 0; +} + +int +ed25519_sign(std::istream& stream, const byte secretKey[32], const byte publicKey[32], + byte signature[64]) +{ + return ed25519_sign_CXX(stream, secretKey, publicKey, signature); +} + +int +ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32], + const byte publicKey[32], byte signature[64]) +{ + return ed25519_sign_CXX(message, messageLength, secretKey, publicKey, signature); +} + +int +ed25519_sign_open_CXX(std::istream& stream, const byte pk[32], const byte RS[64]) { + + using namespace CryptoPP::Donna::Ed25519; + + ALIGN(ALIGN_SPEC) ge25519 R, A; + hash_512bits hash; + bignum256modm hram, S; + byte checkR[32]; + + if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) + return -1; + + /* hram = H(R,A,m) */ + ed25519_hram(hash, RS, pk, stream); + expand256_modm(hram, hash, 64); + + /* S */ + expand256_modm(S, RS + 32, 32); + + /* SB - H(R,A,m)A */ + ge25519_double_scalarmult_vartime(&R, &A, hram, S); + ge25519_pack(checkR, &R); + + /* check that R = SB - H(R,A,m)A */ + return ed25519_verify(RS, checkR, 32) ? 0 : -1; +} + +int +ed25519_sign_open_CXX(const byte *m, size_t mlen, const byte pk[32], const byte RS[64]) { + + using namespace CryptoPP::Donna::Ed25519; + + ALIGN(ALIGN_SPEC) ge25519 R, A; + hash_512bits hash; + bignum256modm hram, S; + byte checkR[32]; + + if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) + return -1; + + /* hram = H(R,A,m) */ + ed25519_hram(hash, RS, pk, m, mlen); + expand256_modm(hram, hash, 64); + + /* S */ + expand256_modm(S, RS + 32, 32); + + /* SB - H(R,A,m)A */ + ge25519_double_scalarmult_vartime(&R, &A, hram, S); + ge25519_pack(checkR, &R); + + /* check that R = SB - H(R,A,m)A */ + return ed25519_verify(RS, checkR, 32) ? 0 : -1; +} + +int +ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKey[32], const byte signature[64]) +{ + return ed25519_sign_open_CXX(message, messageLength, publicKey, signature); +} + +int +ed25519_sign_open(std::istream& stream, const byte publicKey[32], const byte signature[64]) +{ + return ed25519_sign_open_CXX(stream, publicKey, signature); +} + +NAMESPACE_END // Donna +NAMESPACE_END // CryptoPP + +#endif // CRYPTOPP_CURVE25519_32BIT diff --git a/external/ours/library/crypto/src/shared/original/donna_32.h b/external/ours/library/crypto/src/shared/original/donna_32.h new file mode 100755 index 000000000..dc9b91e5b --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/donna_64.cpp b/external/ours/library/crypto/src/shared/original/donna_64.cpp new file mode 100755 index 000000000..ef07a5ab1 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/donna_64.cpp @@ -0,0 +1,1815 @@ +// donna_64.cpp - 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. + +// A fair amount of duplication happens below, but we could not directly +// use curve25519 for both x25519 and ed25519. A close examination reveals +// slight differences in the implementation. For example, look at the +// two curve25519_sub functions. + +// If needed, see Moon's commit "Go back to ignoring 256th bit [sic]", +// https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658 + +#include "pch.h" + +#include "config.h" +#include "donna.h" +#include "secblock.h" +#include "sha.h" +#include "misc.h" +#include "cpu.h" + +#include +#include + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4244) +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char DONNA64_FNAME[] = __FILE__; + +ANONYMOUS_NAMESPACE_BEGIN + +// Can't use GetAlignmentOf() because of C++11 and constexpr +// Can use 'const unsigned int' because of MSVC 2013 +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +# define ALIGN_SPEC 16 +#else +# define ALIGN_SPEC 8 +#endif + +ANONYMOUS_NAMESPACE_END + +#if defined(CRYPTOPP_CURVE25519_64BIT) + +#include "donna_64.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word64; +using CryptoPP::GetWord; +using CryptoPP::PutWord; +using CryptoPP::LITTLE_ENDIAN_ORDER; + +inline word64 U8TO64_LE(const byte* p) +{ + return GetWord(false, LITTLE_ENDIAN_ORDER, p); +} + +inline void U64TO8_LE(byte* p, word64 w) +{ + PutWord(false, LITTLE_ENDIAN_ORDER, p, w); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Donna) +NAMESPACE_BEGIN(X25519) +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::sword32; +using CryptoPP::word64; +using CryptoPP::sword64; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; + +// Bring in all the symbols from the 64-bit header +using namespace CryptoPP::Donna::Arch64; + +/* out = in */ +inline void +curve25519_copy(bignum25519 out, const bignum25519 in) { + out[0] = in[0]; out[1] = in[1]; + out[2] = in[2]; out[3] = in[3]; + out[4] = in[4]; +} + +/* out = a + b */ +inline void +curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + out[3] = a[3] + b[3]; + out[4] = a[4] + b[4]; +} + +/* out = a - b */ +inline void +curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) { + out[0] = a[0] + two54m152 - b[0]; + out[1] = a[1] + two54m8 - b[1]; + out[2] = a[2] + two54m8 - b[2]; + out[3] = a[3] + two54m8 - b[3]; + out[4] = a[4] + two54m8 - b[4]; +} + +/* out = (in * scalar) */ +inline void +curve25519_scalar_product(bignum25519 out, const bignum25519 in, const word64 scalar) { + word128 a; + word64 c; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + a = ((word128) in[0]) * scalar; out[0] = (word64)a & reduce_mask_51; c = (word64)(a >> 51); + a = ((word128) in[1]) * scalar + c; out[1] = (word64)a & reduce_mask_51; c = (word64)(a >> 51); + a = ((word128) in[2]) * scalar + c; out[2] = (word64)a & reduce_mask_51; c = (word64)(a >> 51); + a = ((word128) in[3]) * scalar + c; out[3] = (word64)a & reduce_mask_51; c = (word64)(a >> 51); + a = ((word128) in[4]) * scalar + c; out[4] = (word64)a & reduce_mask_51; c = (word64)(a >> 51); + out[0] += c * 19; +#else + mul64x64_128(a, in[0], scalar) out[0] = lo128(a) & reduce_mask_51; shr128(c, a, 51); + mul64x64_128(a, in[1], scalar) add128_64(a, c) out[1] = lo128(a) & reduce_mask_51; shr128(c, a, 51); + mul64x64_128(a, in[2], scalar) add128_64(a, c) out[2] = lo128(a) & reduce_mask_51; shr128(c, a, 51); + mul64x64_128(a, in[3], scalar) add128_64(a, c) out[3] = lo128(a) & reduce_mask_51; shr128(c, a, 51); + mul64x64_128(a, in[4], scalar) add128_64(a, c) out[4] = lo128(a) & reduce_mask_51; shr128(c, a, 51); + out[0] += c * 19; +#endif +} + +/* out = a * b */ +inline void +curve25519_mul(bignum25519 out, const bignum25519 a, const bignum25519 b) { +#if !defined(CRYPTOPP_WORD128_AVAILABLE) + word128 mul; +#endif + word128 t[5]; + word64 r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c; + + r0 = b[0]; r1 = b[1]; r2 = b[2]; r3 = b[3]; r4 = b[4]; + s0 = a[0]; s1 = a[1]; s2 = a[2]; s3 = a[3]; s4 = a[4]; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + t[0] = ((word128) r0) * s0; + t[1] = ((word128) r0) * s1 + ((word128) r1) * s0; + t[2] = ((word128) r0) * s2 + ((word128) r2) * s0 + ((word128) r1) * s1; + t[3] = ((word128) r0) * s3 + ((word128) r3) * s0 + ((word128) r1) * s2 + ((word128) r2) * s1; + t[4] = ((word128) r0) * s4 + ((word128) r4) * s0 + ((word128) r3) * s1 + ((word128) r1) * s3 + ((word128) r2) * s2; +#else + mul64x64_128(t[0], r0, s0) + mul64x64_128(t[1], r0, s1) mul64x64_128(mul, r1, s0) add128(t[1], mul) + mul64x64_128(t[2], r0, s2) mul64x64_128(mul, r2, s0) add128(t[2], mul) mul64x64_128(mul, r1, s1) add128(t[2], mul) + mul64x64_128(t[3], r0, s3) mul64x64_128(mul, r3, s0) add128(t[3], mul) mul64x64_128(mul, r1, s2) add128(t[3], mul) mul64x64_128(mul, r2, s1) add128(t[3], mul) + mul64x64_128(t[4], r0, s4) mul64x64_128(mul, r4, s0) add128(t[4], mul) mul64x64_128(mul, r3, s1) add128(t[4], mul) mul64x64_128(mul, r1, s3) add128(t[4], mul) mul64x64_128(mul, r2, s2) add128(t[4], mul) +#endif + + r1 *= 19; r2 *= 19; r3 *= 19; r4 *= 19; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + t[0] += ((word128) r4) * s1 + ((word128) r1) * s4 + ((word128) r2) * s3 + ((word128) r3) * s2; + t[1] += ((word128) r4) * s2 + ((word128) r2) * s4 + ((word128) r3) * s3; + t[2] += ((word128) r4) * s3 + ((word128) r3) * s4; + t[3] += ((word128) r4) * s4; +#else + mul64x64_128(mul, r4, s1) add128(t[0], mul) mul64x64_128(mul, r1, s4) add128(t[0], mul) mul64x64_128(mul, r2, s3) add128(t[0], mul) mul64x64_128(mul, r3, s2) add128(t[0], mul) + mul64x64_128(mul, r4, s2) add128(t[1], mul) mul64x64_128(mul, r2, s4) add128(t[1], mul) mul64x64_128(mul, r3, s3) add128(t[1], mul) + mul64x64_128(mul, r4, s3) add128(t[2], mul) mul64x64_128(mul, r3, s4) add128(t[2], mul) + mul64x64_128(mul, r4, s4) add128(t[3], mul) +#endif + + r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51); + add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51); + add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51); + add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51); + add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51; + r1 += c; + + out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4; +} + +/* out = in^(2 * count) */ +inline void +curve25519_square_times(bignum25519 out, const bignum25519 in, word64 count) { +#if !defined(CRYPTOPP_WORD128_AVAILABLE) + word128 mul; +#endif + word128 t[5]; + word64 r0,r1,r2,r3,r4,c; + word64 d0,d1,d2,d4,d419; + + r0 = in[0]; r1 = in[1]; r2 = in[2]; r3 = in[3]; r4 = in[4]; + + do { + d0 = r0 * 2; d1 = r1 * 2; + d2 = r2 * 2 * 19; + d419 = r4 * 19; d4 = d419 * 2; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + t[0] = ((word128) r0) * r0 + ((word128) d4) * r1 + (((word128) d2) * (r3 )); + t[1] = ((word128) d0) * r1 + ((word128) d4) * r2 + (((word128) r3) * (r3 * 19)); + t[2] = ((word128) d0) * r2 + ((word128) r1) * r1 + (((word128) d4) * (r3 )); + t[3] = ((word128) d0) * r3 + ((word128) d1) * r2 + (((word128) r4) * (d419 )); + t[4] = ((word128) d0) * r4 + ((word128) d1) * r3 + (((word128) r2) * (r2 )); +#else + mul64x64_128(t[0], r0, r0) mul64x64_128(mul, d4, r1) add128(t[0], mul) mul64x64_128(mul, d2, r3) add128(t[0], mul) + mul64x64_128(t[1], d0, r1) mul64x64_128(mul, d4, r2) add128(t[1], mul) mul64x64_128(mul, r3, r3 * 19) add128(t[1], mul) + mul64x64_128(t[2], d0, r2) mul64x64_128(mul, r1, r1) add128(t[2], mul) mul64x64_128(mul, d4, r3) add128(t[2], mul) + mul64x64_128(t[3], d0, r3) mul64x64_128(mul, d1, r2) add128(t[3], mul) mul64x64_128(mul, r4, d419) add128(t[3], mul) + mul64x64_128(t[4], d0, r4) mul64x64_128(mul, d1, r3) add128(t[4], mul) mul64x64_128(mul, r2, r2) add128(t[4], mul) +#endif + + r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51); + add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51); + add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51); + add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51); + add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51; + r1 += c; + } while(--count); + + out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4; +} + +inline void +curve25519_square(bignum25519 out, const bignum25519 in) { +#if !defined(CRYPTOPP_WORD128_AVAILABLE) + word128 mul; +#endif + word128 t[5]; + word64 r0,r1,r2,r3,r4,c; + word64 d0,d1,d2,d4,d419; + + r0 = in[0]; r1 = in[1]; r2 = in[2]; r3 = in[3]; r4 = in[4]; + + d0 = r0 * 2; d1 = r1 * 2; + d2 = r2 * 2 * 19; + d419 = r4 * 19; d4 = d419 * 2; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + t[0] = ((word128) r0) * r0 + ((word128) d4) * r1 + (((word128) d2) * (r3 )); + t[1] = ((word128) d0) * r1 + ((word128) d4) * r2 + (((word128) r3) * (r3 * 19)); + t[2] = ((word128) d0) * r2 + ((word128) r1) * r1 + (((word128) d4) * (r3 )); + t[3] = ((word128) d0) * r3 + ((word128) d1) * r2 + (((word128) r4) * (d419 )); + t[4] = ((word128) d0) * r4 + ((word128) d1) * r3 + (((word128) r2) * (r2 )); +#else + mul64x64_128(t[0], r0, r0) mul64x64_128(mul, d4, r1) add128(t[0], mul) mul64x64_128(mul, d2, r3) add128(t[0], mul) + mul64x64_128(t[1], d0, r1) mul64x64_128(mul, d4, r2) add128(t[1], mul) mul64x64_128(mul, r3, r3 * 19) add128(t[1], mul) + mul64x64_128(t[2], d0, r2) mul64x64_128(mul, r1, r1) add128(t[2], mul) mul64x64_128(mul, d4, r3) add128(t[2], mul) + mul64x64_128(t[3], d0, r3) mul64x64_128(mul, d1, r2) add128(t[3], mul) mul64x64_128(mul, r4, d419) add128(t[3], mul) + mul64x64_128(t[4], d0, r4) mul64x64_128(mul, d1, r3) add128(t[4], mul) mul64x64_128(mul, r2, r2) add128(t[4], mul) +#endif + + r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51); + add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51); + add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51); + add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51); + add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51; + r1 += c; + + out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4; +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +inline void +curve25519_expand(bignum25519 out, const byte *in) { + word64 x0,x1,x2,x3; + GetBlock block(in); + block(x0)(x1)(x2)(x3); + + out[0] = x0 & reduce_mask_51; x0 = (x0 >> 51) | (x1 << 13); + out[1] = x0 & reduce_mask_51; x1 = (x1 >> 38) | (x2 << 26); + out[2] = x1 & reduce_mask_51; x2 = (x2 >> 25) | (x3 << 39); + out[3] = x2 & reduce_mask_51; x3 = (x3 >> 12); + out[4] = x3 & reduce_mask_51; /* ignore the top bit */ +} + +/* Take a fully reduced polynomial form number and contract it into a + * little-endian, 32-byte array + */ +inline void +curve25519_contract(byte *out, const bignum25519 input) { + word64 t[5]; + word64 f, i; + + t[0] = input[0]; + t[1] = input[1]; + t[2] = input[2]; + t[3] = input[3]; + t[4] = input[4]; + + #define curve25519_contract_carry() \ + t[1] += t[0] >> 51; t[0] &= reduce_mask_51; \ + t[2] += t[1] >> 51; t[1] &= reduce_mask_51; \ + t[3] += t[2] >> 51; t[2] &= reduce_mask_51; \ + t[4] += t[3] >> 51; t[3] &= reduce_mask_51; + + #define curve25519_contract_carry_full() curve25519_contract_carry() \ + t[0] += 19 * (t[4] >> 51); t[4] &= reduce_mask_51; + + #define curve25519_contract_carry_final() curve25519_contract_carry() \ + t[4] &= reduce_mask_51; + + curve25519_contract_carry_full() + curve25519_contract_carry_full() + + /* now t is between 0 and 2^255-1, properly carried. */ + /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ + t[0] += 19; + curve25519_contract_carry_full() + + /* now between 19 and 2^255-1 in both cases, and offset by 19. */ + t[0] += 0x8000000000000 - 19; + t[1] += 0x8000000000000 - 1; + t[2] += 0x8000000000000 - 1; + t[3] += 0x8000000000000 - 1; + t[4] += 0x8000000000000 - 1; + + /* now between 2^255 and 2^256-20, and offset by 2^255. */ + curve25519_contract_carry_final() + + #define write51full(n,shift) \ + f = ((t[n] >> shift) | (t[n+1] << (51 - shift))); \ + for (i = 0; i < 8; i++, f >>= 8) *out++ = (byte)f; + #define write51(n) write51full(n,13*n) + + write51(0) + write51(1) + write51(2) + write51(3) + + #undef curve25519_contract_carry + #undef curve25519_contract_carry_full + #undef curve25519_contract_carry_final + #undef write51full + #undef write51 +} + +/* + * Swap the contents of [qx] and [qpx] iff @swap is non-zero + */ +inline void +curve25519_swap_conditional(bignum25519 x, bignum25519 qpx, word64 iswap) { + const word64 swap = (word64)(-(sword64)iswap); + word64 x0,x1,x2,x3,x4; + + x0 = swap & (x[0] ^ qpx[0]); x[0] ^= x0; qpx[0] ^= x0; + x1 = swap & (x[1] ^ qpx[1]); x[1] ^= x1; qpx[1] ^= x1; + x2 = swap & (x[2] ^ qpx[2]); x[2] ^= x2; qpx[2] ^= x2; + x3 = swap & (x[3] ^ qpx[3]); x[3] ^= x3; qpx[3] ^= x3; + x4 = swap & (x[4] ^ qpx[4]); x[4] ^= x4; qpx[4] ^= x4; +} + +/* + * In: b = 2^5 - 2^0 + * Out: b = 2^250 - 2^0 + */ +void +curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) { + ALIGN(ALIGN_SPEC) bignum25519 t0,c; + + /* 2^5 - 2^0 */ /* b */ + /* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5); + /* 2^10 - 2^0 */ curve25519_mul(b, t0, b); + /* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10); + /* 2^20 - 2^0 */ curve25519_mul(c, t0, b); + /* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20); + /* 2^40 - 2^0 */ curve25519_mul(t0, t0, c); + /* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10); + /* 2^50 - 2^0 */ curve25519_mul(b, t0, b); + /* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50); + /* 2^100 - 2^0 */ curve25519_mul(c, t0, b); + /* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100); + /* 2^200 - 2^0 */ curve25519_mul(t0, t0, c); + /* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50); + /* 2^250 - 2^0 */ curve25519_mul(b, t0, b); +} + +/* + * z^(p - 2) = z(2^255 - 21) + */ +void +curve25519_recip(bignum25519 out, const bignum25519 z) { + ALIGN(ALIGN_SPEC) bignum25519 a, t0, b; + + /* 2 */ curve25519_square(a, z); /* a = 2 */ + /* 8 */ curve25519_square_times(t0, a, 2); + /* 9 */ curve25519_mul(b, t0, z); /* b = 9 */ + /* 11 */ curve25519_mul(a, b, a); /* a = 11 */ + /* 22 */ curve25519_square(t0, a); + /* 2^5 - 2^0 = 31 */ curve25519_mul(b, t0, b); + /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b); + /* 2^255 - 2^5 */ curve25519_square_times(b, b, 5); + /* 2^255 - 21 */ curve25519_mul(out, b, a); +} + +ANONYMOUS_NAMESPACE_END +NAMESPACE_END // X25519 +NAMESPACE_END // Donna +NAMESPACE_END // CryptoPP + +//******************************* ed25519 *******************************// + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Donna) +NAMESPACE_BEGIN(Ed25519) +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::sword32; +using CryptoPP::word64; +using CryptoPP::sword64; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; + +using CryptoPP::SHA512; + +// Bring in all the symbols from the 64-bit header +using namespace CryptoPP::Donna::Arch64; + +/* out = in */ +inline void +curve25519_copy(bignum25519 out, const bignum25519 in) { + out[0] = in[0]; out[1] = in[1]; + out[2] = in[2]; out[3] = in[3]; + out[4] = in[4]; +} + +/* out = a + b */ +inline void +curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) { + out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; + out[4] = a[4] + b[4]; +} + +/* out = a + b, where a and/or b are the result of a basic op (add,sub) */ +inline void +curve25519_add_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) { + out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; + out[4] = a[4] + b[4]; +} + +inline void +curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word64 c; + out[0] = a[0] + b[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51; + out[1] = a[1] + b[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51; + out[2] = a[2] + b[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51; + out[3] = a[3] + b[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51; + out[4] = a[4] + b[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51; + out[0] += c * 19; +} + +/* out = a - b */ +inline void +curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) { + out[0] = a[0] + twoP0 - b[0]; + out[1] = a[1] + twoP1234 - b[1]; + out[2] = a[2] + twoP1234 - b[2]; + out[3] = a[3] + twoP1234 - b[3]; + out[4] = a[4] + twoP1234 - b[4]; +} + +/* out = a - b, where a and/or b are the result of a basic op (add,sub) */ +inline void +curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) { + out[0] = a[0] + fourP0 - b[0]; + out[1] = a[1] + fourP1234 - b[1]; + out[2] = a[2] + fourP1234 - b[2]; + out[3] = a[3] + fourP1234 - b[3]; + out[4] = a[4] + fourP1234 - b[4]; +} + +inline void +curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { + word64 c; + out[0] = a[0] + fourP0 - b[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51; + out[1] = a[1] + fourP1234 - b[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51; + out[2] = a[2] + fourP1234 - b[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51; + out[3] = a[3] + fourP1234 - b[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51; + out[4] = a[4] + fourP1234 - b[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51; + out[0] += c * 19; +} + +/* out = -a */ +inline void +curve25519_neg(bignum25519 out, const bignum25519 a) { + word64 c; + out[0] = twoP0 - a[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51; + out[1] = twoP1234 - a[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51; + out[2] = twoP1234 - a[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51; + out[3] = twoP1234 - a[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51; + out[4] = twoP1234 - a[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51; + out[0] += c * 19; +} + +/* out = a * b */ +inline void +curve25519_mul(bignum25519 out, const bignum25519 in2, const bignum25519 in) { +#if !defined(CRYPTOPP_WORD128_AVAILABLE) + word128 mul; +#endif + word128 t[5]; + word64 r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c; + + r0 = in[0]; r1 = in[1]; + r2 = in[2]; r3 = in[3]; + r4 = in[4]; + + s0 = in2[0]; s1 = in2[1]; + s2 = in2[2]; s3 = in2[3]; + s4 = in2[4]; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + t[0] = ((word128) r0) * s0; + t[1] = ((word128) r0) * s1 + ((word128) r1) * s0; + t[2] = ((word128) r0) * s2 + ((word128) r2) * s0 + ((word128) r1) * s1; + t[3] = ((word128) r0) * s3 + ((word128) r3) * s0 + ((word128) r1) * s2 + ((word128) r2) * s1; + t[4] = ((word128) r0) * s4 + ((word128) r4) * s0 + ((word128) r3) * s1 + ((word128) r1) * s3 + ((word128) r2) * s2; +#else + mul64x64_128(t[0], r0, s0) + mul64x64_128(t[1], r0, s1) mul64x64_128(mul, r1, s0) add128(t[1], mul) + mul64x64_128(t[2], r0, s2) mul64x64_128(mul, r2, s0) add128(t[2], mul) mul64x64_128(mul, r1, s1) add128(t[2], mul) + mul64x64_128(t[3], r0, s3) mul64x64_128(mul, r3, s0) add128(t[3], mul) mul64x64_128(mul, r1, s2) add128(t[3], mul) mul64x64_128(mul, r2, s1) add128(t[3], mul) + mul64x64_128(t[4], r0, s4) mul64x64_128(mul, r4, s0) add128(t[4], mul) mul64x64_128(mul, r3, s1) add128(t[4], mul) mul64x64_128(mul, r1, s3) add128(t[4], mul) mul64x64_128(mul, r2, s2) add128(t[4], mul) +#endif + + r1 *= 19; r2 *= 19; + r3 *= 19; r4 *= 19; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + t[0] += ((word128) r4) * s1 + ((word128) r1) * s4 + ((word128) r2) * s3 + ((word128) r3) * s2; + t[1] += ((word128) r4) * s2 + ((word128) r2) * s4 + ((word128) r3) * s3; + t[2] += ((word128) r4) * s3 + ((word128) r3) * s4; + t[3] += ((word128) r4) * s4; +#else + mul64x64_128(mul, r4, s1) add128(t[0], mul) mul64x64_128(mul, r1, s4) add128(t[0], mul) mul64x64_128(mul, r2, s3) add128(t[0], mul) mul64x64_128(mul, r3, s2) add128(t[0], mul) + mul64x64_128(mul, r4, s2) add128(t[1], mul) mul64x64_128(mul, r2, s4) add128(t[1], mul) mul64x64_128(mul, r3, s3) add128(t[1], mul) + mul64x64_128(mul, r4, s3) add128(t[2], mul) mul64x64_128(mul, r3, s4) add128(t[2], mul) + mul64x64_128(mul, r4, s4) add128(t[3], mul) +#endif + + r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51); + add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51); + add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51); + add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51); + add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51; + r1 += c; + + out[0] = r0; out[1] = r1; + out[2] = r2; out[3] = r3; + out[4] = r4; +} + +void +curve25519_mul_noinline(bignum25519 out, const bignum25519 in2, const bignum25519 in) { + curve25519_mul(out, in2, in); +} + +/* out = in^(2 * count) */ +void +curve25519_square_times(bignum25519 out, const bignum25519 in, word64 count) { +#if !defined(CRYPTOPP_WORD128_AVAILABLE) + word128 mul; +#endif + word128 t[5]; + word64 r0,r1,r2,r3,r4,c; + word64 d0,d1,d2,d4,d419; + + r0 = in[0]; r1 = in[1]; + r2 = in[2]; r3 = in[3]; + r4 = in[4]; + + do { + d0 = r0 * 2; + d1 = r1 * 2; + d2 = r2 * 2 * 19; + d419 = r4 * 19; + d4 = d419 * 2; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + t[0] = ((word128) r0) * r0 + ((word128) d4) * r1 + (((word128) d2) * (r3 )); + t[1] = ((word128) d0) * r1 + ((word128) d4) * r2 + (((word128) r3) * (r3 * 19)); + t[2] = ((word128) d0) * r2 + ((word128) r1) * r1 + (((word128) d4) * (r3 )); + t[3] = ((word128) d0) * r3 + ((word128) d1) * r2 + (((word128) r4) * (d419 )); + t[4] = ((word128) d0) * r4 + ((word128) d1) * r3 + (((word128) r2) * (r2 )); +#else + mul64x64_128(t[0], r0, r0) mul64x64_128(mul, d4, r1) add128(t[0], mul) mul64x64_128(mul, d2, r3) add128(t[0], mul) + mul64x64_128(t[1], d0, r1) mul64x64_128(mul, d4, r2) add128(t[1], mul) mul64x64_128(mul, r3, r3 * 19) add128(t[1], mul) + mul64x64_128(t[2], d0, r2) mul64x64_128(mul, r1, r1) add128(t[2], mul) mul64x64_128(mul, d4, r3) add128(t[2], mul) + mul64x64_128(t[3], d0, r3) mul64x64_128(mul, d1, r2) add128(t[3], mul) mul64x64_128(mul, r4, d419) add128(t[3], mul) + mul64x64_128(t[4], d0, r4) mul64x64_128(mul, d1, r3) add128(t[4], mul) mul64x64_128(mul, r2, r2) add128(t[4], mul) +#endif + + r0 = lo128(t[0]) & reduce_mask_51; + r1 = lo128(t[1]) & reduce_mask_51; shl128(c, t[0], 13); r1 += c; + r2 = lo128(t[2]) & reduce_mask_51; shl128(c, t[1], 13); r2 += c; + r3 = lo128(t[3]) & reduce_mask_51; shl128(c, t[2], 13); r3 += c; + r4 = lo128(t[4]) & reduce_mask_51; shl128(c, t[3], 13); r4 += c; + shl128(c, t[4], 13); r0 += c * 19; + c = r0 >> 51; r0 &= reduce_mask_51; + r1 += c ; c = r1 >> 51; r1 &= reduce_mask_51; + r2 += c ; c = r2 >> 51; r2 &= reduce_mask_51; + r3 += c ; c = r3 >> 51; r3 &= reduce_mask_51; + r4 += c ; c = r4 >> 51; r4 &= reduce_mask_51; + r0 += c * 19; + } while(--count); + + out[0] = r0; out[1] = r1; + out[2] = r2; out[3] = r3; + out[4] = r4; +} + +inline void +curve25519_square(bignum25519 out, const bignum25519 in) { +#if !defined(CRYPTOPP_WORD128_AVAILABLE) + word128 mul; +#endif + word128 t[5]; + word64 r0,r1,r2,r3,r4,c; + word64 d0,d1,d2,d4,d419; + + r0 = in[0]; r1 = in[1]; + r2 = in[2]; r3 = in[3]; + r4 = in[4]; + + d0 = r0 * 2; d1 = r1 * 2; + d2 = r2 * 2 * 19; + d419 = r4 * 19; + d4 = d419 * 2; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + t[0] = ((word128) r0) * r0 + ((word128) d4) * r1 + (((word128) d2) * (r3 )); + t[1] = ((word128) d0) * r1 + ((word128) d4) * r2 + (((word128) r3) * (r3 * 19)); + t[2] = ((word128) d0) * r2 + ((word128) r1) * r1 + (((word128) d4) * (r3 )); + t[3] = ((word128) d0) * r3 + ((word128) d1) * r2 + (((word128) r4) * (d419 )); + t[4] = ((word128) d0) * r4 + ((word128) d1) * r3 + (((word128) r2) * (r2 )); +#else + mul64x64_128(t[0], r0, r0) mul64x64_128(mul, d4, r1) add128(t[0], mul) mul64x64_128(mul, d2, r3) add128(t[0], mul) + mul64x64_128(t[1], d0, r1) mul64x64_128(mul, d4, r2) add128(t[1], mul) mul64x64_128(mul, r3, r3 * 19) add128(t[1], mul) + mul64x64_128(t[2], d0, r2) mul64x64_128(mul, r1, r1) add128(t[2], mul) mul64x64_128(mul, d4, r3) add128(t[2], mul) + mul64x64_128(t[3], d0, r3) mul64x64_128(mul, d1, r2) add128(t[3], mul) mul64x64_128(mul, r4, d419) add128(t[3], mul) + mul64x64_128(t[4], d0, r4) mul64x64_128(mul, d1, r3) add128(t[4], mul) mul64x64_128(mul, r2, r2) add128(t[4], mul) +#endif + + r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51); + add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51); + add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51); + add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51); + add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51; + r1 += c; + + out[0] = r0; out[1] = r1; + out[2] = r2; out[3] = r3; + out[4] = r4; +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +inline void +curve25519_expand(bignum25519 out, const byte *in) { + word64 x0,x1,x2,x3; + GetBlock block(in); + block(x0)(x1)(x2)(x3); + + out[0] = x0 & reduce_mask_51; x0 = (x0 >> 51) | (x1 << 13); + out[1] = x0 & reduce_mask_51; x1 = (x1 >> 38) | (x2 << 26); + out[2] = x1 & reduce_mask_51; x2 = (x2 >> 25) | (x3 << 39); + out[3] = x2 & reduce_mask_51; x3 = (x3 >> 12); + out[4] = x3 & reduce_mask_51; +} + +/* Take a fully reduced polynomial form number and contract it into a + * little-endian, 32-byte array + */ +inline void +curve25519_contract(byte *out, const bignum25519 input) { + word64 t[5]; + word64 f, i; + + t[0] = input[0]; + t[1] = input[1]; + t[2] = input[2]; + t[3] = input[3]; + t[4] = input[4]; + + #define curve25519_contract_carry() \ + t[1] += t[0] >> 51; t[0] &= reduce_mask_51; \ + t[2] += t[1] >> 51; t[1] &= reduce_mask_51; \ + t[3] += t[2] >> 51; t[2] &= reduce_mask_51; \ + t[4] += t[3] >> 51; t[3] &= reduce_mask_51; + + #define curve25519_contract_carry_full() curve25519_contract_carry() \ + t[0] += 19 * (t[4] >> 51); t[4] &= reduce_mask_51; + + #define curve25519_contract_carry_final() curve25519_contract_carry() \ + t[4] &= reduce_mask_51; + + curve25519_contract_carry_full() + curve25519_contract_carry_full() + + /* now t is between 0 and 2^255-1, properly carried. */ + /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ + t[0] += 19; + curve25519_contract_carry_full() + + /* now between 19 and 2^255-1 in both cases, and offset by 19. */ + t[0] += (reduce_mask_51 + 1) - 19; + t[1] += (reduce_mask_51 + 1) - 1; + t[2] += (reduce_mask_51 + 1) - 1; + t[3] += (reduce_mask_51 + 1) - 1; + t[4] += (reduce_mask_51 + 1) - 1; + + /* now between 2^255 and 2^256-20, and offset by 2^255. */ + curve25519_contract_carry_final() + + #define write51full(n,shift) \ + f = ((t[n] >> shift) | (t[n+1] << (51 - shift))); \ + for (i = 0; i < 8; i++, f >>= 8) *out++ = (byte)f; + #define write51(n) write51full(n,13*n) + write51(0) + write51(1) + write51(2) + write51(3) +} + +#if !defined(ED25519_GCC_64BIT_CHOOSE) + +/* out = (flag) ? in : out */ +inline void +curve25519_move_conditional_bytes(byte out[96], const byte in[96], word64 flag) +{ + // TODO: enable this code path once we can test and benchmark it. + // It is about 24 insns shorter, it avoids punning which may be UB, + // and it is guaranteed constant time. +#if defined(__GNUC__) && defined(__x86_64__) && 0 + const word32 iter = 96/sizeof(word64); + word64* outq = reinterpret_cast(out); + const word64* inq = reinterpret_cast(in); + word64 idx=0, val; + + __asm__ __volatile__ ( + ".att_syntax ;\n" + "cmpq $0, %[flag] ;\n" // compare, set ZERO flag + "movq %[iter], %%rcx ;\n" // load iteration count + "1: ;\n" + " movq (%[idx],%[out]), %[val] ;\n" // val = out[idx] + " cmovnzq (%[idx],%[in]), %[val] ;\n" // copy in[idx] to val if NZ + " movq %[val], (%[idx],%[out]) ;\n" // out[idx] = val + " leaq 8(%[idx]), %[idx] ;\n" // increment index + " loopnz 1b ;\n" // does not affect flags + : [out] "+S" (outq), [in] "+D" (inq), + [idx] "+b" (idx), [val] "=r" (val) + : [flag] "g" (flag), [iter] "I" (iter) + : "rcx", "memory", "cc" + ); +#else + const word64 nb = flag - 1, b = ~nb; + const word64 *inq = (const word64 *)(const void*)in; + word64 *outq = (word64 *)(void *)out; + outq[0] = (outq[0] & nb) | (inq[0] & b); + outq[1] = (outq[1] & nb) | (inq[1] & b); + outq[2] = (outq[2] & nb) | (inq[2] & b); + outq[3] = (outq[3] & nb) | (inq[3] & b); + outq[4] = (outq[4] & nb) | (inq[4] & b); + outq[5] = (outq[5] & nb) | (inq[5] & b); + outq[6] = (outq[6] & nb) | (inq[6] & b); + outq[7] = (outq[7] & nb) | (inq[7] & b); + outq[8] = (outq[8] & nb) | (inq[8] & b); + outq[9] = (outq[9] & nb) | (inq[9] & b); + outq[10] = (outq[10] & nb) | (inq[10] & b); + outq[11] = (outq[11] & nb) | (inq[11] & b); +#endif +} + +/* if (iswap) swap(a, b) */ +inline void +curve25519_swap_conditional(bignum25519 a, bignum25519 b, word64 iswap) { + const word64 swap = (word64)(-(sword64)iswap); + word64 x0,x1,x2,x3,x4; + + x0 = swap & (a[0] ^ b[0]); a[0] ^= x0; b[0] ^= x0; + x1 = swap & (a[1] ^ b[1]); a[1] ^= x1; b[1] ^= x1; + x2 = swap & (a[2] ^ b[2]); a[2] ^= x2; b[2] ^= x2; + x3 = swap & (a[3] ^ b[3]); a[3] ^= x3; b[3] ^= x3; + x4 = swap & (a[4] ^ b[4]); a[4] ^= x4; b[4] ^= x4; +} + +#endif /* ED25519_GCC_64BIT_CHOOSE */ + +// ************************************************************************************ + +inline void +ed25519_hash(byte *hash, const byte *in, size_t inlen) { + SHA512().CalculateDigest(hash, in, inlen); +} + +inline void +ed25519_extsk(hash_512bits extsk, const byte sk[32]) { + ed25519_hash(extsk, sk, 32); + extsk[0] &= 248; + extsk[31] &= 127; + extsk[31] |= 64; +} + +void +UpdateFromStream(HashTransformation& hash, std::istream& stream) +{ + SecByteBlock block(4096); + while (stream.read((char*)block.begin(), block.size())) + hash.Update(block, block.size()); + + std::streamsize rem = stream.gcount(); + if (rem) + hash.Update(block, rem); + + block.SetMark(0); +} + +void +ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], const byte *m, size_t mlen) { + SHA512 hash; + hash.Update(RS, 32); + hash.Update(pk, 32); + hash.Update(m, mlen); + hash.Final(hram); +} + +void +ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], std::istream& stream) { + SHA512 hash; + hash.Update(RS, 32); + hash.Update(pk, 32); + UpdateFromStream(hash, stream); + hash.Final(hram); +} + +bignum256modm_element_t +lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) { + return (a - b) >> 63; +} + +void +reduce256_modm(bignum256modm r) { + bignum256modm t; + bignum256modm_element_t b = 0, pb, mask; + + /* t = r - m */ + pb = 0; + pb += modm_m[0]; b = lt_modm(r[0], pb); t[0] = (r[0] - pb + (b << 56)); pb = b; + pb += modm_m[1]; b = lt_modm(r[1], pb); t[1] = (r[1] - pb + (b << 56)); pb = b; + pb += modm_m[2]; b = lt_modm(r[2], pb); t[2] = (r[2] - pb + (b << 56)); pb = b; + pb += modm_m[3]; b = lt_modm(r[3], pb); t[3] = (r[3] - pb + (b << 56)); pb = b; + pb += modm_m[4]; b = lt_modm(r[4], pb); t[4] = (r[4] - pb + (b << 32)); + + /* keep r if r was smaller than m */ + mask = b - 1; + + r[0] ^= mask & (r[0] ^ t[0]); + r[1] ^= mask & (r[1] ^ t[1]); + r[2] ^= mask & (r[2] ^ t[2]); + r[3] ^= mask & (r[3] ^ t[3]); + r[4] ^= mask & (r[4] ^ t[4]); +} + +void +barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256modm r1) { + bignum256modm q3, r2; + word128 c, mul; + bignum256modm_element_t f, b, pb; + + /* q1 = x >> 248 = 264 bits = 5 56 bit elements + q2 = mu * q1 + q3 = (q2 / 256(32+1)) = q2 / (2^8)^(32+1) = q2 >> 264 */ + mul64x64_128(c, modm_mu[0], q1[3]) mul64x64_128(mul, modm_mu[3], q1[0]) add128(c, mul) mul64x64_128(mul, modm_mu[1], q1[2]) add128(c, mul) mul64x64_128(mul, modm_mu[2], q1[1]) add128(c, mul) shr128(f, c, 56); + mul64x64_128(c, modm_mu[0], q1[4]) add128_64(c, f) mul64x64_128(mul, modm_mu[4], q1[0]) add128(c, mul) mul64x64_128(mul, modm_mu[3], q1[1]) add128(c, mul) mul64x64_128(mul, modm_mu[1], q1[3]) add128(c, mul) mul64x64_128(mul, modm_mu[2], q1[2]) add128(c, mul) + f = lo128(c); q3[0] = (f >> 40) & 0xffff; shr128(f, c, 56); + mul64x64_128(c, modm_mu[4], q1[1]) add128_64(c, f) mul64x64_128(mul, modm_mu[1], q1[4]) add128(c, mul) mul64x64_128(mul, modm_mu[2], q1[3]) add128(c, mul) mul64x64_128(mul, modm_mu[3], q1[2]) add128(c, mul) + f = lo128(c); q3[0] |= (f << 16) & 0xffffffffffffff; q3[1] = (f >> 40) & 0xffff; shr128(f, c, 56); + mul64x64_128(c, modm_mu[4], q1[2]) add128_64(c, f) mul64x64_128(mul, modm_mu[2], q1[4]) add128(c, mul) mul64x64_128(mul, modm_mu[3], q1[3]) add128(c, mul) + f = lo128(c); q3[1] |= (f << 16) & 0xffffffffffffff; q3[2] = (f >> 40) & 0xffff; shr128(f, c, 56); + mul64x64_128(c, modm_mu[4], q1[3]) add128_64(c, f) mul64x64_128(mul, modm_mu[3], q1[4]) add128(c, mul) + f = lo128(c); q3[2] |= (f << 16) & 0xffffffffffffff; q3[3] = (f >> 40) & 0xffff; shr128(f, c, 56); + mul64x64_128(c, modm_mu[4], q1[4]) add128_64(c, f) + f = lo128(c); q3[3] |= (f << 16) & 0xffffffffffffff; q3[4] = (f >> 40) & 0xffff; shr128(f, c, 56); + q3[4] |= (f << 16); + + mul64x64_128(c, modm_m[0], q3[0]) + r2[0] = lo128(c) & 0xffffffffffffff; shr128(f, c, 56); + mul64x64_128(c, modm_m[0], q3[1]) add128_64(c, f) mul64x64_128(mul, modm_m[1], q3[0]) add128(c, mul) + r2[1] = lo128(c) & 0xffffffffffffff; shr128(f, c, 56); + mul64x64_128(c, modm_m[0], q3[2]) add128_64(c, f) mul64x64_128(mul, modm_m[2], q3[0]) add128(c, mul) mul64x64_128(mul, modm_m[1], q3[1]) add128(c, mul) + r2[2] = lo128(c) & 0xffffffffffffff; shr128(f, c, 56); + mul64x64_128(c, modm_m[0], q3[3]) add128_64(c, f) mul64x64_128(mul, modm_m[3], q3[0]) add128(c, mul) mul64x64_128(mul, modm_m[1], q3[2]) add128(c, mul) mul64x64_128(mul, modm_m[2], q3[1]) add128(c, mul) + r2[3] = lo128(c) & 0xffffffffffffff; shr128(f, c, 56); + mul64x64_128(c, modm_m[0], q3[4]) add128_64(c, f) mul64x64_128(mul, modm_m[4], q3[0]) add128(c, mul) mul64x64_128(mul, modm_m[3], q3[1]) add128(c, mul) mul64x64_128(mul, modm_m[1], q3[3]) add128(c, mul) mul64x64_128(mul, modm_m[2], q3[2]) add128(c, mul) + r2[4] = lo128(c) & 0x0000ffffffffff; + + pb = 0; + pb += r2[0]; b = lt_modm(r1[0], pb); r[0] = (r1[0] - pb + (b << 56)); pb = b; + pb += r2[1]; b = lt_modm(r1[1], pb); r[1] = (r1[1] - pb + (b << 56)); pb = b; + pb += r2[2]; b = lt_modm(r1[2], pb); r[2] = (r1[2] - pb + (b << 56)); pb = b; + pb += r2[3]; b = lt_modm(r1[3], pb); r[3] = (r1[3] - pb + (b << 56)); pb = b; + pb += r2[4]; b = lt_modm(r1[4], pb); r[4] = (r1[4] - pb + (b << 40)); + + reduce256_modm(r); + reduce256_modm(r); +} + +void +add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) { + bignum256modm_element_t c; + + c = x[0] + y[0]; r[0] = c & 0xffffffffffffff; c >>= 56; + c += x[1] + y[1]; r[1] = c & 0xffffffffffffff; c >>= 56; + c += x[2] + y[2]; r[2] = c & 0xffffffffffffff; c >>= 56; + c += x[3] + y[3]; r[3] = c & 0xffffffffffffff; c >>= 56; + c += x[4] + y[4]; r[4] = c; + + reduce256_modm(r); +} + +void +mul256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) { + bignum256modm q1, r1; + word128 c, mul; + bignum256modm_element_t f; + + mul64x64_128(c, x[0], y[0]) + f = lo128(c); r1[0] = f & 0xffffffffffffff; shr128(f, c, 56); + mul64x64_128(c, x[0], y[1]) add128_64(c, f) mul64x64_128(mul, x[1], y[0]) add128(c, mul) + f = lo128(c); r1[1] = f & 0xffffffffffffff; shr128(f, c, 56); + mul64x64_128(c, x[0], y[2]) add128_64(c, f) mul64x64_128(mul, x[2], y[0]) add128(c, mul) mul64x64_128(mul, x[1], y[1]) add128(c, mul) + f = lo128(c); r1[2] = f & 0xffffffffffffff; shr128(f, c, 56); + mul64x64_128(c, x[0], y[3]) add128_64(c, f) mul64x64_128(mul, x[3], y[0]) add128(c, mul) mul64x64_128(mul, x[1], y[2]) add128(c, mul) mul64x64_128(mul, x[2], y[1]) add128(c, mul) + f = lo128(c); r1[3] = f & 0xffffffffffffff; shr128(f, c, 56); + mul64x64_128(c, x[0], y[4]) add128_64(c, f) mul64x64_128(mul, x[4], y[0]) add128(c, mul) mul64x64_128(mul, x[3], y[1]) add128(c, mul) mul64x64_128(mul, x[1], y[3]) add128(c, mul) mul64x64_128(mul, x[2], y[2]) add128(c, mul) + f = lo128(c); r1[4] = f & 0x0000ffffffffff; q1[0] = (f >> 24) & 0xffffffff; shr128(f, c, 56); + mul64x64_128(c, x[4], y[1]) add128_64(c, f) mul64x64_128(mul, x[1], y[4]) add128(c, mul) mul64x64_128(mul, x[2], y[3]) add128(c, mul) mul64x64_128(mul, x[3], y[2]) add128(c, mul) + f = lo128(c); q1[0] |= (f << 32) & 0xffffffffffffff; q1[1] = (f >> 24) & 0xffffffff; shr128(f, c, 56); + mul64x64_128(c, x[4], y[2]) add128_64(c, f) mul64x64_128(mul, x[2], y[4]) add128(c, mul) mul64x64_128(mul, x[3], y[3]) add128(c, mul) + f = lo128(c); q1[1] |= (f << 32) & 0xffffffffffffff; q1[2] = (f >> 24) & 0xffffffff; shr128(f, c, 56); + mul64x64_128(c, x[4], y[3]) add128_64(c, f) mul64x64_128(mul, x[3], y[4]) add128(c, mul) + f = lo128(c); q1[2] |= (f << 32) & 0xffffffffffffff; q1[3] = (f >> 24) & 0xffffffff; shr128(f, c, 56); + mul64x64_128(c, x[4], y[4]) add128_64(c, f) + f = lo128(c); q1[3] |= (f << 32) & 0xffffffffffffff; q1[4] = (f >> 24) & 0xffffffff; shr128(f, c, 56); + q1[4] |= (f << 32); + + barrett_reduce256_modm(r, q1, r1); +} + +void +expand256_modm(bignum256modm out, const byte *in, size_t len) { + byte work[64] = {0}; + bignum256modm_element_t x[16]; + bignum256modm q1; + + memcpy(work, in, len); + x[0] = U8TO64_LE(work + 0); + x[1] = U8TO64_LE(work + 8); + x[2] = U8TO64_LE(work + 16); + x[3] = U8TO64_LE(work + 24); + x[4] = U8TO64_LE(work + 32); + x[5] = U8TO64_LE(work + 40); + x[6] = U8TO64_LE(work + 48); + x[7] = U8TO64_LE(work + 56); + + /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) */ + out[0] = ( x[0]) & 0xffffffffffffff; + out[1] = ((x[ 0] >> 56) | (x[ 1] << 8)) & 0xffffffffffffff; + out[2] = ((x[ 1] >> 48) | (x[ 2] << 16)) & 0xffffffffffffff; + out[3] = ((x[ 2] >> 40) | (x[ 3] << 24)) & 0xffffffffffffff; + out[4] = ((x[ 3] >> 32) | (x[ 4] << 32)) & 0x0000ffffffffff; + + /* under 252 bits, no need to reduce */ + if (len < 32) + return; + + /* q1 = x >> 248 = 264 bits */ + q1[0] = ((x[ 3] >> 56) | (x[ 4] << 8)) & 0xffffffffffffff; + q1[1] = ((x[ 4] >> 48) | (x[ 5] << 16)) & 0xffffffffffffff; + q1[2] = ((x[ 5] >> 40) | (x[ 6] << 24)) & 0xffffffffffffff; + q1[3] = ((x[ 6] >> 32) | (x[ 7] << 32)) & 0xffffffffffffff; + q1[4] = ((x[ 7] >> 24) ); + + barrett_reduce256_modm(out, q1, out); +} + +void +expand_raw256_modm(bignum256modm out, const byte in[32]) { + bignum256modm_element_t x[4]; + + x[0] = U8TO64_LE(in + 0); + x[1] = U8TO64_LE(in + 8); + x[2] = U8TO64_LE(in + 16); + x[3] = U8TO64_LE(in + 24); + + out[0] = ( x[0]) & 0xffffffffffffff; + out[1] = ((x[ 0] >> 56) | (x[ 1] << 8)) & 0xffffffffffffff; + out[2] = ((x[ 1] >> 48) | (x[ 2] << 16)) & 0xffffffffffffff; + out[3] = ((x[ 2] >> 40) | (x[ 3] << 24)) & 0xffffffffffffff; + out[4] = ((x[ 3] >> 32) ) & 0x000000ffffffff; +} + +void +contract256_modm(byte out[32], const bignum256modm in) { + U64TO8_LE(out + 0, (in[0] ) | (in[1] << 56)); + U64TO8_LE(out + 8, (in[1] >> 8) | (in[2] << 48)); + U64TO8_LE(out + 16, (in[2] >> 16) | (in[3] << 40)); + U64TO8_LE(out + 24, (in[3] >> 24) | (in[4] << 32)); +} + +void +contract256_window4_modm(signed char r[64], const bignum256modm in) { + char carry; + signed char *quads = r; + bignum256modm_element_t i, j, v, m; + + for (i = 0; i < 5; i++) { + v = in[i]; + m = (i == 4) ? 8 : 14; + for (j = 0; j < m; j++) { + *quads++ = (v & 15); + v >>= 4; + } + } + + /* making it signed */ + carry = 0; + for(i = 0; i < 63; i++) { + r[i] += carry; + r[i+1] += (r[i] >> 4); + r[i] &= 15; + carry = (r[i] >> 3); + r[i] -= (carry << 4); + } + r[63] += carry; +} + +void +contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int windowsize) { + int i,j,k,b; + int m = (1 << (windowsize - 1)) - 1, soplen = 256; + signed char *bits = r; + bignum256modm_element_t v; + + /* first put the binary expansion into r */ + for (i = 0; i < 4; i++) { + v = s[i]; + for (j = 0; j < 56; j++, v >>= 1) + *bits++ = (v & 1); + } + v = s[4]; + for (j = 0; j < 32; j++, v >>= 1) + *bits++ = (v & 1); + + /* Making it sliding window */ + for (j = 0; j < soplen; j++) { + if (!r[j]) + continue; + + for (b = 1; (b < (soplen - j)) && (b <= 6); b++) { + if ((r[j] + (r[j + b] << b)) <= m) { + r[j] += r[j + b] << b; + r[j + b] = 0; + } else if ((r[j] - (r[j + b] << b)) >= -m) { + r[j] -= r[j + b] << b; + for (k = j + b; k < soplen; k++) { + if (!r[k]) { + r[k] = 1; + break; + } + r[k] = 0; + } + } else if (r[j + b]) { + break; + } + } + } +} + +/* + * In: b = 2^5 - 2^0 + * Out: b = 2^250 - 2^0 + */ +void +curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) { + ALIGN(ALIGN_SPEC) bignum25519 t0,c; + + /* 2^5 - 2^0 */ /* b */ + /* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5); + /* 2^10 - 2^0 */ curve25519_mul_noinline(b, t0, b); + /* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10); + /* 2^20 - 2^0 */ curve25519_mul_noinline(c, t0, b); + /* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20); + /* 2^40 - 2^0 */ curve25519_mul_noinline(t0, t0, c); + /* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10); + /* 2^50 - 2^0 */ curve25519_mul_noinline(b, t0, b); + /* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50); + /* 2^100 - 2^0 */ curve25519_mul_noinline(c, t0, b); + /* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100); + /* 2^200 - 2^0 */ curve25519_mul_noinline(t0, t0, c); + /* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50); + /* 2^250 - 2^0 */ curve25519_mul_noinline(b, t0, b); +} + +/* + * z^(p - 2) = z(2^255 - 21) + */ +void +curve25519_recip(bignum25519 out, const bignum25519 z) { + ALIGN(ALIGN_SPEC) bignum25519 a,t0,b; + + /* 2 */ curve25519_square_times(a, z, 1); /* a = 2 */ + /* 8 */ curve25519_square_times(t0, a, 2); + /* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */ + /* 11 */ curve25519_mul_noinline(a, b, a); /* a = 11 */ + /* 22 */ curve25519_square_times(t0, a, 1); + /* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b); + /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b); + /* 2^255 - 2^5 */ curve25519_square_times(b, b, 5); + /* 2^255 - 21 */ curve25519_mul_noinline(out, b, a); +} + +/* + * z^((p-5)/8) = z^(2^252 - 3) + */ +void +curve25519_pow_two252m3(bignum25519 two252m3, const bignum25519 z) { + ALIGN(ALIGN_SPEC) bignum25519 b,c,t0; + + /* 2 */ curve25519_square_times(c, z, 1); /* c = 2 */ + /* 8 */ curve25519_square_times(t0, c, 2); /* t0 = 8 */ + /* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */ + /* 11 */ curve25519_mul_noinline(c, b, c); /* c = 11 */ + /* 22 */ curve25519_square_times(t0, c, 1); + /* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b); + /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b); + /* 2^252 - 2^2 */ curve25519_square_times(b, b, 2); + /* 2^252 - 3 */ curve25519_mul_noinline(two252m3, b, z); +} + +inline void +ge25519_p1p1_to_partial(ge25519 *r, const ge25519_p1p1 *p) { + curve25519_mul(r->x, p->x, p->t); + curve25519_mul(r->y, p->y, p->z); + curve25519_mul(r->z, p->z, p->t); +} + +inline void +ge25519_p1p1_to_full(ge25519 *r, const ge25519_p1p1 *p) { + curve25519_mul(r->x, p->x, p->t); + curve25519_mul(r->y, p->y, p->z); + curve25519_mul(r->z, p->z, p->t); + curve25519_mul(r->t, p->x, p->y); +} + +void +ge25519_full_to_pniels(ge25519_pniels *p, const ge25519 *r) { + curve25519_sub(p->ysubx, r->y, r->x); + curve25519_add(p->xaddy, r->y, r->x); + curve25519_copy(p->z, r->z); + curve25519_mul(p->t2d, r->t, ge25519_ec2d); +} + +void +ge25519_add_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519 *q) { + bignum25519 a,b,c,d,t,u; + + curve25519_sub(a, p->y, p->x); + curve25519_add(b, p->y, p->x); + curve25519_sub(t, q->y, q->x); + curve25519_add(u, q->y, q->x); + curve25519_mul(a, a, t); + curve25519_mul(b, b, u); + curve25519_mul(c, p->t, q->t); + curve25519_mul(c, c, ge25519_ec2d); + curve25519_mul(d, p->z, q->z); + curve25519_add(d, d, d); + curve25519_sub(r->x, b, a); + curve25519_add(r->y, b, a); + curve25519_add_after_basic(r->z, d, c); + curve25519_sub_after_basic(r->t, d, c); +} + +void +ge25519_double_p1p1(ge25519_p1p1 *r, const ge25519 *p) { + bignum25519 a,b,c; + + curve25519_square(a, p->x); + curve25519_square(b, p->y); + curve25519_square(c, p->z); + curve25519_add_reduce(c, c, c); + curve25519_add(r->x, p->x, p->y); + curve25519_square(r->x, r->x); + curve25519_add(r->y, b, a); + curve25519_sub(r->z, b, a); + curve25519_sub_after_basic(r->x, r->x, r->y); + curve25519_sub_after_basic(r->t, c, r->z); +} + +void +ge25519_nielsadd2_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_niels *q, byte signbit) { + const bignum25519 *qb = (const bignum25519 *)q; + bignum25519 *rb = (bignum25519 *)r; + bignum25519 a,b,c; + + curve25519_sub(a, p->y, p->x); + curve25519_add(b, p->y, p->x); + curve25519_mul(a, a, qb[signbit]); /* x for +, y for - */ + curve25519_mul(r->x, b, qb[signbit^1]); /* y for +, x for - */ + curve25519_add(r->y, r->x, a); + curve25519_sub(r->x, r->x, a); + curve25519_mul(c, p->t, q->t2d); + curve25519_add_reduce(r->t, p->z, p->z); + curve25519_copy(r->z, r->t); + curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */ + curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */ +} + +void +ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_pniels *q, byte signbit) { + const bignum25519 *qb = (const bignum25519 *)q; + bignum25519 *rb = (bignum25519 *)r; + bignum25519 a,b,c; + + curve25519_sub(a, p->y, p->x); + curve25519_add(b, p->y, p->x); + curve25519_mul(a, a, qb[signbit]); /* ysubx for +, xaddy for - */ + curve25519_mul(r->x, b, qb[signbit^1]); /* xaddy for +, ysubx for - */ + curve25519_add(r->y, r->x, a); + curve25519_sub(r->x, r->x, a); + curve25519_mul(c, p->t, q->t2d); + curve25519_mul(r->t, p->z, q->z); + curve25519_add_reduce(r->t, r->t, r->t); + curve25519_copy(r->z, r->t); + curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */ + curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */ +} + +void +ge25519_double_partial(ge25519 *r, const ge25519 *p) { + ge25519_p1p1 t; + ge25519_double_p1p1(&t, p); + ge25519_p1p1_to_partial(r, &t); +} + +void +ge25519_double(ge25519 *r, const ge25519 *p) { + ge25519_p1p1 t; + ge25519_double_p1p1(&t, p); + ge25519_p1p1_to_full(r, &t); +} + +void +ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q) { + ge25519_p1p1 t; + ge25519_add_p1p1(&t, p, q); + ge25519_p1p1_to_full(r, &t); +} + +void +ge25519_nielsadd2(ge25519 *r, const ge25519_niels *q) { + bignum25519 a,b,c,e,f,g,h; + + curve25519_sub(a, r->y, r->x); + curve25519_add(b, r->y, r->x); + curve25519_mul(a, a, q->ysubx); + curve25519_mul(e, b, q->xaddy); + curve25519_add(h, e, a); + curve25519_sub(e, e, a); + curve25519_mul(c, r->t, q->t2d); + curve25519_add(f, r->z, r->z); + curve25519_add_after_basic(g, f, c); + curve25519_sub_after_basic(f, f, c); + curve25519_mul(r->x, e, f); + curve25519_mul(r->y, h, g); + curve25519_mul(r->z, g, f); + curve25519_mul(r->t, e, h); +} + +void +ge25519_pnielsadd(ge25519_pniels *r, const ge25519 *p, const ge25519_pniels *q) { + bignum25519 a,b,c,x,y,z,t; + + curve25519_sub(a, p->y, p->x); + curve25519_add(b, p->y, p->x); + curve25519_mul(a, a, q->ysubx); + curve25519_mul(x, b, q->xaddy); + curve25519_add(y, x, a); + curve25519_sub(x, x, a); + curve25519_mul(c, p->t, q->t2d); + curve25519_mul(t, p->z, q->z); + curve25519_add(t, t, t); + curve25519_add_after_basic(z, t, c); + curve25519_sub_after_basic(t, t, c); + curve25519_mul(r->xaddy, x, t); + curve25519_mul(r->ysubx, y, z); + curve25519_mul(r->z, z, t); + curve25519_mul(r->t2d, x, y); + curve25519_copy(y, r->ysubx); + curve25519_sub(r->ysubx, r->ysubx, r->xaddy); + curve25519_add(r->xaddy, r->xaddy, y); + curve25519_mul(r->t2d, r->t2d, ge25519_ec2d); +} + +void +ge25519_pack(byte r[32], const ge25519 *p) { + bignum25519 tx, ty, zi; + byte parity[32]; + curve25519_recip(zi, p->z); + curve25519_mul(tx, p->x, zi); + curve25519_mul(ty, p->y, zi); + curve25519_contract(r, ty); + curve25519_contract(parity, tx); + r[31] ^= ((parity[0] & 1) << 7); +} + +int +ed25519_verify(const byte *x, const byte *y, size_t len) { + size_t differentbits = 0; + while (len--) + differentbits |= (*x++ ^ *y++); + return (int) (1 & ((differentbits - 1) >> 8)); +} + +int +ge25519_unpack_negative_vartime(ge25519 *r, const byte p[32]) { + const byte zero[32] = {0}; + const bignum25519 one = {1}; + byte parity = p[31] >> 7; + byte check[32]; + bignum25519 t, root, num, den, d3; + + curve25519_expand(r->y, p); + curve25519_copy(r->z, one); + curve25519_square(num, r->y); /* x = y^2 */ + curve25519_mul(den, num, ge25519_ecd); /* den = dy^2 */ + curve25519_sub_reduce(num, num, r->z); /* x = y^1 - 1 */ + curve25519_add(den, den, r->z); /* den = dy^2 + 1 */ + + /* Computation of sqrt(num/den) */ + /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ + curve25519_square(t, den); + curve25519_mul(d3, t, den); + curve25519_square(r->x, d3); + curve25519_mul(r->x, r->x, den); + curve25519_mul(r->x, r->x, num); + curve25519_pow_two252m3(r->x, r->x); + + /* 2. computation of r->x = num * den^3 * (num*den^7)^((p-5)/8) */ + curve25519_mul(r->x, r->x, d3); + curve25519_mul(r->x, r->x, num); + + /* 3. Check if either of the roots works: */ + curve25519_square(t, r->x); + curve25519_mul(t, t, den); + curve25519_sub_reduce(root, t, num); + curve25519_contract(check, root); + if (!ed25519_verify(check, zero, 32)) { + curve25519_add_reduce(t, t, num); + curve25519_contract(check, t); + if (!ed25519_verify(check, zero, 32)) + return 0; + curve25519_mul(r->x, r->x, ge25519_sqrtneg1); + } + + curve25519_contract(check, r->x); + if ((check[0] & 1) == parity) { + curve25519_copy(t, r->x); + curve25519_neg(r->x, t); + } + curve25519_mul(r->t, r->x, r->y); + return 1; +} + +/* computes [s1]p1 + [s2]basepoint */ +void +ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const bignum256modm s2) { + signed char slide1[256], slide2[256]; + ge25519_pniels pre1[S1_TABLE_SIZE]; + ge25519 d1; + ge25519_p1p1 t; + sword32 i; + + contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE); + contract256_slidingwindow_modm(slide2, s2, S2_SWINDOWSIZE); + + ge25519_double(&d1, p1); + ge25519_full_to_pniels(pre1, p1); + for (i = 0; i < S1_TABLE_SIZE - 1; i++) + ge25519_pnielsadd(&pre1[i+1], &d1, &pre1[i]); + + /* set neutral */ + memset(r, 0, sizeof(ge25519)); + r->y[0] = 1; + r->z[0] = 1; + + i = 255; + while ((i >= 0) && !(slide1[i] | slide2[i])) + i--; + + for (; i >= 0; i--) { + ge25519_double_p1p1(&t, r); + + if (slide1[i]) { + ge25519_p1p1_to_full(r, &t); + ge25519_pnielsadd_p1p1(&t, r, &pre1[abs(slide1[i]) / 2], (byte)slide1[i] >> 7); + } + + if (slide2[i]) { + ge25519_p1p1_to_full(r, &t); + ge25519_nielsadd2_p1p1(&t, r, &ge25519_niels_sliding_multiples[abs(slide2[i]) / 2], (byte)slide2[i] >> 7); + } + + ge25519_p1p1_to_partial(r, &t); + } +} + +#if !defined(HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS) + +word32 +ge25519_windowb_equal(word32 b, word32 c) { + return ((b ^ c) - 1) >> 31; +} + +void +ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const byte table[256][96], word32 pos, signed char b) { + bignum25519 neg; + word32 sign = (word32)((byte)b >> 7); + word32 mask = ~(sign - 1); + word32 u = (b + mask) ^ mask; + word32 i; + + /* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */ + byte packed[96] = {0}; + packed[0] = 1; + packed[32] = 1; + + for (i = 0; i < 8; i++) + curve25519_move_conditional_bytes(packed, table[(pos * 8) + i], ge25519_windowb_equal(u, i + 1)); + + /* expand in to t */ + curve25519_expand(t->ysubx, packed + 0); + curve25519_expand(t->xaddy, packed + 32); + curve25519_expand(t->t2d , packed + 64); + + /* adjust for sign */ + curve25519_swap_conditional(t->ysubx, t->xaddy, sign); + curve25519_neg(neg, t->t2d); + curve25519_swap_conditional(t->t2d, neg, sign); +} + +#endif /* HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS */ + +/* computes [s]basepoint */ +void +ge25519_scalarmult_base_niels(ge25519 *r, const byte basepoint_table[256][96], const bignum256modm s) { + signed char b[64]; + word32 i; + ge25519_niels t; + + contract256_window4_modm(b, s); + + ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[1]); + curve25519_sub_reduce(r->x, t.xaddy, t.ysubx); + curve25519_add_reduce(r->y, t.xaddy, t.ysubx); + memset(r->z, 0, sizeof(bignum25519)); + curve25519_copy(r->t, t.t2d); + r->z[0] = 2; + for (i = 3; i < 64; i += 2) { + ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]); + ge25519_nielsadd2(r, &t); + } + ge25519_double_partial(r, r); + ge25519_double_partial(r, r); + ge25519_double_partial(r, r); + ge25519_double(r, r); + ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[0]); + curve25519_mul(t.t2d, t.t2d, ge25519_ecd); + ge25519_nielsadd2(r, &t); + for(i = 2; i < 64; i += 2) { + ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]); + ge25519_nielsadd2(r, &t); + } +} + +ANONYMOUS_NAMESPACE_END +NAMESPACE_END // Ed25519 +NAMESPACE_END // Donna +NAMESPACE_END // CryptoPP + +//***************************** curve25519 *****************************// + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Donna) + +int curve25519_mult_CXX(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]) +{ + using namespace CryptoPP::Donna::X25519; + + FixedSizeSecBlock e; + for (size_t i = 0;i < 32;++i) + e[i] = secretKey[i]; + e[0] &= 0xf8; e[31] &= 0x7f; e[31] |= 0x40; + + bignum25519 nqpqx = {1}, nqpqz = {0}, nqz = {1}, nqx; + bignum25519 q, qx, qpqx, qqx, zzz, zmone; + size_t bit, lastbit; + + curve25519_expand(q, othersKey); + curve25519_copy(nqx, q); + + /* bit 255 is always 0, and bit 254 is always 1, so skip bit 255 and + start pre-swapped on bit 254 */ + lastbit = 1; + + /* we are doing bits 254..3 in the loop, but are swapping in bits 253..2 */ + for (int i = 253; i >= 2; i--) { + curve25519_add(qx, nqx, nqz); + curve25519_sub(nqz, nqx, nqz); + curve25519_add(qpqx, nqpqx, nqpqz); + curve25519_sub(nqpqz, nqpqx, nqpqz); + curve25519_mul(nqpqx, qpqx, nqz); + curve25519_mul(nqpqz, qx, nqpqz); + curve25519_add(qqx, nqpqx, nqpqz); + curve25519_sub(nqpqz, nqpqx, nqpqz); + curve25519_square(nqpqz, nqpqz); + curve25519_square(nqpqx, qqx); + curve25519_mul(nqpqz, nqpqz, q); + curve25519_square(qx, qx); + curve25519_square(nqz, nqz); + curve25519_mul(nqx, qx, nqz); + curve25519_sub(nqz, qx, nqz); + curve25519_scalar_product(zzz, nqz, 121665); + curve25519_add(zzz, zzz, qx); + curve25519_mul(nqz, nqz, zzz); + + bit = (e[i/8] >> (i & 7)) & 1; + curve25519_swap_conditional(nqx, nqpqx, bit ^ lastbit); + curve25519_swap_conditional(nqz, nqpqz, bit ^ lastbit); + lastbit = bit; + } + + /* the final 3 bits are always zero, so we only need to double */ + for (int i = 0; i < 3; i++) { + curve25519_add(qx, nqx, nqz); + curve25519_sub(nqz, nqx, nqz); + curve25519_square(qx, qx); + curve25519_square(nqz, nqz); + curve25519_mul(nqx, qx, nqz); + curve25519_sub(nqz, qx, nqz); + curve25519_scalar_product(zzz, nqz, 121665); + curve25519_add(zzz, zzz, qx); + curve25519_mul(nqz, nqz, zzz); + } + + curve25519_recip(zmone, nqz); + curve25519_mul(nqz, nqx, zmone); + curve25519_contract(sharedKey, nqz); + + return 0; +} + +int curve25519_mult(byte publicKey[32], const byte secretKey[32]) +{ + using namespace CryptoPP::Donna::X25519; + +#if (CRYPTOPP_CURVE25519_SSE2) + if (HasSSE2()) + return curve25519_mult_SSE2(publicKey, secretKey, basePoint); + else +#endif + + return curve25519_mult_CXX(publicKey, secretKey, basePoint); +} + +int curve25519_mult(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]) +{ +#if (CRYPTOPP_CURVE25519_SSE2) + if (HasSSE2()) + return curve25519_mult_SSE2(sharedKey, secretKey, othersKey); + else +#endif + + return curve25519_mult_CXX(sharedKey, secretKey, othersKey); +} + +NAMESPACE_END // Donna +NAMESPACE_END // CryptoPP + +//******************************* ed25519 *******************************// + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Donna) + +int +ed25519_publickey_CXX(byte publicKey[32], const byte secretKey[32]) +{ + using namespace CryptoPP::Donna::Ed25519; + + bignum256modm a; + ALIGN(ALIGN_SPEC) ge25519 A; + hash_512bits extsk; + + /* A = aB */ + ed25519_extsk(extsk, secretKey); + expand256_modm(a, extsk, 32); + ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a); + ge25519_pack(publicKey, &A); + + return 0; +} + +int +ed25519_publickey(byte publicKey[32], const byte secretKey[32]) +{ + return ed25519_publickey_CXX(publicKey, secretKey); +} + +int +ed25519_sign_CXX(std::istream& stream, const byte sk[32], const byte pk[32], byte RS[64]) +{ + using namespace CryptoPP::Donna::Ed25519; + + bignum256modm r, S, a; + ALIGN(ALIGN_SPEC) ge25519 R; + hash_512bits extsk, hashr, hram; + + // Unfortunately we need to read the stream twice. The fisrt time calculates + // 'r = H(aExt[32..64], m)'. The second time calculates 'S = H(R,A,m)'. There + // is a data dependency due to hashing 'RS' with 'R = [r]B' that does not + // allow us to read the stream once. + std::streampos where = stream.tellg(); + + ed25519_extsk(extsk, sk); + + /* r = H(aExt[32..64], m) */ + SHA512 hash; + hash.Update(extsk + 32, 32); + UpdateFromStream(hash, stream); + hash.Final(hashr); + expand256_modm(r, hashr, 64); + + /* R = rB */ + ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r); + ge25519_pack(RS, &R); + + // Reset stream for the second digest + stream.clear(); + stream.seekg(where); + + /* S = H(R,A,m).. */ + ed25519_hram(hram, RS, pk, stream); + expand256_modm(S, hram, 64); + + /* S = H(R,A,m)a */ + expand256_modm(a, extsk, 32); + mul256_modm(S, S, a); + + /* S = (r + H(R,A,m)a) */ + add256_modm(S, S, r); + + /* S = (r + H(R,A,m)a) mod L */ + contract256_modm(RS + 32, S); + return 0; +} + +int +ed25519_sign_CXX(const byte *m, size_t mlen, const byte sk[32], const byte pk[32], byte RS[64]) +{ + using namespace CryptoPP::Donna::Ed25519; + + bignum256modm r, S, a; + ALIGN(ALIGN_SPEC) ge25519 R; + hash_512bits extsk, hashr, hram; + + ed25519_extsk(extsk, sk); + + /* r = H(aExt[32..64], m) */ + SHA512 hash; + hash.Update(extsk + 32, 32); + hash.Update(m, mlen); + hash.Final(hashr); + expand256_modm(r, hashr, 64); + + /* R = rB */ + ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r); + ge25519_pack(RS, &R); + + /* S = H(R,A,m).. */ + ed25519_hram(hram, RS, pk, m, mlen); + expand256_modm(S, hram, 64); + + /* S = H(R,A,m)a */ + expand256_modm(a, extsk, 32); + mul256_modm(S, S, a); + + /* S = (r + H(R,A,m)a) */ + add256_modm(S, S, r); + + /* S = (r + H(R,A,m)a) mod L */ + contract256_modm(RS + 32, S); + return 0; +} + +int +ed25519_sign(std::istream& stream, const byte secretKey[32], const byte publicKey[32], + byte signature[64]) +{ + return ed25519_sign_CXX(stream, secretKey, publicKey, signature); +} + +int +ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32], + const byte publicKey[32], byte signature[64]) +{ + return ed25519_sign_CXX(message, messageLength, secretKey, publicKey, signature); +} + +int +ed25519_sign_open_CXX(const byte *m, size_t mlen, const byte pk[32], const byte RS[64]) { + + using namespace CryptoPP::Donna::Ed25519; + + ALIGN(ALIGN_SPEC) ge25519 R, A; + hash_512bits hash; + bignum256modm hram, S; + byte checkR[32]; + + if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) + return -1; + + /* hram = H(R,A,m) */ + ed25519_hram(hash, RS, pk, m, mlen); + expand256_modm(hram, hash, 64); + + /* S */ + expand256_modm(S, RS + 32, 32); + + /* SB - H(R,A,m)A */ + ge25519_double_scalarmult_vartime(&R, &A, hram, S); + ge25519_pack(checkR, &R); + + /* check that R = SB - H(R,A,m)A */ + return ed25519_verify(RS, checkR, 32) ? 0 : -1; +} + +int +ed25519_sign_open_CXX(std::istream& stream, const byte pk[32], const byte RS[64]) { + + using namespace CryptoPP::Donna::Ed25519; + + ALIGN(ALIGN_SPEC) ge25519 R, A; + hash_512bits hash; + bignum256modm hram, S; + byte checkR[32]; + + if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) + return -1; + + /* hram = H(R,A,m) */ + ed25519_hram(hash, RS, pk, stream); + expand256_modm(hram, hash, 64); + + /* S */ + expand256_modm(S, RS + 32, 32); + + /* SB - H(R,A,m)A */ + ge25519_double_scalarmult_vartime(&R, &A, hram, S); + ge25519_pack(checkR, &R); + + /* check that R = SB - H(R,A,m)A */ + return ed25519_verify(RS, checkR, 32) ? 0 : -1; +} + +int +ed25519_sign_open(std::istream& stream, const byte publicKey[32], const byte signature[64]) +{ + return ed25519_sign_open_CXX(stream, publicKey, signature); +} + +int +ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKey[32], const byte signature[64]) +{ + return ed25519_sign_open_CXX(message, messageLength, publicKey, signature); +} + +NAMESPACE_END // Donna +NAMESPACE_END // CryptoPP + +#endif // CRYPTOPP_CURVE25519_64BIT diff --git a/external/ours/library/crypto/src/shared/original/donna_64.h b/external/ours/library/crypto/src/shared/original/donna_64.h new file mode 100755 index 000000000..d98ad6400 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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(_MSC_VER) +# 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(_MSC_VER) +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/external/ours/library/crypto/src/shared/original/donna_sse.cpp b/external/ours/library/crypto/src/shared/original/donna_sse.cpp new file mode 100755 index 000000000..2da9a6f73 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/donna_sse.cpp @@ -0,0 +1,1123 @@ +// donna_sse.cpp - written and placed in public domain by Jeffrey Walton +// This is a integration of Andrew Moon's public domain code. +// Also see https://github.com/floodyberry/curve25519-donna. + +// This is a integration of Andrew Moon's public domain code. The port was +// clean, but it has one potential problem. The original code is C and relies +// upon unions. Accessing the inactive union member is undefined behavior in +// C++. That means copying the array into packedelem8.u is OK; but then using +// packedelem8.v in a calcualtion is UB. Fortunately most (all?) compilers +// take pity on C++ developers and compile the code. We will have to keep an +// eye on things or rewrite significant portions of this code. + +// If needed, see Moon's commit "Go back to ignoring 256th bit [sic]", +// https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658 + +#include "pch.h" + +#include "config.h" +#include "donna.h" +#include "secblock.h" +#include "misc.h" + +// The data is aligned, but Clang issues warning based on type +// and not the actual alignment of the variable and data. +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wcast-align" +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4244) +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char DONNA_SSE_FNAME[] = __FILE__; + +#if (CRYPTOPP_CURVE25519_SSE2) + +#include "donna_sse.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::sword32; +using CryptoPP::word64; +using CryptoPP::sword64; +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; + +// Bring in all the symbols from the SSE header +using namespace CryptoPP::Donna::ArchSSE; + +/* Copy a bignum to another: out = in */ +inline void +curve25519_copy(bignum25519 out, const bignum25519 in) { + xmmi x0,x1,x2; + x0 = _mm_load_si128((xmmi*)in + 0); + x1 = _mm_load_si128((xmmi*)in + 1); + x2 = _mm_load_si128((xmmi*)in + 2); + _mm_store_si128((xmmi*)out + 0, x0); + _mm_store_si128((xmmi*)out + 1, x1); + _mm_store_si128((xmmi*)out + 2, x2); +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +inline void +curve25519_expand(bignum25519 out, const byte in[32]) { + word32 x0,x1,x2,x3,x4,x5,x6,x7; + + x0 = *(word32 *)(in + 0); + x1 = *(word32 *)(in + 4); + x2 = *(word32 *)(in + 8); + x3 = *(word32 *)(in + 12); + x4 = *(word32 *)(in + 16); + x5 = *(word32 *)(in + 20); + x6 = *(word32 *)(in + 24); + x7 = *(word32 *)(in + 28); + + out[0] = ( x0 ) & reduce_mask_26; + out[1] = ((((word64)x1 << 32) | x0) >> 26) & reduce_mask_25; + out[2] = ((((word64)x2 << 32) | x1) >> 19) & reduce_mask_26; + out[3] = ((((word64)x3 << 32) | x2) >> 13) & reduce_mask_25; + out[4] = (( x3) >> 6) & reduce_mask_26; + out[5] = ( x4 ) & reduce_mask_25; + out[6] = ((((word64)x5 << 32) | x4) >> 25) & reduce_mask_26; + out[7] = ((((word64)x6 << 32) | x5) >> 19) & reduce_mask_25; + out[8] = ((((word64)x7 << 32) | x6) >> 12) & reduce_mask_26; + out[9] = (( x7) >> 6) & reduce_mask_25; /* ignore the top bit */ + + out[10] = 0; + out[11] = 0; +} + +/* Take a fully reduced polynomial form number and contract it into a + * little-endian, 32-byte array + */ +inline void +curve25519_contract(byte out[32], const bignum25519 in) { + ALIGN(16) bignum25519 f; + + curve25519_copy(f, in); + + #define carry_pass() \ + f[1] += f[0] >> 26; f[0] &= reduce_mask_26; \ + f[2] += f[1] >> 25; f[1] &= reduce_mask_25; \ + f[3] += f[2] >> 26; f[2] &= reduce_mask_26; \ + f[4] += f[3] >> 25; f[3] &= reduce_mask_25; \ + f[5] += f[4] >> 26; f[4] &= reduce_mask_26; \ + f[6] += f[5] >> 25; f[5] &= reduce_mask_25; \ + f[7] += f[6] >> 26; f[6] &= reduce_mask_26; \ + f[8] += f[7] >> 25; f[7] &= reduce_mask_25; \ + f[9] += f[8] >> 26; f[8] &= reduce_mask_26; + + #define carry_pass_full() \ + carry_pass() \ + f[0] += 19 * (f[9] >> 25); f[9] &= reduce_mask_25; + + #define carry_pass_final() \ + carry_pass() \ + f[9] &= reduce_mask_25; + + carry_pass_full() + carry_pass_full() + + /* now t is between 0 and 2^255-1, properly carried. */ + /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ + f[0] += 19; + carry_pass_full() + + /* now between 19 and 2^255-1 in both cases, and offset by 19. */ + f[0] += (1 << 26) - 19; + f[1] += (1 << 25) - 1; + f[2] += (1 << 26) - 1; + f[3] += (1 << 25) - 1; + f[4] += (1 << 26) - 1; + f[5] += (1 << 25) - 1; + f[6] += (1 << 26) - 1; + f[7] += (1 << 25) - 1; + f[8] += (1 << 26) - 1; + f[9] += (1 << 25) - 1; + + /* now between 2^255 and 2^256-20, and offset by 2^255. */ + carry_pass_final() + + #undef carry_pass + #undef carry_full + #undef carry_final + + *(word32 *)(out + 0) = ((f[0] ) | (f[1] << 26)); + *(word32 *)(out + 4) = ((f[1] >> 6) | (f[2] << 19)); + *(word32 *)(out + 8) = ((f[2] >> 13) | (f[3] << 13)); + *(word32 *)(out + 12) = ((f[3] >> 19) | (f[4] << 6)); + *(word32 *)(out + 16) = ((f[5] ) | (f[6] << 25)); + *(word32 *)(out + 20) = ((f[6] >> 7) | (f[7] << 19)); + *(word32 *)(out + 24) = ((f[7] >> 13) | (f[8] << 12)); + *(word32 *)(out + 28) = ((f[8] >> 20) | (f[9] << 6)); +} + +/* + * Maybe swap the contents of two felem arrays (@a and @b), each 5 elements + * long. Perform the swap iff @swap is non-zero. + */ +inline void +curve25519_swap_conditional(bignum25519 a, bignum25519 b, word32 iswap) { + const word32 swap = (word32)(-(sword32)iswap); + xmmi a0,a1,a2,b0,b1,b2,x0,x1,x2; + xmmi mask = _mm_cvtsi32_si128(swap); + mask = _mm_shuffle_epi32(mask, 0); + a0 = _mm_load_si128((xmmi *)a + 0); + a1 = _mm_load_si128((xmmi *)a + 1); + a2 = _mm_load_si128((xmmi *)a + 2); + b0 = _mm_load_si128((xmmi *)b + 0); + b1 = _mm_load_si128((xmmi *)b + 1); + b2 = _mm_load_si128((xmmi *)b + 2); + b0 = _mm_xor_si128(a0, b0); + b1 = _mm_xor_si128(a1, b1); + b2 = _mm_xor_si128(a2, b2); + x0 = _mm_and_si128(b0, mask); + x1 = _mm_and_si128(b1, mask); + x2 = _mm_and_si128(b2, mask); + x0 = _mm_xor_si128(x0, a0); + x1 = _mm_xor_si128(x1, a1); + x2 = _mm_xor_si128(x2, a2); + a0 = _mm_xor_si128(x0, b0); + a1 = _mm_xor_si128(x1, b1); + a2 = _mm_xor_si128(x2, b2); + _mm_store_si128((xmmi *)a + 0, x0); + _mm_store_si128((xmmi *)a + 1, x1); + _mm_store_si128((xmmi *)a + 2, x2); + _mm_store_si128((xmmi *)b + 0, a0); + _mm_store_si128((xmmi *)b + 1, a1); + _mm_store_si128((xmmi *)b + 2, a2); +} + +/* interleave two bignums */ +inline void +curve25519_tangle32(packedelem32 *out, const bignum25519 x, const bignum25519 z) { + xmmi x0,x1,x2,z0,z1,z2; + + x0 = _mm_load_si128((xmmi *)(x + 0)); + x1 = _mm_load_si128((xmmi *)(x + 4)); + x2 = _mm_load_si128((xmmi *)(x + 8)); + z0 = _mm_load_si128((xmmi *)(z + 0)); + z1 = _mm_load_si128((xmmi *)(z + 4)); + z2 = _mm_load_si128((xmmi *)(z + 8)); + + out[0].v = _mm_unpacklo_epi32(x0, z0); + out[1].v = _mm_unpackhi_epi32(x0, z0); + out[2].v = _mm_unpacklo_epi32(x1, z1); + out[3].v = _mm_unpackhi_epi32(x1, z1); + out[4].v = _mm_unpacklo_epi32(x2, z2); +} + +/* split a packed bignum in to it's two parts */ +inline void +curve25519_untangle64(bignum25519 x, bignum25519 z, const packedelem64 *in) { + _mm_store_si128((xmmi *)(x + 0), _mm_unpacklo_epi64(_mm_unpacklo_epi32(in[0].v, in[1].v), _mm_unpacklo_epi32(in[2].v, in[3].v))); + _mm_store_si128((xmmi *)(x + 4), _mm_unpacklo_epi64(_mm_unpacklo_epi32(in[4].v, in[5].v), _mm_unpacklo_epi32(in[6].v, in[7].v))); + _mm_store_si128((xmmi *)(x + 8), _mm_unpacklo_epi32(in[8].v, in[9].v) ); + _mm_store_si128((xmmi *)(z + 0), _mm_unpacklo_epi64(_mm_unpackhi_epi32(in[0].v, in[1].v), _mm_unpackhi_epi32(in[2].v, in[3].v))); + _mm_store_si128((xmmi *)(z + 4), _mm_unpacklo_epi64(_mm_unpackhi_epi32(in[4].v, in[5].v), _mm_unpackhi_epi32(in[6].v, in[7].v))); + _mm_store_si128((xmmi *)(z + 8), _mm_unpackhi_epi32(in[8].v, in[9].v) ); +} + +/* add two packed bignums */ +inline void +curve25519_add_packed32(packedelem32 *out, const packedelem32 *r, const packedelem32 *s) { + out[0].v = _mm_add_epi32(r[0].v, s[0].v); + out[1].v = _mm_add_epi32(r[1].v, s[1].v); + out[2].v = _mm_add_epi32(r[2].v, s[2].v); + out[3].v = _mm_add_epi32(r[3].v, s[3].v); + out[4].v = _mm_add_epi32(r[4].v, s[4].v); +} + +/* subtract two packed bignums */ +inline void +curve25519_sub_packed32(packedelem32 *out, const packedelem32 *r, const packedelem32 *s) { + xmmi r0,r1,r2,r3,r4; + xmmi s0,s1,s2,s3; + xmmi c1,c2; + + r0 = _mm_add_epi32(r[0].v, packed32zeromodp0.v); + r1 = _mm_add_epi32(r[1].v, packed32zeromodp1.v); + r2 = _mm_add_epi32(r[2].v, packed32zeromodp1.v); + r3 = _mm_add_epi32(r[3].v, packed32zeromodp1.v); + r4 = _mm_add_epi32(r[4].v, packed32zeromodp1.v); + r0 = _mm_sub_epi32(r0, s[0].v); /* 00 11 */ + r1 = _mm_sub_epi32(r1, s[1].v); /* 22 33 */ + r2 = _mm_sub_epi32(r2, s[2].v); /* 44 55 */ + r3 = _mm_sub_epi32(r3, s[3].v); /* 66 77 */ + r4 = _mm_sub_epi32(r4, s[4].v); /* 88 99 */ + + s0 = _mm_unpacklo_epi64(r0, r2); /* 00 44 */ + s1 = _mm_unpackhi_epi64(r0, r2); /* 11 55 */ + s2 = _mm_unpacklo_epi64(r1, r3); /* 22 66 */ + s3 = _mm_unpackhi_epi64(r1, r3); /* 33 77 */ + + c1 = _mm_srli_epi32(s0, 26); c2 = _mm_srli_epi32(s2, 26); s0 = _mm_and_si128(s0, packedmask26262626.v); s2 = _mm_and_si128(s2, packedmask26262626.v); s1 = _mm_add_epi32(s1, c1); s3 = _mm_add_epi32(s3, c2); + c1 = _mm_srli_epi32(s1, 25); c2 = _mm_srli_epi32(s3, 25); s1 = _mm_and_si128(s1, packedmask25252525.v); s3 = _mm_and_si128(s3, packedmask25252525.v); s2 = _mm_add_epi32(s2, c1); r4 = _mm_add_epi32(r4, _mm_srli_si128(c2, 8)); s0 = _mm_add_epi32(s0, _mm_slli_si128(c2, 8)); + + out[0].v = _mm_unpacklo_epi64(s0, s1); /* 00 11 */ + out[1].v = _mm_unpacklo_epi64(s2, s3); /* 22 33 */ + out[2].v = _mm_unpackhi_epi64(s0, s1); /* 44 55 */ + out[3].v = _mm_unpackhi_epi64(s2, s3); /* 66 77 */ + out[4].v = r4; /* 88 99 */ +} + +/* multiply two packed bignums */ +inline void +curve25519_mul_packed64(packedelem64 *out, const packedelem64 *r, const packedelem64 *s) { + xmmi r1,r2,r3,r4,r5,r6,r7,r8,r9; + xmmi r1_2,r3_2,r5_2,r7_2,r9_2; + xmmi c1,c2; + + out[0].v = _mm_mul_epu32(r[0].v, s[0].v); + out[1].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[1].v), _mm_mul_epu32(r[1].v, s[0].v)); + r1_2 = _mm_slli_epi32(r[1].v, 1); + out[2].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r1_2 , s[1].v), _mm_mul_epu32(r[2].v, s[0].v))); + out[3].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[3].v), _mm_add_epi64(_mm_mul_epu32(r[1].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[1].v), _mm_mul_epu32(r[3].v, s[0].v)))); + r3_2 = _mm_slli_epi32(r[3].v, 1); + out[4].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r1_2 , s[3].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r3_2 , s[1].v), _mm_mul_epu32(r[4].v, s[0].v))))); + out[5].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[5].v), _mm_add_epi64(_mm_mul_epu32(r[1].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[3].v), _mm_add_epi64(_mm_mul_epu32(r[3].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[1].v), _mm_mul_epu32(r[5].v, s[0].v)))))); + r5_2 = _mm_slli_epi32(r[5].v, 1); + out[6].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[6].v), _mm_add_epi64(_mm_mul_epu32(r1_2 , s[5].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r3_2 , s[3].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r5_2 , s[1].v), _mm_mul_epu32(r[6].v, s[0].v))))))); + out[7].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[7].v), _mm_add_epi64(_mm_mul_epu32(r[1].v, s[6].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[5].v), _mm_add_epi64(_mm_mul_epu32(r[3].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[3].v), _mm_add_epi64(_mm_mul_epu32(r[5].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r[6].v, s[1].v), _mm_mul_epu32(r[7].v , s[0].v)))))))); + r7_2 = _mm_slli_epi32(r[7].v, 1); + out[8].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[8].v), _mm_add_epi64(_mm_mul_epu32(r1_2 , s[7].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[6].v), _mm_add_epi64(_mm_mul_epu32(r3_2 , s[5].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r5_2 , s[3].v), _mm_add_epi64(_mm_mul_epu32(r[6].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r7_2 , s[1].v), _mm_mul_epu32(r[8].v, s[0].v))))))))); + out[9].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[9].v), _mm_add_epi64(_mm_mul_epu32(r[1].v, s[8].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[7].v), _mm_add_epi64(_mm_mul_epu32(r[3].v, s[6].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[5].v), _mm_add_epi64(_mm_mul_epu32(r[5].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r[6].v, s[3].v), _mm_add_epi64(_mm_mul_epu32(r[7].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r[8].v, s[1].v), _mm_mul_epu32(r[9].v, s[0].v)))))))))); + + r1 = _mm_mul_epu32(r[1].v, packednineteen.v); + r2 = _mm_mul_epu32(r[2].v, packednineteen.v); + r1_2 = _mm_slli_epi32(r1, 1); + r3 = _mm_mul_epu32(r[3].v, packednineteen.v); + r4 = _mm_mul_epu32(r[4].v, packednineteen.v); + r3_2 = _mm_slli_epi32(r3, 1); + r5 = _mm_mul_epu32(r[5].v, packednineteen.v); + r6 = _mm_mul_epu32(r[6].v, packednineteen.v); + r5_2 = _mm_slli_epi32(r5, 1); + r7 = _mm_mul_epu32(r[7].v, packednineteen.v); + r8 = _mm_mul_epu32(r[8].v, packednineteen.v); + r7_2 = _mm_slli_epi32(r7, 1); + r9 = _mm_mul_epu32(r[9].v, packednineteen.v); + r9_2 = _mm_slli_epi32(r9, 1); + + out[0].v = _mm_add_epi64(out[0].v, _mm_add_epi64(_mm_mul_epu32(r9_2, s[1].v), _mm_add_epi64(_mm_mul_epu32(r8, s[2].v), _mm_add_epi64(_mm_mul_epu32(r7_2, s[3].v), _mm_add_epi64(_mm_mul_epu32(r6, s[4].v), _mm_add_epi64(_mm_mul_epu32(r5_2, s[5].v), _mm_add_epi64(_mm_mul_epu32(r4, s[6].v), _mm_add_epi64(_mm_mul_epu32(r3_2, s[7].v), _mm_add_epi64(_mm_mul_epu32(r2, s[8].v), _mm_mul_epu32(r1_2, s[9].v)))))))))); + out[1].v = _mm_add_epi64(out[1].v, _mm_add_epi64(_mm_mul_epu32(r9 , s[2].v), _mm_add_epi64(_mm_mul_epu32(r8, s[3].v), _mm_add_epi64(_mm_mul_epu32(r7 , s[4].v), _mm_add_epi64(_mm_mul_epu32(r6, s[5].v), _mm_add_epi64(_mm_mul_epu32(r5 , s[6].v), _mm_add_epi64(_mm_mul_epu32(r4, s[7].v), _mm_add_epi64(_mm_mul_epu32(r3 , s[8].v), _mm_mul_epu32(r2, s[9].v))))))))); + out[2].v = _mm_add_epi64(out[2].v, _mm_add_epi64(_mm_mul_epu32(r9_2, s[3].v), _mm_add_epi64(_mm_mul_epu32(r8, s[4].v), _mm_add_epi64(_mm_mul_epu32(r7_2, s[5].v), _mm_add_epi64(_mm_mul_epu32(r6, s[6].v), _mm_add_epi64(_mm_mul_epu32(r5_2, s[7].v), _mm_add_epi64(_mm_mul_epu32(r4, s[8].v), _mm_mul_epu32(r3_2, s[9].v)))))))); + out[3].v = _mm_add_epi64(out[3].v, _mm_add_epi64(_mm_mul_epu32(r9 , s[4].v), _mm_add_epi64(_mm_mul_epu32(r8, s[5].v), _mm_add_epi64(_mm_mul_epu32(r7 , s[6].v), _mm_add_epi64(_mm_mul_epu32(r6, s[7].v), _mm_add_epi64(_mm_mul_epu32(r5 , s[8].v), _mm_mul_epu32(r4, s[9].v))))))); + out[4].v = _mm_add_epi64(out[4].v, _mm_add_epi64(_mm_mul_epu32(r9_2, s[5].v), _mm_add_epi64(_mm_mul_epu32(r8, s[6].v), _mm_add_epi64(_mm_mul_epu32(r7_2, s[7].v), _mm_add_epi64(_mm_mul_epu32(r6, s[8].v), _mm_mul_epu32(r5_2, s[9].v)))))); + out[5].v = _mm_add_epi64(out[5].v, _mm_add_epi64(_mm_mul_epu32(r9 , s[6].v), _mm_add_epi64(_mm_mul_epu32(r8, s[7].v), _mm_add_epi64(_mm_mul_epu32(r7 , s[8].v), _mm_mul_epu32(r6, s[9].v))))); + out[6].v = _mm_add_epi64(out[6].v, _mm_add_epi64(_mm_mul_epu32(r9_2, s[7].v), _mm_add_epi64(_mm_mul_epu32(r8, s[8].v), _mm_mul_epu32(r7_2, s[9].v)))); + out[7].v = _mm_add_epi64(out[7].v, _mm_add_epi64(_mm_mul_epu32(r9 , s[8].v), _mm_mul_epu32(r8, s[9].v))); + out[8].v = _mm_add_epi64(out[8].v, _mm_mul_epu32(r9_2, s[9].v)); + + c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); + c1 = _mm_srli_epi64(out[1].v, 25); c2 = _mm_srli_epi64(out[5].v, 25); out[1].v = _mm_and_si128(out[1].v, packedmask25.v); out[5].v = _mm_and_si128(out[5].v, packedmask25.v); out[2].v = _mm_add_epi64(out[2].v, c1); out[6].v = _mm_add_epi64(out[6].v, c2); + c1 = _mm_srli_epi64(out[2].v, 26); c2 = _mm_srli_epi64(out[6].v, 26); out[2].v = _mm_and_si128(out[2].v, packedmask26.v); out[6].v = _mm_and_si128(out[6].v, packedmask26.v); out[3].v = _mm_add_epi64(out[3].v, c1); out[7].v = _mm_add_epi64(out[7].v, c2); + c1 = _mm_srli_epi64(out[3].v, 25); c2 = _mm_srli_epi64(out[7].v, 25); out[3].v = _mm_and_si128(out[3].v, packedmask25.v); out[7].v = _mm_and_si128(out[7].v, packedmask25.v); out[4].v = _mm_add_epi64(out[4].v, c1); out[8].v = _mm_add_epi64(out[8].v, c2); + c2 = _mm_srli_epi64(out[8].v, 26); out[8].v = _mm_and_si128(out[8].v, packedmask26.v); out[9].v = _mm_add_epi64(out[9].v, c2); + c2 = _mm_srli_epi64(out[9].v, 25); out[9].v = _mm_and_si128(out[9].v, packedmask25.v); out[0].v = _mm_add_epi64(out[0].v, _mm_mul_epu32(c2, packednineteen.v)); + c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); +} + +/* multiply a bignum */ +void +curve25519_mul(bignum25519 out, const bignum25519 r, const bignum25519 s) { + xmmi m01,m23,m45,m67,m89; + xmmi m0123,m4567; + xmmi s0123,s4567; + xmmi s01,s23,s45,s67,s89; + xmmi s12,s34,s56,s78,s9; + xmmi r0,r2,r4,r6,r8; + xmmi r1,r3,r5,r7,r9; + xmmi r119,r219,r319,r419,r519,r619,r719,r819,r919; + xmmi c1,c2,c3; + + s0123 = _mm_load_si128((xmmi*)s + 0); + s01 = _mm_shuffle_epi32(s0123,_MM_SHUFFLE(3,1,2,0)); + s12 = _mm_shuffle_epi32(s0123, _MM_SHUFFLE(2,2,1,1)); + s23 = _mm_shuffle_epi32(s0123,_MM_SHUFFLE(3,3,2,2)); + s4567 = _mm_load_si128((xmmi*)s + 1); + s34 = _mm_unpacklo_epi64(_mm_srli_si128(s0123,12),s4567); + s45 = _mm_shuffle_epi32(s4567,_MM_SHUFFLE(3,1,2,0)); + s56 = _mm_shuffle_epi32(s4567, _MM_SHUFFLE(2,2,1,1)); + s67 = _mm_shuffle_epi32(s4567,_MM_SHUFFLE(3,3,2,2)); + s89 = _mm_load_si128((xmmi*)s + 2); + s78 = _mm_unpacklo_epi64(_mm_srli_si128(s4567,12),s89); + s89 = _mm_shuffle_epi32(s89,_MM_SHUFFLE(3,1,2,0)); + s9 = _mm_shuffle_epi32(s89, _MM_SHUFFLE(3,3,2,2)); + + r0 = _mm_load_si128((xmmi*)r + 0); + r1 = _mm_shuffle_epi32(r0, _MM_SHUFFLE(1,1,1,1)); + r1 = _mm_add_epi64(r1, _mm_and_si128(r1, sse2_top64bitmask.v)); + r2 = _mm_shuffle_epi32(r0, _MM_SHUFFLE(2,2,2,2)); + r3 = _mm_shuffle_epi32(r0, _MM_SHUFFLE(3,3,3,3)); + r3 = _mm_add_epi64(r3, _mm_and_si128(r3, sse2_top64bitmask.v)); + r0 = _mm_shuffle_epi32(r0, _MM_SHUFFLE(0,0,0,0)); + r4 = _mm_load_si128((xmmi*)r + 1); + r5 = _mm_shuffle_epi32(r4, _MM_SHUFFLE(1,1,1,1)); + r5 = _mm_add_epi64(r5, _mm_and_si128(r5, sse2_top64bitmask.v)); + r6 = _mm_shuffle_epi32(r4, _MM_SHUFFLE(2,2,2,2)); + r7 = _mm_shuffle_epi32(r4, _MM_SHUFFLE(3,3,3,3)); + r7 = _mm_add_epi64(r7, _mm_and_si128(r7, sse2_top64bitmask.v)); + r4 = _mm_shuffle_epi32(r4, _MM_SHUFFLE(0,0,0,0)); + r8 = _mm_load_si128((xmmi*)r + 2); + r9 = _mm_shuffle_epi32(r8, _MM_SHUFFLE(3,1,3,1)); + r9 = _mm_add_epi64(r9, _mm_and_si128(r9, sse2_top64bitmask.v)); + r8 = _mm_shuffle_epi32(r8, _MM_SHUFFLE(3,0,3,0)); + + m01 = _mm_mul_epu32(r1,s01); + m23 = _mm_mul_epu32(r1,s23); + m45 = _mm_mul_epu32(r1,s45); + m67 = _mm_mul_epu32(r1,s67); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r3,s01)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r3,s23)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r3,s45)); + m89 = _mm_mul_epu32(r1,s89); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r5,s01)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r5,s23)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r3,s67)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r7,s01)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r5,s45)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r7,s23)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r9,s01)); + + /* shift up */ + m89 = _mm_unpackhi_epi64(m67,_mm_slli_si128(m89,8)); + m67 = _mm_unpackhi_epi64(m45,_mm_slli_si128(m67,8)); + m45 = _mm_unpackhi_epi64(m23,_mm_slli_si128(m45,8)); + m23 = _mm_unpackhi_epi64(m01,_mm_slli_si128(m23,8)); + m01 = _mm_unpackhi_epi64(_mm_setzero_si128(),_mm_slli_si128(m01,8)); + + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r0,s01)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r0,s23)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r0,s45)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r0,s67)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r2,s01)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r2,s23)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r4,s23)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r0,s89)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r4,s01)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r2,s45)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r2,s67)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r6,s01)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r4,s45)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r6,s23)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r8,s01)); + + r219 = _mm_mul_epu32(r2, packednineteen.v); + r419 = _mm_mul_epu32(r4, packednineteen.v); + r619 = _mm_mul_epu32(r6, packednineteen.v); + r819 = _mm_mul_epu32(r8, packednineteen.v); + r119 = _mm_shuffle_epi32(r1,_MM_SHUFFLE(0,0,2,2)); r119 = _mm_mul_epu32(r119, packednineteen.v); + r319 = _mm_shuffle_epi32(r3,_MM_SHUFFLE(0,0,2,2)); r319 = _mm_mul_epu32(r319, packednineteen.v); + r519 = _mm_shuffle_epi32(r5,_MM_SHUFFLE(0,0,2,2)); r519 = _mm_mul_epu32(r519, packednineteen.v); + r719 = _mm_shuffle_epi32(r7,_MM_SHUFFLE(0,0,2,2)); r719 = _mm_mul_epu32(r719, packednineteen.v); + r919 = _mm_shuffle_epi32(r9,_MM_SHUFFLE(0,0,2,2)); r919 = _mm_mul_epu32(r919, packednineteen.v); + + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r919,s12)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r919,s34)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r919,s56)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r919,s78)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r719,s34)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r719,s56)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r719,s78)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r719,s9)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r519,s56)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r519,s78)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r519,s9)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r819,s89)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r319,s78)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r319,s9)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r619,s89)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r919,s9)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r819,s23)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r819,s45)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r819,s67)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r619,s45)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r619,s67)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r419,s67)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r419,s89)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r219,s89)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r119,s9)); + + r0 = _mm_unpacklo_epi64(m01, m45); + r1 = _mm_unpackhi_epi64(m01, m45); + r2 = _mm_unpacklo_epi64(m23, m67); + r3 = _mm_unpackhi_epi64(m23, m67); + r4 = _mm_unpacklo_epi64(m89, m89); + r5 = _mm_unpackhi_epi64(m89, m89); + + c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); + c1 = _mm_srli_epi64(r1, 25); c2 = _mm_srli_epi64(r3, 25); r1 = _mm_and_si128(r1, packedmask25.v); r3 = _mm_and_si128(r3, packedmask25.v); r2 = _mm_add_epi64(r2, c1); r4 = _mm_add_epi64(r4, c2); c3 = _mm_slli_si128(c2, 8); + c1 = _mm_srli_epi64(r4, 26); r4 = _mm_and_si128(r4, packedmask26.v); r5 = _mm_add_epi64(r5, c1); + c1 = _mm_srli_epi64(r5, 25); r5 = _mm_and_si128(r5, packedmask25.v); r0 = _mm_add_epi64(r0, _mm_unpackhi_epi64(_mm_mul_epu32(c1, packednineteen.v), c3)); + c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); + + m0123 = _mm_unpacklo_epi32(r0, r1); + m4567 = _mm_unpackhi_epi32(r0, r1); + m0123 = _mm_unpacklo_epi64(m0123, _mm_unpacklo_epi32(r2, r3)); + m4567 = _mm_unpacklo_epi64(m4567, _mm_unpackhi_epi32(r2, r3)); + m89 = _mm_unpackhi_epi32(r4, r5); + + _mm_store_si128((xmmi*)out + 0, m0123); + _mm_store_si128((xmmi*)out + 1, m4567); + _mm_store_si128((xmmi*)out + 2, m89); +} + +typedef struct bignum25519mulprecomp_t { + xmmi r0,r2,r4,r6,r8; + xmmi r1,r3,r5,r7,r9; + xmmi r119,r219,r319,r419,r519,r619,r719,r819,r919; +} bignum25519mulprecomp; + +/* precompute a constant to multiply by */ +inline void +curve25519_mul_precompute(bignum25519mulprecomp *pre, const bignum25519 r) { + pre->r0 = _mm_load_si128((xmmi*)r + 0); + pre->r1 = _mm_shuffle_epi32(pre->r0, _MM_SHUFFLE(1,1,1,1)); + pre->r1 = _mm_add_epi64(pre->r1, _mm_and_si128(pre->r1, sse2_top64bitmask.v)); + pre->r2 = _mm_shuffle_epi32(pre->r0, _MM_SHUFFLE(2,2,2,2)); + pre->r3 = _mm_shuffle_epi32(pre->r0, _MM_SHUFFLE(3,3,3,3)); + pre->r3 = _mm_add_epi64(pre->r3, _mm_and_si128(pre->r3, sse2_top64bitmask.v)); + pre->r0 = _mm_shuffle_epi32(pre->r0, _MM_SHUFFLE(0,0,0,0)); + pre->r4 = _mm_load_si128((xmmi*)r + 1); + pre->r5 = _mm_shuffle_epi32(pre->r4, _MM_SHUFFLE(1,1,1,1)); + pre->r5 = _mm_add_epi64(pre->r5, _mm_and_si128(pre->r5, sse2_top64bitmask.v)); + pre->r6 = _mm_shuffle_epi32(pre->r4, _MM_SHUFFLE(2,2,2,2)); + pre->r7 = _mm_shuffle_epi32(pre->r4, _MM_SHUFFLE(3,3,3,3)); + pre->r7 = _mm_add_epi64(pre->r7, _mm_and_si128(pre->r7, sse2_top64bitmask.v)); + pre->r4 = _mm_shuffle_epi32(pre->r4, _MM_SHUFFLE(0,0,0,0)); + pre->r8 = _mm_load_si128((xmmi*)r + 2); + pre->r9 = _mm_shuffle_epi32(pre->r8, _MM_SHUFFLE(3,1,3,1)); + pre->r9 = _mm_add_epi64(pre->r9, _mm_and_si128(pre->r9, sse2_top64bitmask.v)); + pre->r8 = _mm_shuffle_epi32(pre->r8, _MM_SHUFFLE(3,0,3,0)); + + pre->r219 = _mm_mul_epu32(pre->r2, packednineteen.v); + pre->r419 = _mm_mul_epu32(pre->r4, packednineteen.v); + pre->r619 = _mm_mul_epu32(pre->r6, packednineteen.v); + pre->r819 = _mm_mul_epu32(pre->r8, packednineteen.v); + pre->r119 = _mm_shuffle_epi32(pre->r1,_MM_SHUFFLE(0,0,2,2)); pre->r119 = _mm_mul_epu32(pre->r119, packednineteen.v); + pre->r319 = _mm_shuffle_epi32(pre->r3,_MM_SHUFFLE(0,0,2,2)); pre->r319 = _mm_mul_epu32(pre->r319, packednineteen.v); + pre->r519 = _mm_shuffle_epi32(pre->r5,_MM_SHUFFLE(0,0,2,2)); pre->r519 = _mm_mul_epu32(pre->r519, packednineteen.v); + pre->r719 = _mm_shuffle_epi32(pre->r7,_MM_SHUFFLE(0,0,2,2)); pre->r719 = _mm_mul_epu32(pre->r719, packednineteen.v); + pre->r919 = _mm_shuffle_epi32(pre->r9,_MM_SHUFFLE(0,0,2,2)); pre->r919 = _mm_mul_epu32(pre->r919, packednineteen.v); +} + + +/* multiply a bignum by a pre-computed constant */ +inline void +curve25519_mul_precomputed(bignum25519 out, const bignum25519 s, const bignum25519mulprecomp *r) { + xmmi m01,m23,m45,m67,m89; + xmmi m0123,m4567; + xmmi s0123,s4567; + xmmi s01,s23,s45,s67,s89; + xmmi s12,s34,s56,s78,s9; + xmmi r0,r1,r2,r3,r4,r5; + xmmi c1,c2,c3; + + s0123 = _mm_load_si128((xmmi*)s + 0); + s01 = _mm_shuffle_epi32(s0123,_MM_SHUFFLE(3,1,2,0)); + s12 = _mm_shuffle_epi32(s0123, _MM_SHUFFLE(2,2,1,1)); + s23 = _mm_shuffle_epi32(s0123,_MM_SHUFFLE(3,3,2,2)); + s4567 = _mm_load_si128((xmmi*)s + 1); + s34 = _mm_unpacklo_epi64(_mm_srli_si128(s0123,12),s4567); + s45 = _mm_shuffle_epi32(s4567,_MM_SHUFFLE(3,1,2,0)); + s56 = _mm_shuffle_epi32(s4567, _MM_SHUFFLE(2,2,1,1)); + s67 = _mm_shuffle_epi32(s4567,_MM_SHUFFLE(3,3,2,2)); + s89 = _mm_load_si128((xmmi*)s + 2); + s78 = _mm_unpacklo_epi64(_mm_srli_si128(s4567,12),s89); + s89 = _mm_shuffle_epi32(s89,_MM_SHUFFLE(3,1,2,0)); + s9 = _mm_shuffle_epi32(s89, _MM_SHUFFLE(3,3,2,2)); + + m01 = _mm_mul_epu32(r->r1,s01); + m23 = _mm_mul_epu32(r->r1,s23); + m45 = _mm_mul_epu32(r->r1,s45); + m67 = _mm_mul_epu32(r->r1,s67); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r3,s01)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r3,s23)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r3,s45)); + m89 = _mm_mul_epu32(r->r1,s89); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r5,s01)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r5,s23)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r3,s67)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r7,s01)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r5,s45)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r7,s23)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r9,s01)); + + /* shift up */ + m89 = _mm_unpackhi_epi64(m67,_mm_slli_si128(m89,8)); + m67 = _mm_unpackhi_epi64(m45,_mm_slli_si128(m67,8)); + m45 = _mm_unpackhi_epi64(m23,_mm_slli_si128(m45,8)); + m23 = _mm_unpackhi_epi64(m01,_mm_slli_si128(m23,8)); + m01 = _mm_unpackhi_epi64(_mm_setzero_si128(),_mm_slli_si128(m01,8)); + + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r0,s01)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r0,s23)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r0,s45)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r0,s67)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r2,s01)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r2,s23)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r4,s23)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r0,s89)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r4,s01)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r2,s45)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r2,s67)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r6,s01)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r4,s45)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r6,s23)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r8,s01)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r919,s12)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r919,s34)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r919,s56)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r919,s78)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r719,s34)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r719,s56)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r719,s78)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r719,s9)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r519,s56)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r519,s78)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r519,s9)); + m67 = _mm_add_epi64(m67,_mm_mul_epu32(r->r819,s89)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r319,s78)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r319,s9)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r619,s89)); + m89 = _mm_add_epi64(m89,_mm_mul_epu32(r->r919,s9)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r819,s23)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r819,s45)); + m45 = _mm_add_epi64(m45,_mm_mul_epu32(r->r819,s67)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r619,s45)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r619,s67)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r419,s67)); + m23 = _mm_add_epi64(m23,_mm_mul_epu32(r->r419,s89)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r219,s89)); + m01 = _mm_add_epi64(m01,_mm_mul_epu32(r->r119,s9)); + + r0 = _mm_unpacklo_epi64(m01, m45); + r1 = _mm_unpackhi_epi64(m01, m45); + r2 = _mm_unpacklo_epi64(m23, m67); + r3 = _mm_unpackhi_epi64(m23, m67); + r4 = _mm_unpacklo_epi64(m89, m89); + r5 = _mm_unpackhi_epi64(m89, m89); + + c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); + c1 = _mm_srli_epi64(r1, 25); c2 = _mm_srli_epi64(r3, 25); r1 = _mm_and_si128(r1, packedmask25.v); r3 = _mm_and_si128(r3, packedmask25.v); r2 = _mm_add_epi64(r2, c1); r4 = _mm_add_epi64(r4, c2); c3 = _mm_slli_si128(c2, 8); + c1 = _mm_srli_epi64(r4, 26); r4 = _mm_and_si128(r4, packedmask26.v); r5 = _mm_add_epi64(r5, c1); + c1 = _mm_srli_epi64(r5, 25); r5 = _mm_and_si128(r5, packedmask25.v); r0 = _mm_add_epi64(r0, _mm_unpackhi_epi64(_mm_mul_epu32(c1, packednineteen.v), c3)); + c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); + + m0123 = _mm_unpacklo_epi32(r0, r1); + m4567 = _mm_unpackhi_epi32(r0, r1); + m0123 = _mm_unpacklo_epi64(m0123, _mm_unpacklo_epi32(r2, r3)); + m4567 = _mm_unpacklo_epi64(m4567, _mm_unpackhi_epi32(r2, r3)); + m89 = _mm_unpackhi_epi32(r4, r5); + + _mm_store_si128((xmmi*)out + 0, m0123); + _mm_store_si128((xmmi*)out + 1, m4567); + _mm_store_si128((xmmi*)out + 2, m89); +} + +/* square a bignum 'count' times */ +#define curve25519_square(r,x) curve25519_square_times(r,x,1) + +void +curve25519_square_times(bignum25519 r, const bignum25519 in, int count) { + xmmi m01,m23,m45,m67,m89; + xmmi r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; + xmmi r0a,r1a,r2a,r3a,r7a,r9a; + xmmi r0123,r4567; + xmmi r01,r23,r45,r67,r6x,r89,r8x; + xmmi r12,r34,r56,r78,r9x; + xmmi r5619; + xmmi c1,c2,c3; + + r0123 = _mm_load_si128((xmmi*)in + 0); + r01 = _mm_shuffle_epi32(r0123,_MM_SHUFFLE(3,1,2,0)); + r23 = _mm_shuffle_epi32(r0123,_MM_SHUFFLE(3,3,2,2)); + r4567 = _mm_load_si128((xmmi*)in + 1); + r45 = _mm_shuffle_epi32(r4567,_MM_SHUFFLE(3,1,2,0)); + r67 = _mm_shuffle_epi32(r4567,_MM_SHUFFLE(3,3,2,2)); + r89 = _mm_load_si128((xmmi*)in + 2); + r89 = _mm_shuffle_epi32(r89,_MM_SHUFFLE(3,1,2,0)); + + do { + r12 = _mm_unpackhi_epi64(r01, _mm_slli_si128(r23, 8)); + r0 = _mm_shuffle_epi32(r01, _MM_SHUFFLE(0,0,0,0)); + r0 = _mm_add_epi64(r0, _mm_and_si128(r0, sse2_top64bitmask.v)); + r0a = _mm_shuffle_epi32(r0,_MM_SHUFFLE(3,2,1,2)); + r1 = _mm_shuffle_epi32(r01, _MM_SHUFFLE(2,2,2,2)); + r2 = _mm_shuffle_epi32(r23, _MM_SHUFFLE(0,0,0,0)); + r2 = _mm_add_epi64(r2, _mm_and_si128(r2, sse2_top64bitmask.v)); + r2a = _mm_shuffle_epi32(r2,_MM_SHUFFLE(3,2,1,2)); + r3 = _mm_shuffle_epi32(r23, _MM_SHUFFLE(2,2,2,2)); + r34 = _mm_unpackhi_epi64(r23, _mm_slli_si128(r45, 8)); + r4 = _mm_shuffle_epi32(r45, _MM_SHUFFLE(0,0,0,0)); + r4 = _mm_add_epi64(r4, _mm_and_si128(r4, sse2_top64bitmask.v)); + r56 = _mm_unpackhi_epi64(r45, _mm_slli_si128(r67, 8)); + r5619 = _mm_mul_epu32(r56, packednineteen.v); + r5 = _mm_shuffle_epi32(r5619, _MM_SHUFFLE(1,1,1,0)); + r6 = _mm_shuffle_epi32(r5619, _MM_SHUFFLE(3,2,3,2)); + r78 = _mm_unpackhi_epi64(r67, _mm_slli_si128(r89, 8)); + r6x = _mm_unpacklo_epi64(r67, _mm_setzero_si128()); + r7 = _mm_shuffle_epi32(r67, _MM_SHUFFLE(2,2,2,2)); + r7 = _mm_mul_epu32(r7, packed3819.v); + r7a = _mm_shuffle_epi32(r7, _MM_SHUFFLE(3,3,3,2)); + r8x = _mm_unpacklo_epi64(r89, _mm_setzero_si128()); + r8 = _mm_shuffle_epi32(r89, _MM_SHUFFLE(0,0,0,0)); + r8 = _mm_mul_epu32(r8, packednineteen.v); + r9 = _mm_shuffle_epi32(r89, _MM_SHUFFLE(2,2,2,2)); + r9x = _mm_slli_epi32(_mm_shuffle_epi32(r89, _MM_SHUFFLE(3,3,3,2)), 1); + r9 = _mm_mul_epu32(r9, packed3819.v); + r9a = _mm_shuffle_epi32(r9, _MM_SHUFFLE(2,2,2,2)); + + m01 = _mm_mul_epu32(r01, r0); + m23 = _mm_mul_epu32(r23, r0a); + m45 = _mm_mul_epu32(r45, r0a); + m45 = _mm_add_epi64(m45, _mm_mul_epu32(r23, r2)); + r23 = _mm_slli_epi32(r23, 1); + m67 = _mm_mul_epu32(r67, r0a); + m67 = _mm_add_epi64(m67, _mm_mul_epu32(r45, r2a)); + m89 = _mm_mul_epu32(r89, r0a); + m89 = _mm_add_epi64(m89, _mm_mul_epu32(r67, r2a)); + r67 = _mm_slli_epi32(r67, 1); + m89 = _mm_add_epi64(m89, _mm_mul_epu32(r45, r4)); + r45 = _mm_slli_epi32(r45, 1); + + r1 = _mm_slli_epi32(r1, 1); + r3 = _mm_slli_epi32(r3, 1); + r1a = _mm_add_epi64(r1, _mm_and_si128(r1, sse2_bot64bitmask.v)); + r3a = _mm_add_epi64(r3, _mm_and_si128(r3, sse2_bot64bitmask.v)); + + m23 = _mm_add_epi64(m23, _mm_mul_epu32(r12, r1)); + m45 = _mm_add_epi64(m45, _mm_mul_epu32(r34, r1a)); + m67 = _mm_add_epi64(m67, _mm_mul_epu32(r56, r1a)); + m67 = _mm_add_epi64(m67, _mm_mul_epu32(r34, r3)); + r34 = _mm_slli_epi32(r34, 1); + m89 = _mm_add_epi64(m89, _mm_mul_epu32(r78, r1a)); + r78 = _mm_slli_epi32(r78, 1); + m89 = _mm_add_epi64(m89, _mm_mul_epu32(r56, r3a)); + r56 = _mm_slli_epi32(r56, 1); + + m01 = _mm_add_epi64(m01, _mm_mul_epu32(_mm_slli_epi32(r12, 1), r9)); + m01 = _mm_add_epi64(m01, _mm_mul_epu32(r34, r7)); + m23 = _mm_add_epi64(m23, _mm_mul_epu32(r34, r9)); + m01 = _mm_add_epi64(m01, _mm_mul_epu32(r56, r5)); + m23 = _mm_add_epi64(m23, _mm_mul_epu32(r56, r7)); + m45 = _mm_add_epi64(m45, _mm_mul_epu32(r56, r9)); + m01 = _mm_add_epi64(m01, _mm_mul_epu32(r23, r8)); + m01 = _mm_add_epi64(m01, _mm_mul_epu32(r45, r6)); + m23 = _mm_add_epi64(m23, _mm_mul_epu32(r45, r8)); + m23 = _mm_add_epi64(m23, _mm_mul_epu32(r6x, r6)); + m45 = _mm_add_epi64(m45, _mm_mul_epu32(r78, r7a)); + m67 = _mm_add_epi64(m67, _mm_mul_epu32(r78, r9)); + m45 = _mm_add_epi64(m45, _mm_mul_epu32(r67, r8)); + m67 = _mm_add_epi64(m67, _mm_mul_epu32(r8x, r8)); + m89 = _mm_add_epi64(m89, _mm_mul_epu32(r9x, r9a)); + + r0 = _mm_unpacklo_epi64(m01, m45); + r1 = _mm_unpackhi_epi64(m01, m45); + r2 = _mm_unpacklo_epi64(m23, m67); + r3 = _mm_unpackhi_epi64(m23, m67); + r4 = _mm_unpacklo_epi64(m89, m89); + r5 = _mm_unpackhi_epi64(m89, m89); + + c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); + c1 = _mm_srli_epi64(r1, 25); c2 = _mm_srli_epi64(r3, 25); r1 = _mm_and_si128(r1, packedmask25.v); r3 = _mm_and_si128(r3, packedmask25.v); r2 = _mm_add_epi64(r2, c1); r4 = _mm_add_epi64(r4, c2); c3 = _mm_slli_si128(c2, 8); + c1 = _mm_srli_epi64(r4, 26); r4 = _mm_and_si128(r4, packedmask26.v); r5 = _mm_add_epi64(r5, c1); + c1 = _mm_srli_epi64(r5, 25); r5 = _mm_and_si128(r5, packedmask25.v); r0 = _mm_add_epi64(r0, _mm_unpackhi_epi64(_mm_mul_epu32(c1, packednineteen.v), c3)); + c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); + + r01 = _mm_unpacklo_epi64(r0, r1); + r45 = _mm_unpackhi_epi64(r0, r1); + r23 = _mm_unpacklo_epi64(r2, r3); + r67 = _mm_unpackhi_epi64(r2, r3); + r89 = _mm_unpackhi_epi64(r4, r5); + } while (--count); + + r0123 = _mm_shuffle_epi32(r23, _MM_SHUFFLE(2,0,3,3)); + r4567 = _mm_shuffle_epi32(r67, _MM_SHUFFLE(2,0,3,3)); + r0123 = _mm_or_si128(r0123, _mm_shuffle_epi32(r01, _MM_SHUFFLE(3,3,2,0))); + r4567 = _mm_or_si128(r4567, _mm_shuffle_epi32(r45, _MM_SHUFFLE(3,3,2,0))); + r89 = _mm_shuffle_epi32(r89, _MM_SHUFFLE(3,3,2,0)); + + _mm_store_si128((xmmi*)r + 0, r0123); + _mm_store_si128((xmmi*)r + 1, r4567); + _mm_store_si128((xmmi*)r + 2, r89); +} + +/* square two packed bignums */ +inline void +curve25519_square_packed64(packedelem64 *out, const packedelem64 *r) { + xmmi r0,r1,r2,r3; + xmmi r1_2,r3_2,r4_2,r5_2,r6_2,r7_2; + xmmi d5,d6,d7,d8,d9; + xmmi c1,c2; + + r0 = r[0].v; + r1 = r[1].v; + r2 = r[2].v; + r3 = r[3].v; + + out[0].v = _mm_mul_epu32(r0, r0); + r0 = _mm_slli_epi32(r0, 1); + out[1].v = _mm_mul_epu32(r0, r1); + r1_2 = _mm_slli_epi32(r1, 1); + out[2].v = _mm_add_epi64(_mm_mul_epu32(r0, r2 ), _mm_mul_epu32(r1, r1_2)); + r1 = r1_2; + out[3].v = _mm_add_epi64(_mm_mul_epu32(r0, r3 ), _mm_mul_epu32(r1, r2 )); + r3_2 = _mm_slli_epi32(r3, 1); + out[4].v = _mm_add_epi64(_mm_mul_epu32(r0, r[4].v), _mm_add_epi64(_mm_mul_epu32(r1, r3_2 ), _mm_mul_epu32(r2, r2))); + r2 = _mm_slli_epi32(r2, 1); + out[5].v = _mm_add_epi64(_mm_mul_epu32(r0, r[5].v), _mm_add_epi64(_mm_mul_epu32(r1, r[4].v), _mm_mul_epu32(r2, r3))); + r5_2 = _mm_slli_epi32(r[5].v, 1); + out[6].v = _mm_add_epi64(_mm_mul_epu32(r0, r[6].v), _mm_add_epi64(_mm_mul_epu32(r1, r5_2 ), _mm_add_epi64(_mm_mul_epu32(r2, r[4].v), _mm_mul_epu32(r3, r3_2 )))); + r3 = r3_2; + out[7].v = _mm_add_epi64(_mm_mul_epu32(r0, r[7].v), _mm_add_epi64(_mm_mul_epu32(r1, r[6].v), _mm_add_epi64(_mm_mul_epu32(r2, r[5].v), _mm_mul_epu32(r3, r[4].v)))); + r7_2 = _mm_slli_epi32(r[7].v, 1); + out[8].v = _mm_add_epi64(_mm_mul_epu32(r0, r[8].v), _mm_add_epi64(_mm_mul_epu32(r1, r7_2 ), _mm_add_epi64(_mm_mul_epu32(r2, r[6].v), _mm_add_epi64(_mm_mul_epu32(r3, r5_2 ), _mm_mul_epu32(r[4].v, r[4].v))))); + out[9].v = _mm_add_epi64(_mm_mul_epu32(r0, r[9].v), _mm_add_epi64(_mm_mul_epu32(r1, r[8].v), _mm_add_epi64(_mm_mul_epu32(r2, r[7].v), _mm_add_epi64(_mm_mul_epu32(r3, r[6].v), _mm_mul_epu32(r[4].v, r5_2 ))))); + + d5 = _mm_mul_epu32(r[5].v, packedthirtyeight.v); + d6 = _mm_mul_epu32(r[6].v, packednineteen.v); + d7 = _mm_mul_epu32(r[7].v, packedthirtyeight.v); + d8 = _mm_mul_epu32(r[8].v, packednineteen.v); + d9 = _mm_mul_epu32(r[9].v, packedthirtyeight.v); + + r4_2 = _mm_slli_epi32(r[4].v, 1); + r6_2 = _mm_slli_epi32(r[6].v, 1); + out[0].v = _mm_add_epi64(out[0].v, _mm_add_epi64(_mm_mul_epu32(d9, r1 ), _mm_add_epi64(_mm_mul_epu32(d8, r2 ), _mm_add_epi64(_mm_mul_epu32(d7, r3 ), _mm_add_epi64(_mm_mul_epu32(d6, r4_2), _mm_mul_epu32(d5, r[5].v)))))); + out[1].v = _mm_add_epi64(out[1].v, _mm_add_epi64(_mm_mul_epu32(d9, _mm_srli_epi32(r2, 1)), _mm_add_epi64(_mm_mul_epu32(d8, r3 ), _mm_add_epi64(_mm_mul_epu32(d7, r[4].v), _mm_mul_epu32(d6, r5_2 ))))); + out[2].v = _mm_add_epi64(out[2].v, _mm_add_epi64(_mm_mul_epu32(d9, r3 ), _mm_add_epi64(_mm_mul_epu32(d8, r4_2), _mm_add_epi64(_mm_mul_epu32(d7, r5_2 ), _mm_mul_epu32(d6, r[6].v))))); + out[3].v = _mm_add_epi64(out[3].v, _mm_add_epi64(_mm_mul_epu32(d9, r[4].v ), _mm_add_epi64(_mm_mul_epu32(d8, r5_2), _mm_mul_epu32(d7, r[6].v)))); + out[4].v = _mm_add_epi64(out[4].v, _mm_add_epi64(_mm_mul_epu32(d9, r5_2 ), _mm_add_epi64(_mm_mul_epu32(d8, r6_2), _mm_mul_epu32(d7, r[7].v)))); + out[5].v = _mm_add_epi64(out[5].v, _mm_add_epi64(_mm_mul_epu32(d9, r[6].v ), _mm_mul_epu32(d8, r7_2 ))); + out[6].v = _mm_add_epi64(out[6].v, _mm_add_epi64(_mm_mul_epu32(d9, r7_2 ), _mm_mul_epu32(d8, r[8].v))); + out[7].v = _mm_add_epi64(out[7].v, _mm_mul_epu32(d9, r[8].v)); + out[8].v = _mm_add_epi64(out[8].v, _mm_mul_epu32(d9, r[9].v)); + + c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); + c1 = _mm_srli_epi64(out[1].v, 25); c2 = _mm_srli_epi64(out[5].v, 25); out[1].v = _mm_and_si128(out[1].v, packedmask25.v); out[5].v = _mm_and_si128(out[5].v, packedmask25.v); out[2].v = _mm_add_epi64(out[2].v, c1); out[6].v = _mm_add_epi64(out[6].v, c2); + c1 = _mm_srli_epi64(out[2].v, 26); c2 = _mm_srli_epi64(out[6].v, 26); out[2].v = _mm_and_si128(out[2].v, packedmask26.v); out[6].v = _mm_and_si128(out[6].v, packedmask26.v); out[3].v = _mm_add_epi64(out[3].v, c1); out[7].v = _mm_add_epi64(out[7].v, c2); + c1 = _mm_srli_epi64(out[3].v, 25); c2 = _mm_srli_epi64(out[7].v, 25); out[3].v = _mm_and_si128(out[3].v, packedmask25.v); out[7].v = _mm_and_si128(out[7].v, packedmask25.v); out[4].v = _mm_add_epi64(out[4].v, c1); out[8].v = _mm_add_epi64(out[8].v, c2); + c2 = _mm_srli_epi64(out[8].v, 26); out[8].v = _mm_and_si128(out[8].v, packedmask26.v); out[9].v = _mm_add_epi64(out[9].v, c2); + c2 = _mm_srli_epi64(out[9].v, 25); out[9].v = _mm_and_si128(out[9].v, packedmask25.v); out[0].v = _mm_add_epi64(out[0].v, _mm_mul_epu32(c2, packednineteen.v)); + c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); +} + +/* make [nqx+nqz,nqpqx+nqpqz], [nqpqx-nqpqz,nqx-nqz] from [nqx+nqz,nqpqx+nqpqz], [nqx-nqz,nqpqx-nqpqz] */ +inline void +curve25519_make_nqpq(packedelem64 *primex, packedelem64 *primez, const packedelem32 *pqx, const packedelem32 *pqz) { + primex[0].v = _mm_shuffle_epi32(pqx[0].v, _MM_SHUFFLE(1,1,0,0)); + primex[1].v = _mm_shuffle_epi32(pqx[0].v, _MM_SHUFFLE(3,3,2,2)); + primex[2].v = _mm_shuffle_epi32(pqx[1].v, _MM_SHUFFLE(1,1,0,0)); + primex[3].v = _mm_shuffle_epi32(pqx[1].v, _MM_SHUFFLE(3,3,2,2)); + primex[4].v = _mm_shuffle_epi32(pqx[2].v, _MM_SHUFFLE(1,1,0,0)); + primex[5].v = _mm_shuffle_epi32(pqx[2].v, _MM_SHUFFLE(3,3,2,2)); + primex[6].v = _mm_shuffle_epi32(pqx[3].v, _MM_SHUFFLE(1,1,0,0)); + primex[7].v = _mm_shuffle_epi32(pqx[3].v, _MM_SHUFFLE(3,3,2,2)); + primex[8].v = _mm_shuffle_epi32(pqx[4].v, _MM_SHUFFLE(1,1,0,0)); + primex[9].v = _mm_shuffle_epi32(pqx[4].v, _MM_SHUFFLE(3,3,2,2)); + primez[0].v = _mm_shuffle_epi32(pqz[0].v, _MM_SHUFFLE(0,0,1,1)); + primez[1].v = _mm_shuffle_epi32(pqz[0].v, _MM_SHUFFLE(2,2,3,3)); + primez[2].v = _mm_shuffle_epi32(pqz[1].v, _MM_SHUFFLE(0,0,1,1)); + primez[3].v = _mm_shuffle_epi32(pqz[1].v, _MM_SHUFFLE(2,2,3,3)); + primez[4].v = _mm_shuffle_epi32(pqz[2].v, _MM_SHUFFLE(0,0,1,1)); + primez[5].v = _mm_shuffle_epi32(pqz[2].v, _MM_SHUFFLE(2,2,3,3)); + primez[6].v = _mm_shuffle_epi32(pqz[3].v, _MM_SHUFFLE(0,0,1,1)); + primez[7].v = _mm_shuffle_epi32(pqz[3].v, _MM_SHUFFLE(2,2,3,3)); + primez[8].v = _mm_shuffle_epi32(pqz[4].v, _MM_SHUFFLE(0,0,1,1)); + primez[9].v = _mm_shuffle_epi32(pqz[4].v, _MM_SHUFFLE(2,2,3,3)); +} + +/* make [nqx+nqz,nqx-nqz] from [nqx+nqz,nqpqx+nqpqz], [nqx-nqz,nqpqx-nqpqz] */ +inline void +curve25519_make_nq(packedelem64 *nq, const packedelem32 *pqx, const packedelem32 *pqz) { + nq[0].v = _mm_unpacklo_epi64(pqx[0].v, pqz[0].v); + nq[1].v = _mm_unpackhi_epi64(pqx[0].v, pqz[0].v); + nq[2].v = _mm_unpacklo_epi64(pqx[1].v, pqz[1].v); + nq[3].v = _mm_unpackhi_epi64(pqx[1].v, pqz[1].v); + nq[4].v = _mm_unpacklo_epi64(pqx[2].v, pqz[2].v); + nq[5].v = _mm_unpackhi_epi64(pqx[2].v, pqz[2].v); + nq[6].v = _mm_unpacklo_epi64(pqx[3].v, pqz[3].v); + nq[7].v = _mm_unpackhi_epi64(pqx[3].v, pqz[3].v); + nq[8].v = _mm_unpacklo_epi64(pqx[4].v, pqz[4].v); + nq[9].v = _mm_unpackhi_epi64(pqx[4].v, pqz[4].v); +} + +/* compute [nqx+nqz,nqx-nqz] from nqx, nqz */ +inline void +curve25519_compute_nq(packedelem64 *nq, const bignum25519 nqx, const bignum25519 nqz) { + xmmi x0,x1,x2; + xmmi z0,z1,z2; + xmmi a0,a1,a2; + xmmi s0,s1,s2; + xmmi r0,r1; + xmmi c1,c2; + x0 = _mm_load_si128((xmmi*)nqx + 0); + x1 = _mm_load_si128((xmmi*)nqx + 1); + x2 = _mm_load_si128((xmmi*)nqx + 2); + z0 = _mm_load_si128((xmmi*)nqz + 0); + z1 = _mm_load_si128((xmmi*)nqz + 1); + z2 = _mm_load_si128((xmmi*)nqz + 2); + a0 = _mm_add_epi32(x0, z0); + a1 = _mm_add_epi32(x1, z1); + a2 = _mm_add_epi32(x2, z2); + s0 = _mm_add_epi32(x0, packed2p0.v); + s1 = _mm_add_epi32(x1, packed2p1.v); + s2 = _mm_add_epi32(x2, packed2p2.v); + s0 = _mm_sub_epi32(s0, z0); + s1 = _mm_sub_epi32(s1, z1); + s2 = _mm_sub_epi32(s2, z2); + r0 = _mm_and_si128(_mm_shuffle_epi32(s0, _MM_SHUFFLE(2,2,0,0)), sse2_bot32bitmask.v); + r1 = _mm_and_si128(_mm_shuffle_epi32(s0, _MM_SHUFFLE(3,3,1,1)), sse2_bot32bitmask.v); + c1 = _mm_srli_epi32(r0, 26); + c2 = _mm_srli_epi32(r1, 25); + r0 = _mm_and_si128(r0, packedmask26.v); + r1 = _mm_and_si128(r1, packedmask25.v); + r0 = _mm_add_epi32(r0, _mm_slli_si128(c2, 8)); + r1 = _mm_add_epi32(r1, c1); + s0 = _mm_unpacklo_epi64(_mm_unpacklo_epi32(r0, r1), _mm_unpackhi_epi32(r0, r1)); + s1 = _mm_add_epi32(s1, _mm_srli_si128(c2, 8)); + nq[0].v = _mm_unpacklo_epi64(a0, s0); + nq[2].v = _mm_unpackhi_epi64(a0, s0); + nq[4].v = _mm_unpacklo_epi64(a1, s1); + nq[6].v = _mm_unpackhi_epi64(a1, s1); + nq[8].v = _mm_unpacklo_epi64(a2, s2); + nq[1].v = _mm_shuffle_epi32(nq[0].v, _MM_SHUFFLE(3,3,1,1)); + nq[3].v = _mm_shuffle_epi32(nq[2].v, _MM_SHUFFLE(3,3,1,1)); + nq[5].v = _mm_shuffle_epi32(nq[4].v, _MM_SHUFFLE(3,3,1,1)); + nq[7].v = _mm_shuffle_epi32(nq[6].v, _MM_SHUFFLE(3,3,1,1)); + nq[9].v = _mm_shuffle_epi32(nq[8].v, _MM_SHUFFLE(3,3,1,1)); +} + + +/* compute [x+z,x-z] from [x,z] */ +inline void +curve25519_addsub_packed64(packedelem64 *r) { + packed32bignum25519 x,z,add,sub; + + x[0].v = _mm_unpacklo_epi64(r[0].v, r[1].v); + z[0].v = _mm_unpackhi_epi64(r[0].v, r[1].v); + x[1].v = _mm_unpacklo_epi64(r[2].v, r[3].v); + z[1].v = _mm_unpackhi_epi64(r[2].v, r[3].v); + x[2].v = _mm_unpacklo_epi64(r[4].v, r[5].v); + z[2].v = _mm_unpackhi_epi64(r[4].v, r[5].v); + x[3].v = _mm_unpacklo_epi64(r[6].v, r[7].v); + z[3].v = _mm_unpackhi_epi64(r[6].v, r[7].v); + x[4].v = _mm_unpacklo_epi64(r[8].v, r[9].v); + z[4].v = _mm_unpackhi_epi64(r[8].v, r[9].v); + + curve25519_add_packed32(add, x, z); + curve25519_sub_packed32(sub, x, z); + + r[0].v = _mm_unpacklo_epi64(add[0].v, sub[0].v); + r[1].v = _mm_unpackhi_epi64(add[0].v, sub[0].v); + r[2].v = _mm_unpacklo_epi64(add[1].v, sub[1].v); + r[3].v = _mm_unpackhi_epi64(add[1].v, sub[1].v); + r[4].v = _mm_unpacklo_epi64(add[2].v, sub[2].v); + r[5].v = _mm_unpackhi_epi64(add[2].v, sub[2].v); + r[6].v = _mm_unpacklo_epi64(add[3].v, sub[3].v); + r[7].v = _mm_unpackhi_epi64(add[3].v, sub[3].v); + r[8].v = _mm_unpacklo_epi64(add[4].v, sub[4].v); + r[9].v = _mm_unpackhi_epi64(add[4].v, sub[4].v); +} + +/* compute [x,z] * [121666,121665] */ +inline void +curve25519_121665_packed64(packedelem64 *out, const packedelem64 *in) { + xmmi c1,c2; + + out[0].v = _mm_mul_epu32(in[0].v, packed121666121665.v); + out[1].v = _mm_mul_epu32(in[1].v, packed121666121665.v); + out[2].v = _mm_mul_epu32(in[2].v, packed121666121665.v); + out[3].v = _mm_mul_epu32(in[3].v, packed121666121665.v); + out[4].v = _mm_mul_epu32(in[4].v, packed121666121665.v); + out[5].v = _mm_mul_epu32(in[5].v, packed121666121665.v); + out[6].v = _mm_mul_epu32(in[6].v, packed121666121665.v); + out[7].v = _mm_mul_epu32(in[7].v, packed121666121665.v); + out[8].v = _mm_mul_epu32(in[8].v, packed121666121665.v); + out[9].v = _mm_mul_epu32(in[9].v, packed121666121665.v); + + c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); + c1 = _mm_srli_epi64(out[1].v, 25); c2 = _mm_srli_epi64(out[5].v, 25); out[1].v = _mm_and_si128(out[1].v, packedmask25.v); out[5].v = _mm_and_si128(out[5].v, packedmask25.v); out[2].v = _mm_add_epi64(out[2].v, c1); out[6].v = _mm_add_epi64(out[6].v, c2); + c1 = _mm_srli_epi64(out[2].v, 26); c2 = _mm_srli_epi64(out[6].v, 26); out[2].v = _mm_and_si128(out[2].v, packedmask26.v); out[6].v = _mm_and_si128(out[6].v, packedmask26.v); out[3].v = _mm_add_epi64(out[3].v, c1); out[7].v = _mm_add_epi64(out[7].v, c2); + c1 = _mm_srli_epi64(out[3].v, 25); c2 = _mm_srli_epi64(out[7].v, 25); out[3].v = _mm_and_si128(out[3].v, packedmask25.v); out[7].v = _mm_and_si128(out[7].v, packedmask25.v); out[4].v = _mm_add_epi64(out[4].v, c1); out[8].v = _mm_add_epi64(out[8].v, c2); + c2 = _mm_srli_epi64(out[8].v, 26); out[8].v = _mm_and_si128(out[8].v, packedmask26.v); out[9].v = _mm_add_epi64(out[9].v, c2); + c2 = _mm_srli_epi64(out[9].v, 25); out[9].v = _mm_and_si128(out[9].v, packedmask25.v); out[0].v = _mm_add_epi64(out[0].v, _mm_mul_epu32(c2, packednineteen.v)); + c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); +} + +/* compute [sq.x,sqscalar.x-sqscalar.z] * [sq.z,sq.x-sq.z] */ +inline void +curve25519_final_nq(packedelem64 *nq, const packedelem64 *sq, const packedelem64 *sq121665) { + packed32bignum25519 x, z, sub; + packed64bignum25519 t, nqa, nqb; + + x[0].v = _mm_or_si128(_mm_unpacklo_epi64(sq[0].v, sq[1].v), _mm_slli_si128(_mm_unpacklo_epi64(sq121665[0].v, sq121665[1].v), 4)); + z[0].v = _mm_or_si128(_mm_unpackhi_epi64(sq[0].v, sq[1].v), _mm_slli_si128(_mm_unpackhi_epi64(sq121665[0].v, sq121665[1].v), 4)); + x[1].v = _mm_or_si128(_mm_unpacklo_epi64(sq[2].v, sq[3].v), _mm_slli_si128(_mm_unpacklo_epi64(sq121665[2].v, sq121665[3].v), 4)); + z[1].v = _mm_or_si128(_mm_unpackhi_epi64(sq[2].v, sq[3].v), _mm_slli_si128(_mm_unpackhi_epi64(sq121665[2].v, sq121665[3].v), 4)); + x[2].v = _mm_or_si128(_mm_unpacklo_epi64(sq[4].v, sq[5].v), _mm_slli_si128(_mm_unpacklo_epi64(sq121665[4].v, sq121665[5].v), 4)); + z[2].v = _mm_or_si128(_mm_unpackhi_epi64(sq[4].v, sq[5].v), _mm_slli_si128(_mm_unpackhi_epi64(sq121665[4].v, sq121665[5].v), 4)); + x[3].v = _mm_or_si128(_mm_unpacklo_epi64(sq[6].v, sq[7].v), _mm_slli_si128(_mm_unpacklo_epi64(sq121665[6].v, sq121665[7].v), 4)); + z[3].v = _mm_or_si128(_mm_unpackhi_epi64(sq[6].v, sq[7].v), _mm_slli_si128(_mm_unpackhi_epi64(sq121665[6].v, sq121665[7].v), 4)); + x[4].v = _mm_or_si128(_mm_unpacklo_epi64(sq[8].v, sq[9].v), _mm_slli_si128(_mm_unpacklo_epi64(sq121665[8].v, sq121665[9].v), 4)); + z[4].v = _mm_or_si128(_mm_unpackhi_epi64(sq[8].v, sq[9].v), _mm_slli_si128(_mm_unpackhi_epi64(sq121665[8].v, sq121665[9].v), 4)); + + curve25519_sub_packed32(sub, x, z); + + t[0].v = _mm_shuffle_epi32(sub[0].v, _MM_SHUFFLE(1,1,0,0)); + t[1].v = _mm_shuffle_epi32(sub[0].v, _MM_SHUFFLE(3,3,2,2)); + t[2].v = _mm_shuffle_epi32(sub[1].v, _MM_SHUFFLE(1,1,0,0)); + t[3].v = _mm_shuffle_epi32(sub[1].v, _MM_SHUFFLE(3,3,2,2)); + t[4].v = _mm_shuffle_epi32(sub[2].v, _MM_SHUFFLE(1,1,0,0)); + t[5].v = _mm_shuffle_epi32(sub[2].v, _MM_SHUFFLE(3,3,2,2)); + t[6].v = _mm_shuffle_epi32(sub[3].v, _MM_SHUFFLE(1,1,0,0)); + t[7].v = _mm_shuffle_epi32(sub[3].v, _MM_SHUFFLE(3,3,2,2)); + t[8].v = _mm_shuffle_epi32(sub[4].v, _MM_SHUFFLE(1,1,0,0)); + t[9].v = _mm_shuffle_epi32(sub[4].v, _MM_SHUFFLE(3,3,2,2)); + + nqa[0].v = _mm_unpacklo_epi64(sq[0].v, t[0].v); + nqb[0].v = _mm_unpackhi_epi64(sq[0].v, t[0].v); + nqa[1].v = _mm_unpacklo_epi64(sq[1].v, t[1].v); + nqb[1].v = _mm_unpackhi_epi64(sq[1].v, t[1].v); + nqa[2].v = _mm_unpacklo_epi64(sq[2].v, t[2].v); + nqb[2].v = _mm_unpackhi_epi64(sq[2].v, t[2].v); + nqa[3].v = _mm_unpacklo_epi64(sq[3].v, t[3].v); + nqb[3].v = _mm_unpackhi_epi64(sq[3].v, t[3].v); + nqa[4].v = _mm_unpacklo_epi64(sq[4].v, t[4].v); + nqb[4].v = _mm_unpackhi_epi64(sq[4].v, t[4].v); + nqa[5].v = _mm_unpacklo_epi64(sq[5].v, t[5].v); + nqb[5].v = _mm_unpackhi_epi64(sq[5].v, t[5].v); + nqa[6].v = _mm_unpacklo_epi64(sq[6].v, t[6].v); + nqb[6].v = _mm_unpackhi_epi64(sq[6].v, t[6].v); + nqa[7].v = _mm_unpacklo_epi64(sq[7].v, t[7].v); + nqb[7].v = _mm_unpackhi_epi64(sq[7].v, t[7].v); + nqa[8].v = _mm_unpacklo_epi64(sq[8].v, t[8].v); + nqb[8].v = _mm_unpackhi_epi64(sq[8].v, t[8].v); + nqa[9].v = _mm_unpacklo_epi64(sq[9].v, t[9].v); + nqb[9].v = _mm_unpackhi_epi64(sq[9].v, t[9].v); + + curve25519_mul_packed64(nq, nqa, nqb); +} + +/* + * In: b = 2^5 - 2^0 + * Out: b = 2^250 - 2^0 + */ +void +curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) { + ALIGN(16) bignum25519 t0,c; + + /* 2^5 - 2^0 */ /* b */ + /* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5); + /* 2^10 - 2^0 */ curve25519_mul(b, t0, b); + /* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10); + /* 2^20 - 2^0 */ curve25519_mul(c, t0, b); + /* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20); + /* 2^40 - 2^0 */ curve25519_mul(t0, t0, c); + /* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10); + /* 2^50 - 2^0 */ curve25519_mul(b, t0, b); + /* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50); + /* 2^100 - 2^0 */ curve25519_mul(c, t0, b); + /* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100); + /* 2^200 - 2^0 */ curve25519_mul(t0, t0, c); + /* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50); + /* 2^250 - 2^0 */ curve25519_mul(b, t0, b); +} + +/* + * z^(p - 2) = z(2^255 - 21) + */ +void +curve25519_recip(bignum25519 out, const bignum25519 z) { + ALIGN(16) bignum25519 a, t0, b; + + /* 2 */ curve25519_square(a, z); /* a = 2 */ + /* 8 */ curve25519_square_times(t0, a, 2); + /* 9 */ curve25519_mul(b, t0, z); /* b = 9 */ + /* 11 */ curve25519_mul(a, b, a); /* a = 11 */ + /* 22 */ curve25519_square(t0, a); + /* 2^5 - 2^0 = 31 */ curve25519_mul(b, t0, b); + /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b); + /* 2^255 - 2^5 */ curve25519_square_times(b, b, 5); + /* 2^255 - 21 */ curve25519_mul(out, b, a); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Donna) + +int curve25519_mult_SSE2(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]) +{ + FixedSizeSecBlock e; + for (size_t i = 0;i < 32;++i) + e[i] = secretKey[i]; + e[0] &= 0xf8; e[31] &= 0x7f; e[31] |= 0x40; + + ALIGN(16) bignum25519 nqx = {1}, nqpqz = {1}, nqz = {0}, nqpqx, zmone; + packed32bignum25519 qx, qz, pqz, pqx; + packed64bignum25519 nq, sq, sqscalar, prime, primex, primez, nqpq; + bignum25519mulprecomp preq; + size_t bit=0; + + curve25519_expand(nqpqx, othersKey); + curve25519_mul_precompute(&preq, nqpqx); + + /* do bits 254..3 */ + for (size_t i = 254, lastbit=0; i >= 3; i--) { + bit = (e[i/8] >> (i & 7)) & 1; + curve25519_swap_conditional(nqx, nqpqx, (word32)(bit ^ lastbit)); + curve25519_swap_conditional(nqz, nqpqz, (word32)(bit ^ lastbit)); + lastbit = bit; + + curve25519_tangle32(qx, nqx, nqpqx); /* qx = [nqx,nqpqx] */ + curve25519_tangle32(qz, nqz, nqpqz); /* qz = [nqz,nqpqz] */ + + curve25519_add_packed32(pqx, qx, qz); /* pqx = [nqx+nqz,nqpqx+nqpqz] */ + curve25519_sub_packed32(pqz, qx, qz); /* pqz = [nqx-nqz,nqpqx-nqpqz] */ + + curve25519_make_nqpq(primex, primez, pqx, pqz); /* primex = [nqx+nqz,nqpqx+nqpqz], primez = [nqpqx-nqpqz,nqx-nqz] */ + curve25519_mul_packed64(prime, primex, primez); /* prime = [nqx+nqz,nqpqx+nqpqz] * [nqpqx-nqpqz,nqx-nqz] */ + curve25519_addsub_packed64(prime); /* prime = [prime.x+prime.z,prime.x-prime.z] */ + curve25519_square_packed64(nqpq, prime); /* nqpq = prime^2 */ + curve25519_untangle64(nqpqx, nqpqz, nqpq); + curve25519_mul_precomputed(nqpqz, nqpqz, &preq); /* nqpqz = nqpqz * q */ + + /* (((sq.x-sq.z)*121665)+sq.x) * (sq.x-sq.z) is equivalent to (sq.x*121666-sq.z*121665) * (sq.x-sq.z) */ + curve25519_make_nq(nq, pqx, pqz); /* nq = [nqx+nqz,nqx-nqz] */ + curve25519_square_packed64(sq, nq); /* sq = nq^2 */ + curve25519_121665_packed64(sqscalar, sq); /* sqscalar = sq * [121666,121665] */ + curve25519_final_nq(nq, sq, sqscalar); /* nq = [sq.x,sqscalar.x-sqscalar.z] * [sq.z,sq.x-sq.z] */ + curve25519_untangle64(nqx, nqz, nq); + }; + + /* it's possible to get rid of this swap with the swap in the above loop + at the bottom instead of the top, but compilers seem to optimize better this way */ + curve25519_swap_conditional(nqx, nqpqx, (word32)bit); + curve25519_swap_conditional(nqz, nqpqz, (word32)bit); + + /* do bits 2..0 */ + for (size_t i = 0; i < 3; i++) { + curve25519_compute_nq(nq, nqx, nqz); + curve25519_square_packed64(sq, nq); /* sq = nq^2 */ + curve25519_121665_packed64(sqscalar, sq); /* sqscalar = sq * [121666,121665] */ + curve25519_final_nq(nq, sq, sqscalar); /* nq = [sq.x,sqscalar.x-sqscalar.z] * [sq.z,sq.x-sq.z] */ + curve25519_untangle64(nqx, nqz, nq); + } + + curve25519_recip(zmone, nqz); + curve25519_mul(nqz, nqx, zmone); + curve25519_contract(sharedKey, nqz); + + return 0; +} + +NAMESPACE_END // Donna +NAMESPACE_END // CryptoPP + +#endif // CRYPTOPP_CURVE25519_SSE2 diff --git a/external/ours/library/crypto/src/shared/original/donna_sse.h b/external/ours/library/crypto/src/shared/original/donna_sse.h new file mode 100755 index 000000000..298a91417 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/drbg.h b/external/ours/library/crypto/src/shared/original/drbg.h new file mode 100755 index 000000000..b56256def --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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); + 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/external/ours/library/crypto/src/shared/original/dsa.cpp b/external/ours/library/crypto/src/shared/original/dsa.cpp new file mode 100755 index 000000000..6bc187a91 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/dsa.cpp @@ -0,0 +1,66 @@ +// dsa.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "dsa.h" +#include "asn.h" +#include "integer.h" +#include "filters.h" +#include "nbtheory.h" + +NAMESPACE_BEGIN(CryptoPP) + +size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat, const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat) +{ + Integer r, s; + StringStore store(signature, signatureLen); + ArraySink sink(buffer, bufferSize); + + switch (fromFormat) + { + case DSA_P1363: + r.Decode(store, signatureLen/2); + s.Decode(store, signatureLen/2); + break; + case DSA_DER: + { + BERSequenceDecoder seq(store); + r.BERDecode(seq); + s.BERDecode(seq); + seq.MessageEnd(); + break; + } + case DSA_OPENPGP: + r.OpenPGPDecode(store); + s.OpenPGPDecode(store); + break; + } + + switch (toFormat) + { + case DSA_P1363: + r.Encode(sink, bufferSize/2); + s.Encode(sink, bufferSize/2); + break; + case DSA_DER: + { + DERSequenceEncoder seq(sink); + r.DEREncode(seq); + s.DEREncode(seq); + seq.MessageEnd(); + break; + } + case DSA_OPENPGP: + r.OpenPGPEncode(sink); + s.OpenPGPEncode(sink); + break; + } + + return (size_t)sink.TotalPutLength(); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/dsa.h b/external/ours/library/crypto/src/shared/original/dsa.h new file mode 100755 index 000000000..01e5fecdf --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/eax.cpp b/external/ours/library/crypto/src/shared/original/eax.cpp new file mode 100755 index 000000000..90b9d90b8 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/eax.cpp @@ -0,0 +1,59 @@ +// eax.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "eax.h" + +NAMESPACE_BEGIN(CryptoPP) + +void EAX_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) +{ + AccessMAC().SetKey(userKey, keylength, params); + m_buffer.New(2*AccessMAC().TagSize()); +} + +void EAX_Base::Resync(const byte *iv, size_t len) +{ + MessageAuthenticationCode &mac = AccessMAC(); + unsigned int blockSize = mac.TagSize(); + + memset(m_buffer, 0, blockSize); + mac.Update(m_buffer, blockSize); + mac.CalculateDigest(m_buffer+blockSize, iv, len); + + m_buffer[blockSize-1] = 1; + mac.Update(m_buffer, blockSize); + + m_ctr.SetCipherWithIV(AccessMAC().AccessCipher(), m_buffer+blockSize, blockSize); +} + +size_t EAX_Base::AuthenticateBlocks(const byte *data, size_t len) +{ + AccessMAC().Update(data, len); + return 0; +} + +void EAX_Base::AuthenticateLastHeaderBlock() +{ + CRYPTOPP_ASSERT(m_bufferedDataLength == 0); + MessageAuthenticationCode &mac = AccessMAC(); + const unsigned int blockSize = mac.TagSize(); + + mac.Final(m_buffer); + xorbuf(m_buffer+blockSize, m_buffer, blockSize); + + memset(m_buffer, 0, blockSize); + m_buffer[blockSize-1] = 2; + mac.Update(m_buffer, blockSize); +} + +void EAX_Base::AuthenticateLastFooterBlock(byte *tag, size_t macSize) +{ + CRYPTOPP_ASSERT(m_bufferedDataLength == 0); + MessageAuthenticationCode &mac = AccessMAC(); + unsigned int blockSize = mac.TagSize(); + + mac.TruncatedFinal(m_buffer, macSize); + xorbuf(tag, m_buffer, m_buffer+blockSize, macSize); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/eax.h b/external/ours/library/crypto/src/shared/original/eax.h new file mode 100755 index 000000000..9d4edfaae --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/ec2n.cpp b/external/ours/library/crypto/src/shared/original/ec2n.cpp new file mode 100755 index 000000000..87aed8532 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ec2n.cpp @@ -0,0 +1,320 @@ +// ec2n.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "ec2n.h" +#include "asn.h" +#include "integer.h" +#include "filters.h" +#include "algebra.cpp" +#include "eprecomp.cpp" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::EC2N; + +#if defined(HAVE_GCC_INIT_PRIORITY) + #define INIT_ATTRIBUTE __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 51))) + const EC2N::Point g_identity INIT_ATTRIBUTE = EC2N::Point(); +#elif defined(HAVE_MSC_INIT_PRIORITY) + #pragma warning(disable: 4075) + #pragma init_seg(".CRT$XCU") + const EC2N::Point g_identity; + #pragma warning(default: 4075) +#elif defined(HAVE_XLC_INIT_PRIORITY) + #pragma priority(290) + const EC2N::Point g_identity; +#endif + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +EC2N::EC2N(BufferedTransformation &bt) + : m_field(BERDecodeGF2NP(bt)) +{ + BERSequenceDecoder seq(bt); + m_field->BERDecodeElement(seq, m_a); + m_field->BERDecodeElement(seq, m_b); + // skip optional seed + if (!seq.EndReached()) + { + SecByteBlock seed; + unsigned int unused; + BERDecodeBitString(seq, seed, unused); + } + seq.MessageEnd(); +} + +void EC2N::DEREncode(BufferedTransformation &bt) const +{ + m_field->DEREncode(bt); + DERSequenceEncoder seq(bt); + m_field->DEREncodeElement(seq, m_a); + m_field->DEREncodeElement(seq, m_b); + seq.MessageEnd(); +} + +bool EC2N::DecodePoint(EC2N::Point &P, const byte *encodedPoint, size_t encodedPointLen) const +{ + StringStore store(encodedPoint, encodedPointLen); + return DecodePoint(P, store, encodedPointLen); +} + +bool EC2N::DecodePoint(EC2N::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const +{ + byte type; + if (encodedPointLen < 1 || !bt.Get(type)) + return false; + + switch (type) + { + case 0: + P.identity = true; + return true; + case 2: + case 3: + { + if (encodedPointLen != EncodedPointSize(true)) + return false; + + P.identity = false; + P.x.Decode(bt, m_field->MaxElementByteLength()); + + if (P.x.IsZero()) + { + P.y = m_field->SquareRoot(m_b); + return true; + } + + FieldElement z = m_field->Square(P.x); + CRYPTOPP_ASSERT(P.x == m_field->SquareRoot(z)); + P.y = m_field->Divide(m_field->Add(m_field->Multiply(z, m_field->Add(P.x, m_a)), m_b), z); + CRYPTOPP_ASSERT(P.x == m_field->Subtract(m_field->Divide(m_field->Subtract(m_field->Multiply(P.y, z), m_b), z), m_a)); + z = m_field->SolveQuadraticEquation(P.y); + CRYPTOPP_ASSERT(m_field->Add(m_field->Square(z), z) == P.y); + z.SetCoefficient(0, type & 1); + + P.y = m_field->Multiply(z, P.x); + return true; + } + case 4: + { + if (encodedPointLen != EncodedPointSize(false)) + return false; + + unsigned int len = m_field->MaxElementByteLength(); + P.identity = false; + P.x.Decode(bt, len); + P.y.Decode(bt, len); + return true; + } + default: + return false; + } +} + +void EC2N::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + if (P.identity) + NullStore().TransferTo(bt, EncodedPointSize(compressed)); + else if (compressed) + { + bt.Put((byte)(2U + (!P.x ? 0U : m_field->Divide(P.y, P.x).GetBit(0)))); + P.x.Encode(bt, m_field->MaxElementByteLength()); + } + else + { + unsigned int len = m_field->MaxElementByteLength(); + bt.Put(4); // uncompressed + P.x.Encode(bt, len); + P.y.Encode(bt, len); + } +} + +void EC2N::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const +{ + ArraySink sink(encodedPoint, EncodedPointSize(compressed)); + EncodePoint(sink, P, compressed); + CRYPTOPP_ASSERT(sink.TotalPutLength() == EncodedPointSize(compressed)); +} + +EC2N::Point EC2N::BERDecodePoint(BufferedTransformation &bt) const +{ + SecByteBlock str; + BERDecodeOctetString(bt, str); + Point P; + if (!DecodePoint(P, str, str.size())) + BERDecodeError(); + return P; +} + +void EC2N::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + SecByteBlock str(EncodedPointSize(compressed)); + EncodePoint(str, P, compressed); + DEREncodeOctetString(bt, str); +} + +bool EC2N::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const +{ + CRYPTOPP_UNUSED(rng); + bool pass = !!m_b; + pass = pass && m_a.CoefficientCount() <= m_field->MaxElementBitLength(); + pass = pass && m_b.CoefficientCount() <= m_field->MaxElementBitLength(); + + if (level >= 1) + pass = pass && m_field->GetModulus().IsIrreducible(); + + return pass; +} + +bool EC2N::VerifyPoint(const Point &P) const +{ + const FieldElement &x = P.x, &y = P.y; + return P.identity || + (x.CoefficientCount() <= m_field->MaxElementBitLength() + && y.CoefficientCount() <= m_field->MaxElementBitLength() + && !(((x+m_a)*x*x+m_b-(x+y)*y)%m_field->GetModulus())); +} + +bool EC2N::Equal(const Point &P, const Point &Q) const +{ + if (P.identity && Q.identity) + return true; + + if (P.identity && !Q.identity) + return false; + + if (!P.identity && Q.identity) + return false; + + return (m_field->Equal(P.x,Q.x) && m_field->Equal(P.y,Q.y)); +} + +const EC2N::Point& EC2N::Identity() const +{ +#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY) || defined(HAVE_XLC_INIT_PRIORITY) + return g_identity; +#elif defined(CRYPTOPP_CXX11_STATIC_INIT) + static const EC2N::Point g_identity; + return g_identity; +#else + return Singleton().Ref(); +#endif +} + +const EC2N::Point& EC2N::Inverse(const Point &P) const +{ + if (P.identity) + return P; + else + { + m_R.identity = false; + m_R.y = m_field->Add(P.x, P.y); + m_R.x = P.x; + return m_R; + } +} + +const EC2N::Point& EC2N::Add(const Point &P, const Point &Q) const +{ + if (P.identity) return Q; + if (Q.identity) return P; + if (Equal(P, Q)) return Double(P); + if (m_field->Equal(P.x, Q.x) && m_field->Equal(P.y, m_field->Add(Q.x, Q.y))) return Identity(); + + FieldElement t = m_field->Add(P.y, Q.y); + t = m_field->Divide(t, m_field->Add(P.x, Q.x)); + FieldElement x = m_field->Square(t); + m_field->Accumulate(x, t); + m_field->Accumulate(x, Q.x); + m_field->Accumulate(x, m_a); + m_R.y = m_field->Add(P.y, m_field->Multiply(t, x)); + m_field->Accumulate(x, P.x); + m_field->Accumulate(m_R.y, x); + + m_R.x.swap(x); + m_R.identity = false; + return m_R; +} + +const EC2N::Point& EC2N::Double(const Point &P) const +{ + if (P.identity) return P; + if (!m_field->IsUnit(P.x)) return Identity(); + + FieldElement t = m_field->Divide(P.y, P.x); + m_field->Accumulate(t, P.x); + m_R.y = m_field->Square(P.x); + m_R.x = m_field->Square(t); + m_field->Accumulate(m_R.x, t); + m_field->Accumulate(m_R.x, m_a); + m_field->Accumulate(m_R.y, m_field->Multiply(t, m_R.x)); + m_field->Accumulate(m_R.y, m_R.x); + + m_R.identity = false; + return m_R; +} + +// ******************************************************** + +#if 0 +EcPrecomputation& EcPrecomputation::operator=(const EcPrecomputation &rhs) +{ + m_ec = rhs.m_ec; + m_ep = rhs.m_ep; + m_ep.m_group = m_ec.get(); + return *this; +} + +void EcPrecomputation::SetCurveAndBase(const EC2N &ec, const EC2N::Point &base) +{ + m_ec.reset(new EC2N(ec)); + m_ep.SetGroupAndBase(*m_ec, base); +} + +void EcPrecomputation::Precompute(unsigned int maxExpBits, unsigned int storage) +{ + m_ep.Precompute(maxExpBits, storage); +} + +void EcPrecomputation::Load(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(seq, version, INTEGER, 1, 1); + m_ep.m_exponentBase.BERDecode(seq); + m_ep.m_windowSize = m_ep.m_exponentBase.BitCount() - 1; + m_ep.m_bases.clear(); + while (!seq.EndReached()) + m_ep.m_bases.push_back(m_ec->BERDecodePoint(seq)); + seq.MessageEnd(); +} + +void EcPrecomputation::Save(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + DEREncodeUnsigned(seq, 1); // version + m_ep.m_exponentBase.DEREncode(seq); + for (unsigned i=0; iDEREncodePoint(seq, m_ep.m_bases[i]); + seq.MessageEnd(); +} + +EC2N::Point EcPrecomputation::Exponentiate(const Integer &exponent) const +{ + return m_ep.Exponentiate(exponent); +} + +EC2N::Point EcPrecomputation::CascadeExponentiate(const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const +{ + return m_ep.CascadeExponentiate(exponent, static_cast &>(pc2).m_ep, exponent2); +} +#endif + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/ec2n.h b/external/ours/library/crypto/src/shared/original/ec2n.h new file mode 100755 index 000000000..1da178423 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/eccrypto.cpp b/external/ours/library/crypto/src/shared/original/eccrypto.cpp new file mode 100755 index 000000000..9a0914c03 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/eccrypto.cpp @@ -0,0 +1,840 @@ +// eccrypto.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4127 4189 4505) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#ifndef CRYPTOPP_IMPORTS + +#include "eccrypto.h" +#include "integer.h" +#include "nbtheory.h" +#include "filters.h" +#include "argnames.h" +#include "smartptr.h" +#include "oids.h" +#include "asn.h" +#include "hex.h" +#include "ec2n.h" +#include "misc.h" + +#include +#include + +// Squash MS LNK4221 and libtool warnings +#ifndef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +extern const char ECCRYPTO_FNAME[] = __FILE__; +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if 0 +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +static void ECDSA_TestInstantiations() +{ + ECDSA::Signer t1; + ECDSA::Verifier t2(t1); + ECNR::Signer t3; + ECNR::Verifier t4(t3); + ECIES::Encryptor t5; + ECIES::Decryptor t6; + ECDH::Domain t7; + ECMQV::Domain t8; +} +#endif +#endif + +ANONYMOUS_NAMESPACE_BEGIN +inline Integer ConvertToInteger(const PolynomialMod2 &x) +{ + unsigned int l = x.ByteCount(); + SecByteBlock temp(l); + x.Encode(temp, l); + return Integer(temp, l); +} + +inline Integer ConvertToInteger(const Integer &x) +{ + return x; +} + +inline bool CheckMOVCondition(const Integer &q, const Integer &r) +{ + // see "Updated standards for validating elliptic curves", http://eprint.iacr.org/2007/343 + Integer t = 1; + unsigned int n = q.IsEven() ? 1 : q.BitCount(), m = r.BitCount(); + + for (unsigned int i=n; DiscreteLogWorkFactor(i) struct EcRecommendedParameters; + +template<> struct EcRecommendedParameters +{ + EcRecommendedParameters(const OID &oid, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h) + : oid(oid), a(a), b(b), g(g), n(n), h(h), t0(0), t1(0), t2(t2), t3(t3), t4(t4) {} + EcRecommendedParameters(const OID &oid, unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h) + : oid(oid), a(a), b(b), g(g), n(n), h(h), t0(t0), t1(t1), t2(t2), t3(t3), t4(t4) {} + EC2N *NewEC() const + { + StringSource ssA(a, true, new HexDecoder); + StringSource ssB(b, true, new HexDecoder); + if (t0 == 0) + { + if (t2 == 233 && t3 == 74 && t4 == 0) + return new EC2N(GF2NT233(233, 74, 0), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); + else + return new EC2N(GF2NT(t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); + } + else + return new EC2N(GF2NPP(t0, t1, t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); + }; + + OID oid; + const char *a, *b, *g, *n; + unsigned int h, t0, t1, t2, t3, t4; +}; + +template<> struct EcRecommendedParameters +{ + EcRecommendedParameters(const OID &oid, const char *p, const char *a, const char *b, const char *g, const char *n, unsigned int h) + : oid(oid), p(p), a(a), b(b), g(g), n(n), h(h) {} + ECP *NewEC() const + { + StringSource ssP(p, true, new HexDecoder); + StringSource ssA(a, true, new HexDecoder); + StringSource ssB(b, true, new HexDecoder); + return new ECP(Integer(ssP, (size_t)ssP.MaxRetrievable()), ECP::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), ECP::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); + }; + + OID oid; + const char *p, *a, *b, *g, *n; + unsigned int h; +}; + +struct OIDLessThan +{ + template + inline bool operator()(const EcRecommendedParameters& a, const OID& b) {return a.oid < b;} + template + inline bool operator()(const OID& a, const EcRecommendedParameters& b) {return a < b.oid;} + template + inline bool operator()(const EcRecommendedParameters& a, const EcRecommendedParameters& b) {return a.oid < b.oid;} +}; + +static void GetRecommendedParameters(const EcRecommendedParameters *&begin, const EcRecommendedParameters *&end) +{ + // this array must be sorted by OID + static const EcRecommendedParameters rec[] = { + EcRecommendedParameters(ASN1::sect163k1(), + 163, 7, 6, 3, 0, + "000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000001", + "0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9", + "04000000000000000000020108A2E0CC0D99F8A5EF", + 2), + EcRecommendedParameters(ASN1::sect163r1(), + 163, 7, 6, 3, 0, + "07B6882CAAEFA84F9554FF8428BD88E246D2782AE2", + "0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9", + "040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883", + "03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", + 2), + EcRecommendedParameters(ASN1::sect239k1(), + 239, 158, 0, + "000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000001", + "0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA", + "2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", + 4), + EcRecommendedParameters(ASN1::sect113r1(), + 113, 9, 0, + "003088250CA6E7C7FE649CE85820F7", + "00E8BEE4D3E2260744188BE0E9C723", + "04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886", + "0100000000000000D9CCEC8A39E56F", + 2), + EcRecommendedParameters(ASN1::sect113r2(), + 113, 9, 0, + "00689918DBEC7E5A0DD6DFC0AA55C7", + "0095E9A9EC9B297BD4BF36E059184F", + "0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D", + "010000000000000108789B2496AF93", + 2), + EcRecommendedParameters(ASN1::sect163r2(), + 163, 7, 6, 3, 0, + "000000000000000000000000000000000000000001", + "020A601907B8C953CA1481EB10512F78744A3205FD", + "0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", + "040000000000000000000292FE77E70C12A4234C33", + 2), + EcRecommendedParameters(ASN1::sect283k1(), + 283, 12, 7, 5, 0, + "000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000001", + "040503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC245849283601CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", + 4), + EcRecommendedParameters(ASN1::sect283r1(), + 283, 12, 7, 5, 0, + "000000000000000000000000000000000000000000000000000000000000000000000001", + "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", + "0405F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B1205303676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", + "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", + 2), + EcRecommendedParameters(ASN1::sect131r1(), + 131, 8, 3, 2, 0, + "07A11B09A76B562144418FF3FF8C2570B8", + "0217C05610884B63B9C6C7291678F9D341", + "040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150", + "0400000000000000023123953A9464B54D", + 2), + EcRecommendedParameters(ASN1::sect131r2(), + 131, 8, 3, 2, 0, + "03E5A88919D7CAFCBF415F07C2176573B2", + "04B8266A46C55657AC734CE38F018F2192", + "040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F", + "0400000000000000016954A233049BA98F", + 2), + EcRecommendedParameters(ASN1::sect193r1(), + 193, 15, 0, + "0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01", + "00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814", + "0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05", + "01000000000000000000000000C7F34A778F443ACC920EBA49", + 2), + EcRecommendedParameters(ASN1::sect193r2(), + 193, 15, 0, + "0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B", + "00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE", + "0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C", + "010000000000000000000000015AAB561B005413CCD4EE99D5", + 2), + EcRecommendedParameters(ASN1::sect233k1(), + 233, 74, 0, + "000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000001", + "04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", + "8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", + 4), + EcRecommendedParameters(ASN1::sect233r1(), + 233, 74, 0, + "000000000000000000000000000000000000000000000000000000000001", + "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", + "0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", + "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", + 2), + EcRecommendedParameters(ASN1::sect409k1(), + 409, 87, 0, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "040060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE902374601E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", + 4), + EcRecommendedParameters(ASN1::sect409r1(), + 409, 87, 0, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", + "04015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A70061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", + "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", + 2), + EcRecommendedParameters(ASN1::sect571k1(), + 571, 10, 5, 2, 0, + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "04026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C89720349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", + "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", + 4), + EcRecommendedParameters(ASN1::sect571r1(), + 571, 10, 5, 2, 0, + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", + "040303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", + "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", + 2), + }; + begin = rec; + end = rec + sizeof(rec)/sizeof(rec[0]); +} + +// See https://www.cryptopp.com/wiki/SM2 for details on sm2p256v1 and sm2encrypt_recommendedParameters +static void GetRecommendedParameters(const EcRecommendedParameters *&begin, const EcRecommendedParameters *&end) +{ + // this array must be sorted by OID + static const EcRecommendedParameters rec[] = { + EcRecommendedParameters(ASN1::sm2p256v1(), + "FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF", + "FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC", + "28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93", + "04" "32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7" + "BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0", + "FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123", + 1), + EcRecommendedParameters(ASN1::sm2encrypt_recommendedParameters(), + "FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF", + "FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC", + "28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93", + "04" "32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7" + "BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0", + "FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123", + 1), + EcRecommendedParameters(ASN1::secp192r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", + "04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811", + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", + 1), + EcRecommendedParameters(ASN1::secp256r1(), + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + 1), + EcRecommendedParameters(ASN1::brainpoolP160r1(), + "E95E4A5F737059DC60DFC7AD95B3D8139515620F", + "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", + "1E589A8595423412134FAA2DBDEC95C8D8675E58", + "04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321", + "E95E4A5F737059DC60DF5991D45029409E60FC09", + 1), + EcRecommendedParameters(ASN1::brainpoolP192r1(), + "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", + "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", + "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", + "04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", + "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", + 1), + EcRecommendedParameters(ASN1::brainpoolP224r1(), + "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", + "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", + "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", + "040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", + "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", + 1), + EcRecommendedParameters(ASN1::brainpoolP256r1(), + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", + "048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + 1), + EcRecommendedParameters(ASN1::brainpoolP320r1(), + "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", + "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", + "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", + "0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", + "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", + 1), + EcRecommendedParameters(ASN1::brainpoolP384r1(), + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", + "041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + 1), + EcRecommendedParameters(ASN1::brainpoolP512r1(), + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", + "0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + 1), + EcRecommendedParameters(ASN1::secp112r1(), + "DB7C2ABF62E35E668076BEAD208B", + "DB7C2ABF62E35E668076BEAD2088", + "659EF8BA043916EEDE8911702B22", + "0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500", + "DB7C2ABF62E35E7628DFAC6561C5", + 1), + EcRecommendedParameters(ASN1::secp112r2(), + "DB7C2ABF62E35E668076BEAD208B", + "6127C24C05F38A0AAAF65C0EF02C", + "51DEF1815DB5ED74FCC34C85D709", + "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97", + "36DF0AAFD8B8D7597CA10520D04B", + 4), + EcRecommendedParameters(ASN1::secp160r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", + "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", + "044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32", + "0100000000000000000001F4C8F927AED3CA752257", + 1), + EcRecommendedParameters(ASN1::secp160k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + "0000000000000000000000000000000000000000", + "0000000000000000000000000000000000000007", + "043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE", + "0100000000000000000001B8FA16DFAB9ACA16B6B3", + 1), + EcRecommendedParameters(ASN1::secp256k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000007", + "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + 1), + EcRecommendedParameters(ASN1::secp128r1(), + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", + "E87579C11079F43DD824993C2CEE5ED3", + "04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83", + "FFFFFFFE0000000075A30D1B9038A115", + 1), + EcRecommendedParameters(ASN1::secp128r2(), + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + "D6031998D1B3BBFEBF59CC9BBFF9AEE1", + "5EEEFCA380D02919DC2C6558BB6D8A5D", + "047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44", + "3FFFFFFF7FFFFFFFBE0024720613B5A3", + 4), + EcRecommendedParameters(ASN1::secp160r2(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", + "B4E134D3FB59EB8BAB57274904664D5AF50388BA", + "0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", + "0100000000000000000000351EE786A818F3A1A16B", + 1), + EcRecommendedParameters(ASN1::secp192k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", + "000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000003", + "04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", + 1), + EcRecommendedParameters(ASN1::secp224k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", + "00000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000005", + "04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", + "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", + 1), + EcRecommendedParameters(ASN1::secp224r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", + "04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + 1), + EcRecommendedParameters(ASN1::secp384r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + "04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + 1), + EcRecommendedParameters(ASN1::secp521r1(), + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + 1), + }; + begin = rec; + end = rec + sizeof(rec)/sizeof(rec[0]); +} + +template OID DL_GroupParameters_EC::GetNextRecommendedParametersOID(const OID &oid) +{ + const EcRecommendedParameters *begin, *end; + GetRecommendedParameters(begin, end); + const EcRecommendedParameters *it = std::upper_bound(begin, end, oid, OIDLessThan()); + return (it == end ? OID() : it->oid); +} + +template void DL_GroupParameters_EC::Initialize(const OID &oid) +{ + const EcRecommendedParameters *begin, *end; + GetRecommendedParameters(begin, end); + const EcRecommendedParameters *it = std::lower_bound(begin, end, oid, OIDLessThan()); + if (it == end || it->oid != oid) + throw UnknownOID(); + + const EcRecommendedParameters ¶m = *it; + m_oid = oid; + member_ptr ec(param.NewEC()); + this->m_groupPrecomputation.SetCurve(*ec); + + StringSource ssG(param.g, true, new HexDecoder); + Element G; + bool result = GetCurve().DecodePoint(G, ssG, (size_t)ssG.MaxRetrievable()); + this->SetSubgroupGenerator(G); + + // TODO: this fails in practice. Should it throw? + CRYPTOPP_UNUSED(result); CRYPTOPP_ASSERT(result); + + StringSource ssN(param.n, true, new HexDecoder); + m_n.Decode(ssN, (size_t)ssN.MaxRetrievable()); + m_k = param.h; +} + +template +bool DL_GroupParameters_EC::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (strcmp(name, Name::GroupOID()) == 0) + { + if (m_oid.Empty()) + return false; + + this->ThrowIfTypeMismatch(name, typeid(OID), valueType); + *reinterpret_cast(pValue) = m_oid; + return true; + } + else + return GetValueHelper >(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Curve); +} + +template +void DL_GroupParameters_EC::AssignFrom(const NameValuePairs &source) +{ + OID oid; + if (source.GetValue(Name::GroupOID(), oid)) + Initialize(oid); + else + { + EllipticCurve ec; + Point G; + Integer n; + + source.GetRequiredParameter("DL_GroupParameters_EC", Name::Curve(), ec); + source.GetRequiredParameter("DL_GroupParameters_EC", Name::SubgroupGenerator(), G); + source.GetRequiredParameter("DL_GroupParameters_EC", Name::SubgroupOrder(), n); + Integer k = source.GetValueWithDefault(Name::Cofactor(), Integer::Zero()); + + Initialize(ec, G, n, k); + } +} + +template +void DL_GroupParameters_EC::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + try + { + CRYPTOPP_UNUSED(rng); + AssignFrom(alg); + } + catch (InvalidArgument &) + { + throw NotImplemented("DL_GroupParameters_EC: curve generation is not implemented yet"); + } +} + +template +void DL_GroupParameters_EC::BERDecode(BufferedTransformation &bt) +{ + byte b; + if (!bt.Peek(b)) + BERDecodeError(); + if (b == OBJECT_IDENTIFIER) + Initialize(OID(bt)); + else + { + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(seq, version, INTEGER, 1, 1); // check version + EllipticCurve ec(seq); + Point G = ec.BERDecodePoint(seq); + Integer n(seq); + Integer k; + bool cofactorPresent = !seq.EndReached(); + if (cofactorPresent) + k.BERDecode(seq); + else + k = Integer::Zero(); + seq.MessageEnd(); + + Initialize(ec, G, n, k); + } +} + +template +void DL_GroupParameters_EC::DEREncode(BufferedTransformation &bt) const +{ + if (m_encodeAsOID && !m_oid.Empty()) + m_oid.DEREncode(bt); + else + { + DERSequenceEncoder seq(bt); + DEREncodeUnsigned(seq, 1); // version + GetCurve().DEREncode(seq); + GetCurve().DEREncodePoint(seq, this->GetSubgroupGenerator(), m_compress); + m_n.DEREncode(seq); + if (m_k.NotZero()) + m_k.DEREncode(seq); + seq.MessageEnd(); + } +} + +template +Integer DL_GroupParameters_EC::GetCofactor() const +{ + if (!m_k) + { + Integer q = GetCurve().FieldSize(); + Integer qSqrt = q.SquareRoot(); + m_k = (q+2*qSqrt+1)/m_n; + } + + return m_k; +} + +template +Integer DL_GroupParameters_EC::ConvertElementToInteger(const Element &element) const +{ + return ConvertToInteger(element.x); +} + +template +bool DL_GroupParameters_EC::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = GetCurve().ValidateParameters(rng, level); + CRYPTOPP_ASSERT(pass); + + Integer q = GetCurve().FieldSize(); + pass = pass && m_n!=q; + CRYPTOPP_ASSERT(pass); + + if (level >= 2) + { + Integer qSqrt = q.SquareRoot(); + pass = pass && m_n>4*qSqrt; + CRYPTOPP_ASSERT(pass); + pass = pass && VerifyPrime(rng, m_n, level-2); + CRYPTOPP_ASSERT(pass); + pass = pass && (m_k.IsZero() || m_k == (q+2*qSqrt+1)/m_n); + CRYPTOPP_ASSERT(pass); + pass = pass && CheckMOVCondition(q, m_n); + CRYPTOPP_ASSERT(pass); + } + + return pass; +} + +template +bool DL_GroupParameters_EC::ValidateElement(unsigned int level, const Element &g, const DL_FixedBasePrecomputation *gpc) const +{ + bool pass = !IsIdentity(g); + CRYPTOPP_ASSERT(pass); + pass = pass && GetCurve().VerifyPoint(g); + CRYPTOPP_ASSERT(pass); + + if (level >= 1) + { + if (gpc) + { + pass = pass && gpc->Exponentiate(this->GetGroupPrecomputation(), Integer::One()) == g; + CRYPTOPP_ASSERT(pass); + } + } + if (level >= 2 && pass) + { + const Integer &q = GetSubgroupOrder(); + Element gq = gpc ? gpc->Exponentiate(this->GetGroupPrecomputation(), q) : this->ExponentiateElement(g, q); + pass = pass && IsIdentity(gq); + CRYPTOPP_ASSERT(pass); + } + return pass; +} + +template +void DL_GroupParameters_EC::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const +{ + GetCurve().SimultaneousMultiply(results, base, exponents, exponentsCount); +} + +template +typename DL_GroupParameters_EC::Element DL_GroupParameters_EC::MultiplyElements(const Element &a, const Element &b) const +{ + return GetCurve().Add(a, b); +} + +template +typename DL_GroupParameters_EC::Element DL_GroupParameters_EC::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const +{ + return GetCurve().CascadeMultiply(exponent1, element1, exponent2, element2); +} + +template +OID DL_GroupParameters_EC::GetAlgorithmID() const +{ + return ASN1::id_ecPublicKey(); +} + +std::ostream& operator<<(std::ostream& os, const DL_GroupParameters_EC::Element& obj) +{ + std::ostringstream oss; + oss << "(" << std::hex << obj.x << ", " << std::hex << obj.y << ")"; + return os << oss.str(); +} + +// ****************************************************************** + +template +void DL_PublicKey_EC::BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) +{ + CRYPTOPP_UNUSED(parametersPresent); + + typename EC::Point P; + if (!this->GetGroupParameters().GetCurve().DecodePoint(P, bt, size)) + BERDecodeError(); + this->SetPublicElement(P); +} + +template +void DL_PublicKey_EC::DEREncodePublicKey(BufferedTransformation &bt) const +{ + this->GetGroupParameters().GetCurve().EncodePoint(bt, this->GetPublicElement(), this->GetGroupParameters().GetPointCompression()); +} + +// ****************************************************************** + +template +void DL_PrivateKey_EC::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) +{ + CRYPTOPP_UNUSED(size); + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(seq, version, INTEGER, 1, 1); // check version + + BERGeneralDecoder dec(seq, OCTET_STRING); + if (!dec.IsDefiniteLength()) + BERDecodeError(); + Integer x; + x.Decode(dec, (size_t)dec.RemainingLength()); + dec.MessageEnd(); + if (!parametersPresent && seq.PeekByte() != (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) + BERDecodeError(); + if (!seq.EndReached() && seq.PeekByte() == (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) + { + BERGeneralDecoder parameters(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 0); + this->AccessGroupParameters().BERDecode(parameters); + parameters.MessageEnd(); + } + if (!seq.EndReached()) + { + // skip over the public element + SecByteBlock subjectPublicKey; + unsigned int unusedBits; + BERGeneralDecoder publicKey(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 1); + BERDecodeBitString(publicKey, subjectPublicKey, unusedBits); + publicKey.MessageEnd(); + Element Q; + if (!(unusedBits == 0 && this->GetGroupParameters().GetCurve().DecodePoint(Q, subjectPublicKey, subjectPublicKey.size()))) + BERDecodeError(); + } + seq.MessageEnd(); + + this->SetPrivateExponent(x); +} + +template +void DL_PrivateKey_EC::DEREncodePrivateKey(BufferedTransformation &bt) const +{ + DERSequenceEncoder privateKey(bt); + DEREncodeUnsigned(privateKey, 1); // version + // SEC 1 ver 1.0 says privateKey (m_d) has the same length as order of the curve + // this will be changed to order of base point in a future version + this->GetPrivateExponent().DEREncodeAsOctetString(privateKey, this->GetGroupParameters().GetSubgroupOrder().ByteCount()); + privateKey.MessageEnd(); +} + +// ****************************************************************** + +template +void DL_PublicKey_ECGDSA::BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) +{ + CRYPTOPP_UNUSED(parametersPresent); + + typename EC::Point P; + if (!this->GetGroupParameters().GetCurve().DecodePoint(P, bt, size)) + BERDecodeError(); + this->SetPublicElement(P); +} + +template +void DL_PublicKey_ECGDSA::DEREncodePublicKey(BufferedTransformation &bt) const +{ + this->GetGroupParameters().GetCurve().EncodePoint(bt, this->GetPublicElement(), this->GetGroupParameters().GetPointCompression()); +} + +// ****************************************************************** + +template +void DL_PrivateKey_ECGDSA::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) +{ + CRYPTOPP_UNUSED(size); + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(seq, version, INTEGER, 1, 1); // check version + + BERGeneralDecoder dec(seq, OCTET_STRING); + if (!dec.IsDefiniteLength()) + BERDecodeError(); + Integer x; + x.Decode(dec, (size_t)dec.RemainingLength()); + dec.MessageEnd(); + if (!parametersPresent && seq.PeekByte() != (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) + BERDecodeError(); + if (!seq.EndReached() && seq.PeekByte() == (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) + { + BERGeneralDecoder parameters(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 0); + this->AccessGroupParameters().BERDecode(parameters); + parameters.MessageEnd(); + } + if (!seq.EndReached()) + { + // skip over the public element + SecByteBlock subjectPublicKey; + unsigned int unusedBits; + BERGeneralDecoder publicKey(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 1); + BERDecodeBitString(publicKey, subjectPublicKey, unusedBits); + publicKey.MessageEnd(); + Element Q; + if (!(unusedBits == 0 && this->GetGroupParameters().GetCurve().DecodePoint(Q, subjectPublicKey, subjectPublicKey.size()))) + BERDecodeError(); + } + seq.MessageEnd(); + + this->SetPrivateExponent(x); +} + +template +void DL_PrivateKey_ECGDSA::DEREncodePrivateKey(BufferedTransformation &bt) const +{ + DERSequenceEncoder privateKey(bt); + DEREncodeUnsigned(privateKey, 1); // version + // SEC 1 ver 1.0 says privateKey (m_d) has the same length as order of the curve + // this will be changed to order of base point in a future version + this->GetPrivateExponent().DEREncodeAsOctetString(privateKey, this->GetGroupParameters().GetSubgroupOrder().ByteCount()); + privateKey.MessageEnd(); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/eccrypto.h b/external/ours/library/crypto/src/shared/original/eccrypto.h new file mode 100755 index 000000000..870628684 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 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 +/// \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 compatibile 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 drivation 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 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 ECIES_P1363. +/// If you desire an Integrated Encryption Scheme compatibile 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/external/ours/library/crypto/src/shared/original/ecp.cpp b/external/ours/library/crypto/src/shared/original/ecp.cpp new file mode 100755 index 000000000..643ba70a0 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ecp.cpp @@ -0,0 +1,506 @@ +// ecp.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "ecp.h" +#include "asn.h" +#include "integer.h" +#include "nbtheory.h" +#include "modarith.h" +#include "filters.h" +#include "algebra.cpp" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::ECP; +using CryptoPP::Integer; +using CryptoPP::ModularArithmetic; + +#if defined(HAVE_GCC_INIT_PRIORITY) + #define INIT_ATTRIBUTE __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 50))) + const ECP::Point g_identity INIT_ATTRIBUTE = ECP::Point(); +#elif defined(HAVE_MSC_INIT_PRIORITY) + #pragma warning(disable: 4075) + #pragma init_seg(".CRT$XCU") + const ECP::Point g_identity; + #pragma warning(default: 4075) +#elif defined(HAVE_XLC_INIT_PRIORITY) + #pragma priority(290) + const ECP::Point g_identity; +#endif + +inline ECP::Point ToMontgomery(const ModularArithmetic &mr, const ECP::Point &P) +{ + return P.identity ? P : ECP::Point(mr.ConvertIn(P.x), mr.ConvertIn(P.y)); +} + +inline ECP::Point FromMontgomery(const ModularArithmetic &mr, const ECP::Point &P) +{ + return P.identity ? P : ECP::Point(mr.ConvertOut(P.x), mr.ConvertOut(P.y)); +} + +inline Integer IdentityToInteger(bool val) +{ + return val ? Integer::One() : Integer::Zero(); +} + +struct ProjectivePoint +{ + ProjectivePoint() {} + ProjectivePoint(const Integer &x, const Integer &y, const Integer &z) + : x(x), y(y), z(z) {} + + Integer x, y, z; +}; + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +ECP::ECP(const ECP &ecp, bool convertToMontgomeryRepresentation) +{ + if (convertToMontgomeryRepresentation && !ecp.GetField().IsMontgomeryRepresentation()) + { + m_fieldPtr.reset(new MontgomeryRepresentation(ecp.GetField().GetModulus())); + m_a = GetField().ConvertIn(ecp.m_a); + m_b = GetField().ConvertIn(ecp.m_b); + } + else + operator=(ecp); +} + +ECP::ECP(BufferedTransformation &bt) + : m_fieldPtr(new Field(bt)) +{ + BERSequenceDecoder seq(bt); + GetField().BERDecodeElement(seq, m_a); + GetField().BERDecodeElement(seq, m_b); + // skip optional seed + if (!seq.EndReached()) + { + SecByteBlock seed; + unsigned int unused; + BERDecodeBitString(seq, seed, unused); + } + seq.MessageEnd(); +} + +void ECP::DEREncode(BufferedTransformation &bt) const +{ + GetField().DEREncode(bt); + DERSequenceEncoder seq(bt); + GetField().DEREncodeElement(seq, m_a); + GetField().DEREncodeElement(seq, m_b); + seq.MessageEnd(); +} + +bool ECP::DecodePoint(ECP::Point &P, const byte *encodedPoint, size_t encodedPointLen) const +{ + StringStore store(encodedPoint, encodedPointLen); + return DecodePoint(P, store, encodedPointLen); +} + +bool ECP::DecodePoint(ECP::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const +{ + byte type; + if (encodedPointLen < 1 || !bt.Get(type)) + return false; + + switch (type) + { + case 0: + P.identity = true; + return true; + case 2: + case 3: + { + if (encodedPointLen != EncodedPointSize(true)) + return false; + + Integer p = FieldSize(); + + P.identity = false; + P.x.Decode(bt, GetField().MaxElementByteLength()); + P.y = ((P.x*P.x+m_a)*P.x+m_b) % p; + + if (Jacobi(P.y, p) !=1) + return false; + + P.y = ModularSquareRoot(P.y, p); + + if ((type & 1) != P.y.GetBit(0)) + P.y = p-P.y; + + return true; + } + case 4: + { + if (encodedPointLen != EncodedPointSize(false)) + return false; + + unsigned int len = GetField().MaxElementByteLength(); + P.identity = false; + P.x.Decode(bt, len); + P.y.Decode(bt, len); + return true; + } + default: + return false; + } +} + +void ECP::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + if (P.identity) + NullStore().TransferTo(bt, EncodedPointSize(compressed)); + else if (compressed) + { + bt.Put((byte)(2U + P.y.GetBit(0))); + P.x.Encode(bt, GetField().MaxElementByteLength()); + } + else + { + unsigned int len = GetField().MaxElementByteLength(); + bt.Put(4U); // uncompressed + P.x.Encode(bt, len); + P.y.Encode(bt, len); + } +} + +void ECP::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const +{ + ArraySink sink(encodedPoint, EncodedPointSize(compressed)); + EncodePoint(sink, P, compressed); + CRYPTOPP_ASSERT(sink.TotalPutLength() == EncodedPointSize(compressed)); +} + +ECP::Point ECP::BERDecodePoint(BufferedTransformation &bt) const +{ + SecByteBlock str; + BERDecodeOctetString(bt, str); + Point P; + if (!DecodePoint(P, str, str.size())) + BERDecodeError(); + return P; +} + +void ECP::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + SecByteBlock str(EncodedPointSize(compressed)); + EncodePoint(str, P, compressed); + DEREncodeOctetString(bt, str); +} + +bool ECP::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const +{ + Integer p = FieldSize(); + + bool pass = p.IsOdd(); + pass = pass && !m_a.IsNegative() && m_a

= 1) + pass = pass && ((4*m_a*m_a*m_a+27*m_b*m_b)%p).IsPositive(); + + if (level >= 2) + pass = pass && VerifyPrime(rng, p); + + return pass; +} + +bool ECP::VerifyPoint(const Point &P) const +{ + const FieldElement &x = P.x, &y = P.y; + Integer p = FieldSize(); + return P.identity || + (!x.IsNegative() && x

().Ref(); +#endif +} + +const ECP::Point& ECP::Inverse(const Point &P) const +{ + if (P.identity) + return P; + else + { + m_R.identity = false; + m_R.x = P.x; + m_R.y = GetField().Inverse(P.y); + return m_R; + } +} + +const ECP::Point& ECP::Add(const Point &P, const Point &Q) const +{ + if (P.identity) return Q; + if (Q.identity) return P; + if (GetField().Equal(P.x, Q.x)) + return GetField().Equal(P.y, Q.y) ? Double(P) : Identity(); + + FieldElement t = GetField().Subtract(Q.y, P.y); + t = GetField().Divide(t, GetField().Subtract(Q.x, P.x)); + FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), Q.x); + m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); + + m_R.x.swap(x); + m_R.identity = false; + return m_R; +} + +const ECP::Point& ECP::Double(const Point &P) const +{ + if (P.identity || P.y==GetField().Identity()) return Identity(); + + FieldElement t = GetField().Square(P.x); + t = GetField().Add(GetField().Add(GetField().Double(t), t), m_a); + t = GetField().Divide(t, GetField().Double(P.y)); + FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), P.x); + m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); + + m_R.x.swap(x); + m_R.identity = false; + return m_R; +} + +template void ParallelInvert(const AbstractRing &ring, Iterator begin, Iterator end) +{ + size_t n = end-begin; + if (n == 1) + *begin = ring.MultiplicativeInverse(*begin); + else if (n > 1) + { + std::vector vec((n+1)/2); + unsigned int i; + Iterator it; + + for (i=0, it=begin; i::iterator it) : it(it) {} + Integer& operator*() {return it->z;} + int operator-(ZIterator it2) {return int(it-it2.it);} + ZIterator operator+(int i) {return ZIterator(it+i);} + ZIterator& operator+=(int i) {it+=i; return *this;} + std::vector::iterator it; +}; + +ECP::Point ECP::ScalarMultiply(const Point &P, const Integer &k) const +{ + Element result; + if (k.BitCount() <= 5) + AbstractGroup::SimultaneousMultiply(&result, P, &k, 1); + else + ECP::SimultaneousMultiply(&result, P, &k, 1); + return result; +} + +void ECP::SimultaneousMultiply(ECP::Point *results, const ECP::Point &P, const Integer *expBegin, unsigned int expCount) const +{ + if (!GetField().IsMontgomeryRepresentation()) + { + ECP ecpmr(*this, true); + const ModularArithmetic &mr = ecpmr.GetField(); + ecpmr.SimultaneousMultiply(results, ToMontgomery(mr, P), expBegin, expCount); + for (unsigned int i=0; i bases; + std::vector exponents; + exponents.reserve(expCount); + std::vector > baseIndices(expCount); + std::vector > negateBase(expCount); + std::vector > exponentWindows(expCount); + unsigned int i; + + for (i=0; iNotNegative()); + exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 5)); + exponents[i].FindNextWindow(); + } + + unsigned int expBitPosition = 0; + bool notDone = true; + + while (notDone) + { + notDone = false; + bool baseAdded = false; + for (i=0; i > finalCascade; + for (i=0; i::CascadeScalarMultiply(P, k1, Q, k2); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/ecp.h b/external/ours/library/crypto/src/shared/original/ecp.h new file mode 100755 index 000000000..1dc02ab05 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/ecpoint.h b/external/ours/library/crypto/src/shared/original/ecpoint.h new file mode 100755 index 000000000..1fe3820fb --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/elgamal.cpp b/external/ours/library/crypto/src/shared/original/elgamal.cpp new file mode 100755 index 000000000..9871c538d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/elgamal.cpp @@ -0,0 +1,22 @@ +// elgamal.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "elgamal.h" +#include "asn.h" +#include "nbtheory.h" + +// Squash MS LNK4221 and libtool warnings +extern const char ELGAMAL_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void ElGamal_TestInstantiations() +{ + ElGamalEncryptor test1(1, 1, 1); + ElGamalDecryptor test2(NullRNG(), 123); + ElGamalEncryptor test3(test2); +} +#endif + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/elgamal.h b/external/ours/library/crypto/src/shared/original/elgamal.h new file mode 100755 index 000000000..c4e1732d8 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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); + 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/external/ours/library/crypto/src/shared/original/emsa2.cpp b/external/ours/library/crypto/src/shared/original/emsa2.cpp new file mode 100755 index 000000000..dd5173dde --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/emsa2.cpp @@ -0,0 +1,44 @@ +// emsa2.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "emsa2.h" + +#ifndef CRYPTOPP_IMPORTS + +NAMESPACE_BEGIN(CryptoPP) + +// Inclusion based on DLL due to Clang, http://github.com/weidai11/cryptopp/issues/300 +#ifndef CRYPTOPP_IS_DLL +template<> const byte EMSA2HashId::id = 0x33; +template<> const byte EMSA2HashId::id = 0x38; +template<> const byte EMSA2HashId::id = 0x34; +template<> const byte EMSA2HashId::id = 0x36; +template<> const byte EMSA2HashId::id = 0x35; +#endif + +void EMSA2Pad::ComputeMessageRepresentative(RandomNumberGenerator& /*rng*/, + const byte* recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const +{ + CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(recoverableMessageLength), CRYPTOPP_UNUSED(representativeBitLength); + CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); + + if (representativeBitLength % 8 != 7) + throw PK_SignatureScheme::InvalidKeyLength("EMSA2: EMSA2 requires a key length that is a multiple of 8"); + + size_t digestSize = hash.DigestSize(); + size_t representativeByteLength = BitsToBytes(representativeBitLength); + + representative[0] = messageEmpty ? 0x4b : 0x6b; + memset(representative+1, 0xbb, representativeByteLength-digestSize-4); // pad with 0xbb + byte *afterP2 = representative+representativeByteLength-digestSize-3; + afterP2[0] = 0xba; + hash.Final(afterP2+1); + representative[representativeByteLength-2] = *hashIdentifier.first; + representative[representativeByteLength-1] = 0xcc; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/emsa2.h b/external/ours/library/crypto/src/shared/original/emsa2.h new file mode 100755 index 000000000..0db5ea341 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/eprecomp.cpp b/external/ours/library/crypto/src/shared/original/eprecomp.cpp new file mode 100755 index 000000000..751030893 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/eprecomp.cpp @@ -0,0 +1,114 @@ +// eprecomp.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "eprecomp.h" +#include "integer.h" +#include "algebra.h" +#include "asn.h" + +NAMESPACE_BEGIN(CryptoPP) + +template void DL_FixedBasePrecomputationImpl::SetBase(const DL_GroupPrecomputation &group, const Element &i_base) +{ + m_base = group.NeedConversions() ? group.ConvertIn(i_base) : i_base; + + if (m_bases.empty() || !(m_base == m_bases[0])) + { + m_bases.resize(1); + m_bases[0] = m_base; + } + + if (group.NeedConversions()) + m_base = i_base; +} + +template void DL_FixedBasePrecomputationImpl::Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage) +{ + CRYPTOPP_ASSERT(m_bases.size() > 0); + CRYPTOPP_ASSERT(storage <= maxExpBits); + + if (storage > 1) + { + m_windowSize = (maxExpBits+storage-1)/storage; + m_exponentBase = Integer::Power2(m_windowSize); + } + + m_bases.resize(storage); + for (unsigned i=1; i void DL_FixedBasePrecomputationImpl::Load(const DL_GroupPrecomputation &group, BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(seq, version, INTEGER, 1, 1); + m_exponentBase.BERDecode(seq); + m_windowSize = m_exponentBase.BitCount() - 1; + m_bases.clear(); + while (!seq.EndReached()) + m_bases.push_back(group.BERDecodeElement(seq)); + if (!m_bases.empty() && group.NeedConversions()) + m_base = group.ConvertOut(m_bases[0]); + seq.MessageEnd(); +} + +template void DL_FixedBasePrecomputationImpl::Save(const DL_GroupPrecomputation &group, BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + DEREncodeUnsigned(seq, 1); // version + m_exponentBase.DEREncode(seq); + for (unsigned i=0; i void DL_FixedBasePrecomputationImpl::PrepareCascade(const DL_GroupPrecomputation &i_group, std::vector > &eb, const Integer &exponent) const +{ + const AbstractGroup &group = i_group.GetGroup(); + + Integer r, q, e = exponent; + bool fastNegate = group.InversionIsFast() && m_windowSize > 1; + unsigned int i; + + for (i=0; i+1(group.Inverse(m_bases[i]), m_exponentBase - r)); + } + else + eb.push_back(BaseAndExponent(m_bases[i], r)); + } + eb.push_back(BaseAndExponent(m_bases[i], e)); +} + +template T DL_FixedBasePrecomputationImpl::Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const +{ + std::vector > eb; // array of segments of the exponent and precalculated bases + eb.reserve(m_bases.size()); + PrepareCascade(group, eb, exponent); + return group.ConvertOut(GeneralCascadeMultiplication(group.GetGroup(), eb.begin(), eb.end())); +} + +template T + DL_FixedBasePrecomputationImpl::CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, + const DL_FixedBasePrecomputation &i_pc2, const Integer &exponent2) const +{ + std::vector > eb; // array of segments of the exponent and precalculated bases + const DL_FixedBasePrecomputationImpl &pc2 = static_cast &>(i_pc2); + eb.reserve(m_bases.size() + pc2.m_bases.size()); + PrepareCascade(group, eb, exponent); + pc2.PrepareCascade(group, eb, exponent2); + return group.ConvertOut(GeneralCascadeMultiplication(group.GetGroup(), eb.begin(), eb.end())); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/eprecomp.h b/external/ours/library/crypto/src/shared/original/eprecomp.h new file mode 100755 index 000000000..737a15694 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/esign.cpp b/external/ours/library/crypto/src/shared/original/esign.cpp new file mode 100755 index 000000000..7c69a6841 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/esign.cpp @@ -0,0 +1,233 @@ +// esign.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +// TODO: fix the C4589 warnings +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4589) +#endif + +#include "esign.h" +#include "modarith.h" +#include "integer.h" +#include "nbtheory.h" +#include "algparam.h" +#include "sha.h" +#include "asn.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void ESIGN_TestInstantiations() +{ + ESIGN::Verifier x1(1, 1); + ESIGN::Signer x2(NullRNG(), 1); + ESIGN::Verifier x3(x2); + ESIGN::Verifier x4(x2.GetKey()); + ESIGN::Verifier x5(x3); + ESIGN::Signer x6 = x2; + + x6 = x2; + x3 = ESIGN::Verifier(x2); + x4 = x2.GetKey(); +} +#endif + +void ESIGNFunction::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + m_n.BERDecode(seq); + m_e.BERDecode(seq); + seq.MessageEnd(); +} + +void ESIGNFunction::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + m_n.DEREncode(seq); + m_e.DEREncode(seq); + seq.MessageEnd(); +} + +Integer ESIGNFunction::ApplyFunction(const Integer &x) const +{ + DoQuickSanityCheck(); + return STDMIN(a_exp_b_mod_c(x, m_e, m_n) >> (2*GetK()+2), MaxImage()); +} + +bool ESIGNFunction::Validate(RandomNumberGenerator& rng, unsigned int level) const +{ + CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(level); + bool pass = true; + pass = pass && m_n > Integer::One() && m_n.IsOdd(); + CRYPTOPP_ASSERT(pass); + pass = pass && m_e >= 8 && m_e < m_n; + CRYPTOPP_ASSERT(pass); + return pass; +} + +bool ESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent) + ; +} + +void ESIGNFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent) + ; +} + +// ***************************************************************************** + +void InvertibleESIGNFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶m) +{ + int modulusSize = 1023*2; + param.GetIntValue("ModulusSize", modulusSize) || param.GetIntValue("KeySize", modulusSize); + + if (modulusSize < 24) + throw InvalidArgument("InvertibleESIGNFunction: specified modulus size is too small"); + + if (modulusSize % 3 != 0) + throw InvalidArgument("InvertibleESIGNFunction: modulus size must be divisible by 3"); + + m_e = param.GetValueWithDefault("PublicExponent", Integer(32)); + + if (m_e < 8) + throw InvalidArgument("InvertibleESIGNFunction: public exponents less than 8 may not be secure"); + + // VC70 workaround: putting these after primeParam causes overlapped stack allocation + ConstByteArrayParameter seedParam; + SecByteBlock seed; + + const Integer minP = Integer(204) << (modulusSize/3-8); + const Integer maxP = Integer::Power2(modulusSize/3)-1; + AlgorithmParameters primeParam = MakeParameters("Min", minP)("Max", maxP)("RandomNumberType", Integer::PRIME); + + if (param.GetValue("Seed", seedParam)) + { + seed.resize(seedParam.size() + 4); + memcpy(seed + 4, seedParam.begin(), seedParam.size()); + + PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)0); + m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed)))); + PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)1); + m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed)))); + } + else + { + m_p.GenerateRandom(rng, primeParam); + m_q.GenerateRandom(rng, primeParam); + } + + m_n = m_p * m_p * m_q; + + CRYPTOPP_ASSERT(m_n.BitCount() == (unsigned int)modulusSize); +} + +void InvertibleESIGNFunction::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder privateKey(bt); + m_n.BERDecode(privateKey); + m_e.BERDecode(privateKey); + m_p.BERDecode(privateKey); + m_q.BERDecode(privateKey); + privateKey.MessageEnd(); +} + +void InvertibleESIGNFunction::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder privateKey(bt); + m_n.DEREncode(privateKey); + m_e.DEREncode(privateKey); + m_p.DEREncode(privateKey); + m_q.DEREncode(privateKey); + privateKey.MessageEnd(); +} + +Integer InvertibleESIGNFunction::CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const +{ + DoQuickSanityCheck(); + + Integer pq = m_p * m_q; + Integer p2 = m_p * m_p; + Integer r, z, re, a, w0, w1; + + do + { + r.Randomize(rng, Integer::Zero(), pq); + z = x << (2*GetK()+2); + re = a_exp_b_mod_c(r, m_e, m_n); + a = (z - re) % m_n; + Integer::Divide(w1, w0, a, pq); + if (w1.NotZero()) + { + ++w0; + w1 = pq - w1; + } + } + while ((w1 >> (2*GetK()+1)).IsPositive()); + + ModularArithmetic modp(m_p); + Integer t = modp.Divide(w0 * r % m_p, m_e * re % m_p); + Integer s = r + t*pq; + CRYPTOPP_ASSERT(s < m_n); +#if 0 + using namespace std; + cout << "f = " << x << endl; + cout << "r = " << r << endl; + cout << "z = " << z << endl; + cout << "a = " << a << endl; + cout << "w0 = " << w0 << endl; + cout << "w1 = " << w1 << endl; + cout << "t = " << t << endl; + cout << "s = " << s << endl; +#endif + return s; +} + +bool InvertibleESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = ESIGNFunction::Validate(rng, level); + CRYPTOPP_ASSERT(pass); + pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_p.BitCount() == m_q.BitCount(); + CRYPTOPP_ASSERT(pass); + if (level >= 1) + { + pass = pass && m_p * m_p * m_q == m_n; + CRYPTOPP_ASSERT(pass); + } + if (level >= 2) + { + pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2); + CRYPTOPP_ASSERT(pass); + } + return pass; +} + +bool InvertibleESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_GET_FUNCTION_ENTRY(Prime2) + ; +} + +void InvertibleESIGNFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime2) + ; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/esign.h b/external/ours/library/crypto/src/shared/original/esign.h new file mode 100755 index 000000000..274c18106 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/factory.h b/external/ours/library/crypto/src/shared/original/factory.h new file mode 100755 index 000000000..d3d36e3c3 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/fhmqv.h b/external/ours/library/crypto/src/shared/original/fhmqv.h new file mode 100755 index 000000000..e247e1f20 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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); + 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/external/ours/library/crypto/src/shared/original/files.cpp b/external/ours/library/crypto/src/shared/original/files.cpp new file mode 100755 index 000000000..16b66480e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/files.cpp @@ -0,0 +1,300 @@ +// files.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "files.h" + +#include +#include +#include + +ANONYMOUS_NAMESPACE_BEGIN + +/// \brief Disable badbit, failbit and eof exceptions +/// \sa https://github.com/weidai11/cryptopp/pull/968 and +/// https://www.cplusplus.com/reference/ios/ios/exceptions +class IosExceptionMask +{ +public: + IosExceptionMask(std::istream& stream) : m_stream(stream) { + m_mask = m_stream.exceptions(); + m_stream.exceptions(static_cast(0)); + } + + IosExceptionMask(std::istream& stream, std::ios::iostate newMask) : m_stream(stream) { + m_mask = m_stream.exceptions(); + m_stream.exceptions(newMask); + } + + ~IosExceptionMask() { + m_stream.exceptions(m_mask); + } + +private: + std::istream& m_stream; + std::ios::iostate m_mask; +}; + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void Files_TestInstantiations() +{ + FileStore f0; + FileSource f1; + FileSink f2; +} +#endif + +void FileStore::StoreInitialize(const NameValuePairs ¶meters) +{ + m_waiting = false; + m_stream = NULLPTR; + m_file.release(); + + const char *fileName = NULLPTR; +#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400 + const wchar_t *fileNameWide = NULLPTR; + if (!parameters.GetValue(Name::InputFileNameWide(), fileNameWide)) +#endif + if (!parameters.GetValue(Name::InputFileName(), fileName)) + { + parameters.GetValue(Name::InputStreamPointer(), m_stream); + return; + } + + std::ios::openmode binary = parameters.GetValueWithDefault(Name::InputBinaryMode(), true) ? std::ios::binary : std::ios::openmode(0); + m_file.reset(new std::ifstream); +#ifdef CRYPTOPP_UNIX_AVAILABLE + std::string narrowed; + if (fileNameWide) + fileName = (narrowed = StringNarrow(fileNameWide)).c_str(); +#endif +#if _MSC_VER >= 1400 + if (fileNameWide) + { + m_file->open(fileNameWide, std::ios::in | binary); + if (!*m_file) + throw OpenErr(StringNarrow(fileNameWide, false)); + } +#endif + if (fileName) + { + m_file->open(fileName, std::ios::in | binary); + if (!*m_file) + throw OpenErr(fileName); + } + m_stream = m_file.get(); +} + +lword FileStore::MaxRetrievable() const +{ + if (!m_stream) + return 0; + + // Disable badbit, failbit and eof exceptions + IosExceptionMask guard(*m_stream); + + // Clear error bits due to seekg(). Also see + // https://github.com/weidai11/cryptopp/pull/968 + std::streampos current = m_stream->tellg(); + std::streampos end = m_stream->seekg(0, std::ios::end).tellg(); + m_stream->clear(); + m_stream->seekg(current); + m_stream->clear(); + + // Return max for a non-seekable stream + // https://www.cplusplus.com/reference/istream/istream/tellg + if (end == static_cast(-1)) + return LWORD_MAX; + + return end-current; +} + +size_t FileStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + if (!m_stream) + { + transferBytes = 0; + return 0; + } + + lword size=transferBytes; + transferBytes = 0; + + if (m_waiting) + goto output; + + size_t spaceSize, blockedBytes; + while (size && m_stream->good()) + { + spaceSize = 1024; + m_space = HelpCreatePutSpace(target, channel, 1, UnsignedMin(size_t(SIZE_MAX), size), spaceSize); + m_stream->read((char *)m_space, (std::streamsize)STDMIN(size, (lword)spaceSize)); + m_len = (size_t)m_stream->gcount(); + +output: + blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking); + m_waiting = blockedBytes > 0; + if (m_waiting) + return blockedBytes; + size -= m_len; + transferBytes += m_len; + } + + if (!m_stream->good() && !m_stream->eof()) + throw ReadErr(); + + return 0; +} + +size_t FileStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + if (!m_stream) + return 0; + + if (begin == 0 && end == 1) + { + int result = m_stream->peek(); + if (result == std::char_traits::eof()) + return 0; + else + { + size_t blockedBytes = target.ChannelPut(channel, byte(result), blocking); + begin += 1-blockedBytes; + return blockedBytes; + } + } + + // TODO: figure out what happens on cin + std::streampos current = m_stream->tellg(); + std::streampos endPosition = m_stream->seekg(0, std::ios::end).tellg(); + std::streampos newPosition = current + static_cast(begin); + + if (newPosition >= endPosition) + { + m_stream->seekg(current); + return 0; // don't try to seek beyond the end of file + } + m_stream->seekg(newPosition); + try + { + CRYPTOPP_ASSERT(!m_waiting); + lword copyMax = end-begin; + size_t blockedBytes = const_cast(this)->TransferTo2(target, copyMax, channel, blocking); + begin += copyMax; + if (blockedBytes) + { + const_cast(this)->m_waiting = false; + return blockedBytes; + } + } + catch(...) + { + m_stream->clear(); + m_stream->seekg(current); + throw; + } + m_stream->clear(); + m_stream->seekg(current); + + return 0; +} + +lword FileStore::Skip(lword skipMax) +{ + if (!m_stream) + return 0; + + lword oldPos = m_stream->tellg(); + std::istream::off_type offset; + if (!SafeConvert(skipMax, offset)) + throw InvalidArgument("FileStore: maximum seek offset exceeded"); + m_stream->seekg(offset, std::ios::cur); + return (lword)m_stream->tellg() - oldPos; +} + +void FileSink::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_stream = NULLPTR; + m_file.release(); + + const char *fileName = NULLPTR; +#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400 + const wchar_t *fileNameWide = NULLPTR; + if (!parameters.GetValue(Name::OutputFileNameWide(), fileNameWide)) +#endif + if (!parameters.GetValue(Name::OutputFileName(), fileName)) + { + parameters.GetValue(Name::OutputStreamPointer(), m_stream); + return; + } + + std::ios::openmode binary = parameters.GetValueWithDefault(Name::OutputBinaryMode(), true) ? std::ios::binary : std::ios::openmode(0); + m_file.reset(new std::ofstream); +#ifdef CRYPTOPP_UNIX_AVAILABLE + std::string narrowed; + if (fileNameWide) + fileName = (narrowed = StringNarrow(fileNameWide)).c_str(); +#elif (CRYPTOPP_MSC_VERSION >= 1400) + if (fileNameWide) + { + m_file->open(fileNameWide, std::ios::out | std::ios::trunc | binary); + if (!*m_file) + throw OpenErr(StringNarrow(fileNameWide, false)); + } +#endif + if (fileName) + { + m_file->open(fileName, std::ios::out | std::ios::trunc | binary); + if (!*m_file) + throw OpenErr(fileName); + } + m_stream = m_file.get(); +} + +bool FileSink::IsolatedFlush(bool hardFlush, bool blocking) +{ + CRYPTOPP_UNUSED(hardFlush), CRYPTOPP_UNUSED(blocking); + if (!m_stream) + throw Err("FileSink: output stream not opened"); + + m_stream->flush(); + if (!m_stream->good()) + throw WriteErr(); + + return false; +} + +size_t FileSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) +{ + CRYPTOPP_UNUSED(blocking); + if (!m_stream) + throw Err("FileSink: output stream not opened"); + + while (length > 0) + { + std::streamsize size; + if (!SafeConvert(length, size)) + size = ((std::numeric_limits::max)()); + m_stream->write((const char *)inString, size); + inString += size; + length -= (size_t)size; + } + + if (messageEnd) + m_stream->flush(); + + if (!m_stream->good()) + throw WriteErr(); + + return 0; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/files.h b/external/ours/library/crypto/src/shared/original/files.h new file mode 100755 index 000000000..8ff5dc85c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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) || _MSC_VER >= 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) || _MSC_VER >= 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) || _MSC_VER >= 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/external/ours/library/crypto/src/shared/original/filters.cpp b/external/ours/library/crypto/src/shared/original/filters.cpp index 852a7b7fa..228a0f778 100755 --- a/external/ours/library/crypto/src/shared/original/filters.cpp +++ b/external/ours/library/crypto/src/shared/original/filters.cpp @@ -1,424 +1,1270 @@ -// filters.cpp - written and placed in the public domain by Wei Dai - -#include "FirstCrypto.h" -#include "filters.h" -#include "mqueue.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -BitBucket g_bitBucket; - -Filter::Filter(BufferedTransformation *outQ) - : m_outQueue(outQ ? outQ : new MessageQueue) -{ -} - -void Filter::Detach(BufferedTransformation *newOut) -{ - m_outQueue.reset(newOut ? newOut : new MessageQueue); - NotifyAttachmentChange(); -} - -void Filter::Insert(Filter *filter) -{ - filter->m_outQueue.reset(m_outQueue.release()); - m_outQueue.reset(filter); - NotifyAttachmentChange(); -} - -// ************************************************************* - -FilterWithBufferedInput::BlockQueue::BlockQueue(unsigned int blockSize, unsigned int maxBlocks) - : m_buffer(blockSize * maxBlocks) -{ - ResetQueue(blockSize, maxBlocks); -} - -void FilterWithBufferedInput::BlockQueue::ResetQueue(unsigned int blockSize, unsigned int maxBlocks) -{ - m_buffer.Resize(blockSize * maxBlocks); - m_blockSize = blockSize; - m_maxBlocks = maxBlocks; - m_size = 0; - m_begin = m_buffer; -} - -const byte *FilterWithBufferedInput::BlockQueue::GetBlock() -{ - if (m_size >= m_blockSize) - { - const byte *ptr = m_begin; - if ((m_begin+=m_blockSize) == m_buffer.End()) - m_begin = m_buffer; - m_size -= m_blockSize; - return ptr; - } - else - return nullptr; -} - -const byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(unsigned int &numberOfBlocks) -{ - numberOfBlocks = STDMIN(numberOfBlocks, STDMIN((unsigned int)(m_buffer.End()-m_begin), m_size)/m_blockSize); - const byte *ptr = m_begin; - if ((m_begin+=m_blockSize*numberOfBlocks) == m_buffer.End()) - m_begin = m_buffer; - m_size -= m_blockSize*numberOfBlocks; - return ptr; -} - -unsigned int FilterWithBufferedInput::BlockQueue::GetAll(byte *outString) -{ - unsigned int size = m_size; - unsigned int numberOfBlocks = m_maxBlocks; - const byte *ptr = GetContigousBlocks(numberOfBlocks); - memcpy(outString, ptr, numberOfBlocks*m_blockSize); - memcpy(outString+numberOfBlocks*m_blockSize, m_begin, m_size); - m_size = 0; - return size; -} - -void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, unsigned int length) -{ - assert(m_size + length <= m_buffer.size); - byte *end = (m_size < (unsigned)(m_buffer+m_buffer.size-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size; - unsigned int len = STDMIN(length, (unsigned int)(m_buffer+m_buffer.size-end)); - memcpy(end, inString, len); - if (len < length) - memcpy(m_buffer, inString+len, length-len); - m_size += length; -} - -FilterWithBufferedInput::FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *outQ) - : Filter(outQ), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize) - , m_firstInputDone(false) - , m_queue(1, m_firstSize) -{ -} - -void FilterWithBufferedInput::Put(byte inByte) -{ - Put(&inByte, 1); -} - -void FilterWithBufferedInput::Put(const byte *inString, unsigned int length) -{ - if (length == 0) - return; - - unsigned int newLength = m_queue.CurrentSize() + length; - - if (!m_firstInputDone && newLength >= m_firstSize) - { - unsigned int len = m_firstSize - m_queue.CurrentSize(); - m_queue.Put(inString, len); - FirstPut(m_queue.GetContigousBlocks(m_firstSize)); - assert(m_queue.CurrentSize() == 0); - m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize); - - inString += len; - newLength -= m_firstSize; - m_firstInputDone = true; - } - - if (m_firstInputDone) - { - if (m_blockSize == 1) - { - while (newLength > m_lastSize && m_queue.CurrentSize() > 0) - { - unsigned int len = newLength - m_lastSize; - const byte *ptr = m_queue.GetContigousBlocks(len); - NextPut(ptr, len); - newLength -= len; - } - - if (newLength > m_lastSize) - { - unsigned int len = newLength - m_lastSize; - NextPut(inString, len); - inString += len; - newLength -= len; - } - } - else - { - while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize) - { - NextPut(m_queue.GetBlock(), m_blockSize); - newLength -= m_blockSize; - } - - if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0) - { - assert(m_queue.CurrentSize() < m_blockSize); - unsigned int len = m_blockSize - m_queue.CurrentSize(); - m_queue.Put(inString, len); - inString += len; - NextPut(m_queue.GetBlock(), m_blockSize); - newLength -= m_blockSize; - } - - while (newLength >= m_blockSize + m_lastSize) - { - NextPut(inString, m_blockSize); - inString += m_blockSize; - newLength -= m_blockSize; - } - } - } - - m_queue.Put(inString, newLength - m_queue.CurrentSize()); -} - -void FilterWithBufferedInput::MessageEnd(int propagation) -{ - if (!m_firstInputDone && m_firstSize==0) - FirstPut(nullptr); - - SecByteBlock temp(m_queue.CurrentSize()); - m_queue.GetAll(temp); - LastPut(temp, temp.size); - - m_firstInputDone = false; - m_queue.ResetQueue(1, m_firstSize); - - Filter::MessageEnd(propagation); -} - -void FilterWithBufferedInput::ForceNextPut() -{ - if (m_firstInputDone && m_queue.CurrentSize() >= m_blockSize) - NextPut(m_queue.GetBlock(), m_blockSize); -} - -// ************************************************************* - - - -// ************************************************************* - -ProxyFilter::ProxyFilter(Filter *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *outQ) - : FilterWithBufferedInput(firstSize, 1, lastSize, outQ), m_filter(filter), m_proxy(nullptr) -{ - if (m_filter.get()) - m_filter->Attach(m_proxy = new OutputProxy(*this, false)); -} - -void ProxyFilter::Flush(bool completeFlush, int propagation) -{ - if (m_filter.get()) - { - bool passSignal = m_proxy->GetPassSignal(); - m_proxy->SetPassSignal(false); - m_filter->Flush(completeFlush, -1); - m_proxy->SetPassSignal(passSignal); - } - Filter::Flush(completeFlush, propagation); -} - -void ProxyFilter::SetFilter(Filter *filter) -{ - bool passSignal = m_proxy ? m_proxy->GetPassSignal() : false; - m_filter.reset(filter); - if (filter) - { - std::unique_ptr temp(m_proxy = new OutputProxy(*this, passSignal)); - m_filter->TransferAllTo(*m_proxy); - m_filter->Attach(temp.release()); - } - else - m_proxy=nullptr; -} - -void ProxyFilter::NextPut(const byte *s, unsigned int len) -{ - if (m_filter.get()) - m_filter->Put(s, len); -} - -// ************************************************************* - -void StreamCipherFilter::Put(const byte *inString, unsigned int length) -{ - SecByteBlock temp(length); - cipher.ProcessString(temp, inString, length); - AttachedTransformation()->Put(temp, length); -} - -void HashFilter::Put(byte inByte) -{ - m_hashModule.Update(&inByte, 1); - if (m_putMessage) - AttachedTransformation()->Put(inByte); -} - -void HashFilter::Put(const byte *inString, unsigned int length) -{ - m_hashModule.Update(inString, length); - if (m_putMessage) - AttachedTransformation()->Put(inString, length); -} - -void HashFilter::MessageEnd(int propagation) -{ - SecByteBlock buf(m_hashModule.DigestSize()); - m_hashModule.Final(buf); - AttachedTransformation()->Put(buf, buf.size); - Filter::MessageEnd(propagation); -} - -// ************************************************************* - -HashVerifier::HashVerifier(HashModule &hm, BufferedTransformation *outQueue, word32 flags) - : FilterWithBufferedInput(flags & HASH_AT_BEGIN ? hm.DigestSize() : 0, 1, flags & HASH_AT_BEGIN ? 0 : hm.DigestSize(), outQueue) - , m_hashModule(hm), m_flags(flags) - , m_expectedHash(flags & HASH_AT_BEGIN ? hm.DigestSize() : 0), m_verified(false) -{ -} - -void HashVerifier::FirstPut(const byte *inString) -{ - if (m_flags & HASH_AT_BEGIN) - { - memcpy(m_expectedHash, inString, m_expectedHash.size); - if (m_flags & PUT_HASH) - AttachedTransformation()->Put(inString, m_expectedHash.size); - } -} - -void HashVerifier::NextPut(const byte *inString, unsigned int length) -{ - m_hashModule.Update(inString, length); - if (m_flags & PUT_MESSAGE) - AttachedTransformation()->Put(inString, length); -} - -void HashVerifier::LastPut(const byte *inString, unsigned int length) -{ - if (m_flags & HASH_AT_BEGIN) - { - assert(length == 0); - m_verified = m_hashModule.Verify(m_expectedHash); - } - else - { - m_verified = (length==m_hashModule.DigestSize() && m_hashModule.Verify(inString)); - if (m_flags & PUT_HASH) - AttachedTransformation()->Put(inString, length); - } - - if (m_flags & PUT_RESULT) - AttachedTransformation()->Put(m_verified); - - if ((m_flags & THROW_EXCEPTION) && !m_verified) - throw HashVerificationFailed(); -} - -// ************************************************************* - -void SignerFilter::MessageEnd(int propagation) -{ - SecByteBlock buf(m_signer.SignatureLength()); - m_signer.Sign(m_rng, m_messageAccumulator.release(), buf); - AttachedTransformation()->Put(buf, buf.size); - Filter::MessageEnd(propagation); - m_messageAccumulator.reset(m_signer.NewMessageAccumulator()); -} - -void VerifierFilter::PutSignature(const byte *sig) -{ - memcpy(m_signature.ptr, sig, m_signature.size); -} - -void VerifierFilter::MessageEnd(int propagation) -{ - AttachedTransformation()->Put((byte)m_verifier.Verify(m_messageAccumulator.release(), m_signature)); - Filter::MessageEnd(propagation); - m_messageAccumulator.reset(m_verifier.NewMessageAccumulator()); -} - -// ************************************************************* - -void Source::PumpAll() -{ - while (PumpMessages()) {} - while (Pump()) {} -} - -StringSource::StringSource(const char *string, bool pumpAll, BufferedTransformation *outQueue) - : Source(outQueue), m_store(string) -{ - if (pumpAll) - PumpAll(); -} - -StringSource::StringSource(const byte *string, unsigned int length, bool pumpAll, BufferedTransformation *outQueue) - : Source(outQueue), m_store(string, length) -{ - if (pumpAll) - PumpAll(); -} - -bool Store::GetNextMessage() -{ - if (!m_messageEnd && !AnyRetrievable()) - { - m_messageEnd=true; - return true; - } - else - return false; -} - -unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count) const -{ - if (m_messageEnd || count == 0) - return 0; - else - { - CopyTo(target); - if (GetAutoSignalPropagation()) - target.MessageEnd(GetAutoSignalPropagation()-1); - return 1; - } -} - -unsigned long StringStore::TransferTo(BufferedTransformation &target, unsigned long transferMax) -{ - unsigned long result = CopyTo(target, transferMax); - m_count += result; - return result; -} - -unsigned long StringStore::CopyTo(BufferedTransformation &target, unsigned long copyMax) const -{ - unsigned int len = (unsigned int)STDMIN((unsigned long)(m_length-m_count), copyMax); - target.Put(m_store+m_count, len); - return len; -} - -unsigned long RandomNumberStore::CopyTo(BufferedTransformation &target, unsigned long copyMax) const -{ - unsigned int len = (unsigned int)STDMIN((unsigned long)(m_length-m_count), copyMax); - for (unsigned int i=0; i(this)->m_attachment.reset(NewDefaultAttachment()); + return m_attachment.get(); +} + +void Filter::Detach(BufferedTransformation *newOut) +{ + m_attachment.reset(newOut); +} + +void Filter::Insert(Filter *filter) +{ + filter->m_attachment.reset(m_attachment.release()); + m_attachment.reset(filter); +} + +size_t Filter::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking); +} + +size_t Filter::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking); +} + +void Filter::Initialize(const NameValuePairs ¶meters, int propagation) +{ + m_inputPosition = m_continueAt = 0; + IsolatedInitialize(parameters); + PropagateInitialize(parameters, propagation); +} + +bool Filter::Flush(bool hardFlush, int propagation, bool blocking) +{ + switch (m_continueAt) + { + case 0: + if (IsolatedFlush(hardFlush, blocking)) + return true; + // fall through + case 1: + if (OutputFlush(1, hardFlush, propagation, blocking)) + return true; + // fall through + default: ; + } + return false; +} + +bool Filter::MessageSeriesEnd(int propagation, bool blocking) +{ + switch (m_continueAt) + { + case 0: + if (IsolatedMessageSeriesEnd(blocking)) + return true; + // fall through + case 1: + if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking)) + return true; + // fall through + default: ; + } + return false; +} + +void Filter::PropagateInitialize(const NameValuePairs ¶meters, int propagation) +{ + if (propagation) + AttachedTransformation()->Initialize(parameters, propagation-1); +} + +size_t Filter::OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel) +{ + if (messageEnd) + messageEnd--; + size_t result = AttachedTransformation()->ChannelPutModifiable2(channel, inString, length, messageEnd, blocking); + m_continueAt = result ? outputSite : 0; + return result; +} + +size_t Filter::Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel) +{ + if (messageEnd) + messageEnd--; + size_t result = AttachedTransformation()->ChannelPut2(channel, inString, length, messageEnd, blocking); + m_continueAt = result ? outputSite : 0; + return result; +} + +bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel) +{ + if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking)) + { + m_continueAt = outputSite; + return true; + } + m_continueAt = 0; + return false; +} + +bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel) +{ + if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking)) + { + m_continueAt = outputSite; + return true; + } + m_continueAt = 0; + return false; +} + +// ************************************************************* + +void MeterFilter::ResetMeter() +{ + m_currentMessageBytes = m_totalBytes = m_currentSeriesMessages = m_totalMessages = m_totalMessageSeries = 0; + m_rangesToSkip.clear(); +} + +void MeterFilter::AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow) +{ + MessageRange r = {message, position, size}; + m_rangesToSkip.push_back(r); + if (sortNow) + std::sort(m_rangesToSkip.begin(), m_rangesToSkip.end()); +} + +size_t MeterFilter::PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable) +{ + if (!m_transparent) + return 0; + + size_t t; + FILTER_BEGIN; + + m_begin = begin; + m_length = length; + + while (m_length > 0 || messageEnd) + { + if (m_length > 0 && !m_rangesToSkip.empty() && m_rangesToSkip.front().message == m_totalMessages && m_currentMessageBytes + m_length > m_rangesToSkip.front().position) + { + FILTER_OUTPUT_MAYBE_MODIFIABLE(1, m_begin, t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position, m_currentMessageBytes), false, modifiable); + + CRYPTOPP_ASSERT(t < m_length); + m_begin = PtrAdd(m_begin, t); + m_length -= t; + m_currentMessageBytes += t; + m_totalBytes += t; + + if (m_currentMessageBytes + m_length < m_rangesToSkip.front().position + m_rangesToSkip.front().size) + t = m_length; + else + { + t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position + m_rangesToSkip.front().size, m_currentMessageBytes); + CRYPTOPP_ASSERT(t <= m_length); + m_rangesToSkip.pop_front(); + } + + m_begin = PtrAdd(m_begin, t); + m_length -= t; + m_currentMessageBytes += t; + m_totalBytes += t; + } + else + { + FILTER_OUTPUT_MAYBE_MODIFIABLE(2, m_begin, m_length, messageEnd, modifiable); + + m_currentMessageBytes += m_length; + m_totalBytes += m_length; + m_length = 0; + + if (messageEnd) + { + m_currentMessageBytes = 0; + m_currentSeriesMessages++; + m_totalMessages++; + messageEnd = false; + } + } + } + + FILTER_END_NO_MESSAGE_END; +} + +size_t MeterFilter::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + return PutMaybeModifiable(const_cast(begin), length, messageEnd, blocking, false); +} + +size_t MeterFilter::PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking) +{ + return PutMaybeModifiable(begin, length, messageEnd, blocking, true); +} + +bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking) +{ + CRYPTOPP_UNUSED(blocking); + m_currentMessageBytes = 0; + m_currentSeriesMessages = 0; + m_totalMessageSeries++; + return false; +} + +// ************************************************************* + +void FilterWithBufferedInput::BlockQueue::ResetQueue(size_t blockSize, size_t maxBlocks) +{ + m_buffer.New(blockSize * maxBlocks); + m_blockSize = blockSize; + m_maxBlocks = maxBlocks; + m_size = 0; + m_begin = m_buffer; +} + +byte *FilterWithBufferedInput::BlockQueue::GetBlock() +{ + if (m_size >= m_blockSize) + { + byte *ptr = m_begin; + if ((m_begin = PtrAdd(m_begin, m_blockSize)) == m_buffer.end()) + m_begin = m_buffer; + m_size -= m_blockSize; + return ptr; + } + else + return NULLPTR; +} + +byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(size_t &numberOfBytes) +{ + numberOfBytes = STDMIN(numberOfBytes, STDMIN(PtrDiff(m_buffer.end(), m_begin), m_size)); + byte *ptr = m_begin; + m_begin = PtrAdd(m_begin, numberOfBytes); + m_size -= numberOfBytes; + if (m_size == 0 || m_begin == m_buffer.end()) + m_begin = m_buffer; + return ptr; +} + +size_t FilterWithBufferedInput::BlockQueue::GetAll(byte *outString) +{ + // Avoid passing NULL pointer to memcpy + if (!outString) return 0; + + size_t size = m_size; + size_t numberOfBytes = m_maxBlocks*m_blockSize; + const byte *ptr = GetContigousBlocks(numberOfBytes); + memcpy(outString, ptr, numberOfBytes); + memcpy(PtrAdd(outString, numberOfBytes), m_begin, m_size); + m_size = 0; + return size; +} + +void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, size_t length) +{ + // Avoid passing NULL pointer to memcpy + if (!inString || !length) return; + + CRYPTOPP_ASSERT(m_size + length <= m_buffer.size()); + byte *end = (m_size < static_cast(PtrDiff(m_buffer.end(), m_begin)) ? + PtrAdd(m_begin, m_size) : PtrAdd(m_begin, m_size - m_buffer.size())); + size_t len = STDMIN(length, size_t(m_buffer.end()-end)); + memcpy(end, inString, len); + if (len < length) + memcpy(m_buffer, PtrAdd(inString, len), length-len); + m_size += length; +} + +FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment) + : Filter(attachment), m_firstSize(SIZE_MAX), m_blockSize(0), m_lastSize(SIZE_MAX), m_firstInputDone(false) +{ +} + +FilterWithBufferedInput::FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment) + : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize), m_firstInputDone(false) +{ + if (m_firstSize == SIZE_MAX || m_blockSize < 1 || m_lastSize == SIZE_MAX) + throw InvalidArgument("FilterWithBufferedInput: invalid buffer size"); + + m_queue.ResetQueue(1, m_firstSize); +} + +void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs ¶meters) +{ + InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize); + if (m_firstSize == SIZE_MAX || m_blockSize < 1 || m_lastSize == SIZE_MAX) + throw InvalidArgument("FilterWithBufferedInput: invalid buffer size"); + m_queue.ResetQueue(1, m_firstSize); + m_firstInputDone = false; +} + +bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking) +{ + if (!blocking) + throw BlockingInputOnly("FilterWithBufferedInput"); + + if (hardFlush) + ForceNextPut(); + FlushDerived(); + + return false; +} + +size_t FilterWithBufferedInput::PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable) +{ + if (!blocking) + throw BlockingInputOnly("FilterWithBufferedInput"); + + if (length != 0) + { + size_t newLength = m_queue.CurrentSize() + length; + + if (!m_firstInputDone && newLength >= m_firstSize) + { + size_t len = m_firstSize - m_queue.CurrentSize(); + m_queue.Put(inString, len); + FirstPut(m_queue.GetContigousBlocks(m_firstSize)); + CRYPTOPP_ASSERT(m_queue.CurrentSize() == 0); + m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize); + + inString = PtrAdd(inString, len); + newLength -= m_firstSize; + m_firstInputDone = true; + } + + if (m_firstInputDone) + { + if (m_blockSize == 1) + { + while (newLength > m_lastSize && m_queue.CurrentSize() > 0) + { + size_t len = newLength - m_lastSize; + byte *ptr = m_queue.GetContigousBlocks(len); + NextPutModifiable(ptr, len); + newLength -= len; + } + + if (newLength > m_lastSize) + { + size_t len = newLength - m_lastSize; + NextPutMaybeModifiable(inString, len, modifiable); + inString = PtrAdd(inString, len); + newLength -= len; + } + } + else + { + while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize) + { + NextPutModifiable(m_queue.GetBlock(), m_blockSize); + newLength -= m_blockSize; + } + + if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0) + { + CRYPTOPP_ASSERT(m_queue.CurrentSize() < m_blockSize); + size_t len = m_blockSize - m_queue.CurrentSize(); + m_queue.Put(inString, len); + inString = PtrAdd(inString, len); + NextPutModifiable(m_queue.GetBlock(), m_blockSize); + newLength -= m_blockSize; + } + + if (newLength >= m_blockSize + m_lastSize) + { + size_t len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize); + NextPutMaybeModifiable(inString, len, modifiable); + inString = PtrAdd(inString, len); + newLength -= len; + } + } + } + + m_queue.Put(inString, newLength - m_queue.CurrentSize()); + } + + if (messageEnd) + { + if (!m_firstInputDone && m_firstSize==0) + FirstPut(NULLPTR); + + SecByteBlock temp(m_queue.CurrentSize()); + m_queue.GetAll(temp); + LastPut(temp, temp.size()); + + m_firstInputDone = false; + m_queue.ResetQueue(1, m_firstSize); + + // Cast to void to suppress Coverity finding + (void)Output(1, NULLPTR, 0, messageEnd, blocking); + } + return 0; +} + +void FilterWithBufferedInput::ForceNextPut() +{ + if (!m_firstInputDone) + return; + + if (m_blockSize > 1) + { + while (m_queue.CurrentSize() >= m_blockSize) + NextPutModifiable(m_queue.GetBlock(), m_blockSize); + } + else + { + size_t len; + while ((len = m_queue.CurrentSize()) > 0) + NextPutModifiable(m_queue.GetContigousBlocks(len), len); + } +} + +void FilterWithBufferedInput::NextPutMultiple(const byte *inString, size_t length) +{ + CRYPTOPP_ASSERT(m_blockSize > 1); // m_blockSize = 1 should always override this function + while (length > 0) + { + CRYPTOPP_ASSERT(length >= m_blockSize); + NextPutSingle(inString); + inString = PtrAdd(inString, m_blockSize); + length -= m_blockSize; + } +} + +// ************************************************************* + +void Redirector::Initialize(const NameValuePairs ¶meters, int propagation) +{ + m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULLPTR); + m_behavior = parameters.GetIntValueWithDefault("RedirectionBehavior", PASS_EVERYTHING); + + if (m_target && GetPassSignals()) + m_target->Initialize(parameters, propagation); +} + +// ************************************************************* + +ProxyFilter::ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment) + : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter) +{ + if (m_filter.get()) + m_filter->Attach(new OutputProxy(*this, false)); +} + +bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking) +{ + return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false; +} + +void ProxyFilter::SetFilter(Filter *filter) +{ + m_filter.reset(filter); + if (filter) + { + OutputProxy *proxy; + member_ptr temp(proxy = new OutputProxy(*this, false)); + m_filter->TransferAllTo(*proxy); + m_filter->Attach(temp.release()); + } +} + +void ProxyFilter::NextPutMultiple(const byte *s, size_t len) +{ + if (m_filter.get()) + m_filter->Put(s, len); +} + +void ProxyFilter::NextPutModifiable(byte *s, size_t len) +{ + if (m_filter.get()) + m_filter->PutModifiable(s, len); +} + +// ************************************************************* + +void RandomNumberSink::IsolatedInitialize(const NameValuePairs ¶meters) +{ + parameters.GetRequiredParameter("RandomNumberSink", "RandomNumberGeneratorPointer", m_rng); +} + +size_t RandomNumberSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking); + m_rng->IncorporateEntropy(begin, length); + return 0; +} + +size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking); + + // Avoid passing NULL pointer to memcpy. Using memmove due to + // Valgrind finding on overlapping buffers. + size_t copied = 0; + if (m_buf && begin) + { + copied = STDMIN(length, SaturatingSubtract(m_size, m_total)); + memmove(PtrAdd(m_buf, m_total), begin, copied); + } + m_total += copied; + return length - copied; +} + +byte * ArraySink::CreatePutSpace(size_t &size) +{ + size = SaturatingSubtract(m_size, m_total); + return PtrAdd(m_buf, m_total); +} + +void ArraySink::IsolatedInitialize(const NameValuePairs ¶meters) +{ + ByteArrayParameter array; + if (!parameters.GetValue(Name::OutputBuffer(), array)) + throw InvalidArgument("ArraySink: missing OutputBuffer argument"); + m_buf = array.begin(); + m_size = array.size(); +} + +size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking); + + // Avoid passing NULL pointer to xorbuf + size_t copied = 0; + if (m_buf && begin) + { + copied = STDMIN(length, SaturatingSubtract(m_size, m_total)); + xorbuf(PtrAdd(m_buf, m_total), begin, copied); + } + m_total += copied; + return length - copied; +} + +// ************************************************************* + +StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding) + : FilterWithBufferedInput(attachment), m_cipher(c), m_padding(DEFAULT_PADDING) +{ + CRYPTOPP_ASSERT(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize()); + + const bool authenticatedFilter = dynamic_cast(&c) != NULLPTR; + if (authenticatedFilter) + throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher"); + + // InitializeDerivedAndReturnNewSizes may override some of these + m_mandatoryBlockSize = m_cipher.MandatoryBlockSize(); + m_optimalBufferSize = m_cipher.OptimalBlockSize(); + m_isSpecial = m_cipher.IsLastBlockSpecial() && m_mandatoryBlockSize > 1; + m_reservedBufferSize = STDMAX(2*m_mandatoryBlockSize, m_optimalBufferSize); + + FilterWithBufferedInput::IsolatedInitialize( + MakeParameters + (Name::BlockPaddingScheme(), padding)); +} + +StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool authenticated) + : FilterWithBufferedInput(attachment), m_cipher(c), m_padding(DEFAULT_PADDING) +{ + const bool authenticatedFilter = dynamic_cast(&c) != NULLPTR; + if (!authenticatedFilter) + { + CRYPTOPP_ASSERT(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize()); + } + + if (authenticatedFilter && !authenticated) + throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher"); + + // InitializeDerivedAndReturnNewSizes may override some of these + m_mandatoryBlockSize = m_cipher.MandatoryBlockSize(); + m_optimalBufferSize = m_cipher.OptimalBlockSize(); + m_isSpecial = m_cipher.IsLastBlockSpecial() && m_mandatoryBlockSize > 1; + m_reservedBufferSize = STDMAX(2*m_mandatoryBlockSize, m_optimalBufferSize); + + FilterWithBufferedInput::IsolatedInitialize( + MakeParameters + (Name::BlockPaddingScheme(), padding)); +} + +size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding) +{ + if (c.MinLastBlockSize() > 0) + return c.MinLastBlockSize(); + else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING) + return c.MandatoryBlockSize(); + + return 0; +} + +void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) +{ + BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING); + bool isBlockCipher = (m_mandatoryBlockSize > 1 && m_cipher.MinLastBlockSize() == 0); + + if (padding == DEFAULT_PADDING) + m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING; + else + m_padding = padding; + + if (!isBlockCipher) + { + if (m_padding == PKCS_PADDING) + throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING cannot be used with " + m_cipher.AlgorithmName()); + else if (m_padding == W3C_PADDING) + throw InvalidArgument("StreamTransformationFilter: W3C_PADDING cannot be used with " + m_cipher.AlgorithmName()); + else if (m_padding == ONE_AND_ZEROS_PADDING) + throw InvalidArgument("StreamTransformationFilter: ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName()); + } + + firstSize = 0; + blockSize = m_mandatoryBlockSize; + lastSize = LastBlockSize(m_cipher, m_padding); +} + +void StreamTransformationFilter::FirstPut(const byte* inString) +{ + CRYPTOPP_UNUSED(inString); + m_optimalBufferSize = STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize)); +} + +void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length) +{ + if (!length) + {return;} + + const size_t s = m_cipher.MandatoryBlockSize(); + do + { + size_t len = m_optimalBufferSize; + byte *space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, length, len); + if (len < length) + { + if (len == m_optimalBufferSize) + len -= m_cipher.GetOptimalBlockSizeUsed(); + len = RoundDownToMultipleOf(len, s); + } + else + len = length; + m_cipher.ProcessString(space, inString, len); + AttachedTransformation()->PutModifiable(space, len); + inString = PtrAdd(inString, len); + length -= len; + } + while (length > 0); +} + +void StreamTransformationFilter::NextPutModifiable(byte *inString, size_t length) +{ + m_cipher.ProcessString(inString, length); + AttachedTransformation()->PutModifiable(inString, length); +} + +void StreamTransformationFilter::LastPut(const byte *inString, size_t length) +{ + // This block is new to StreamTransformationFilter. It is somewhat of a hack and was + // added for OCB mode; see GitHub Issue 515. The rub with OCB is, its a block cipher + // and the last block size can be 0. However, "last block = 0" is not the 0 predicated + // in the original code. In the original code 0 means "nothing special" so + // DEFAULT_PADDING is applied. OCB's 0 literally means a final block size can be 0 or + // non-0; and no padding is needed in either case because OCB has its own scheme (see + // handling of P_* and A_*). + // Stream ciphers have policy objects to convey how to operate the cipher. The Crypto++ + // framework operates well when MinLastBlockSize() is 1. However, it did not appear to + // cover the OCB case either because we can't stream OCB. It needs full block sizes. In + // response we hacked a IsLastBlockSpecial(). When true StreamTransformationFilter + // defers to the mode for processing of the last block. + // The behavior supplied when IsLastBlockSpecial() will likely have to evolve to capture + // more complex cases from different authenc modes. I suspect it will have to change + // from a simple bool to something that conveys more information, like "last block + // no padding" or "custom padding applied by cipher". + // In some respect we have already hit the need for more information. For example, OCB + // calculates the checksum on the cipher text at the same time, so we don't need the + // disjoint behavior of calling "EncryptBlock" followed by a separate "AuthenticateBlock". + // Additional information may allow us to avoid the two separate calls. + if (m_isSpecial) + { + const size_t leftOver = length % m_mandatoryBlockSize; + byte* space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, m_reservedBufferSize); + length -= leftOver; + + if (length) + { + // Process full blocks + m_cipher.ProcessData(space, inString, length); + AttachedTransformation()->Put(space, length); + inString = PtrAdd(inString, length); + } + + if (leftOver) + { + // Process final partial block + length = m_cipher.ProcessLastBlock(space, m_reservedBufferSize, inString, leftOver); + AttachedTransformation()->Put(space, length); + } + else + { + // Process final empty block + length = m_cipher.ProcessLastBlock(space, m_reservedBufferSize, NULLPTR, 0); + AttachedTransformation()->Put(space, length); + } + + return; + } + + switch (m_padding) + { + case NO_PADDING: + case ZEROS_PADDING: + if (length > 0) + { + const size_t minLastBlockSize = m_cipher.MinLastBlockSize(); + const bool isForwardTransformation = m_cipher.IsForwardTransformation(); + + if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize)) + { + // do padding + size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_mandatoryBlockSize); + byte* space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize); + if (inString) {memcpy(space, inString, length);} + memset(PtrAdd(space, length), 0, blockSize - length); + size_t used = m_cipher.ProcessLastBlock(space, blockSize, space, blockSize); + AttachedTransformation()->Put(space, used); + } + else + { + if (minLastBlockSize == 0) + { + if (isForwardTransformation) + throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified"); + else + throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size"); + } + + byte* space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize); + size_t used = m_cipher.ProcessLastBlock(space, length, inString, length); + AttachedTransformation()->Put(space, used); + } + } + break; + + case PKCS_PADDING: + case W3C_PADDING: + case ONE_AND_ZEROS_PADDING: + unsigned int s; + byte* space; + s = m_mandatoryBlockSize; + CRYPTOPP_ASSERT(s > 1); + space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize); + if (m_cipher.IsForwardTransformation()) + { + CRYPTOPP_ASSERT(length < s); + if (inString) {memcpy(space, inString, length);} + if (m_padding == PKCS_PADDING) + { + CRYPTOPP_ASSERT(s < 256); + byte pad = static_cast(s-length); + memset(PtrAdd(space, length), pad, s-length); + } + else if (m_padding == W3C_PADDING) + { + CRYPTOPP_ASSERT(s < 256); + memset(PtrAdd(space, length), 0, s-length-1); + space[s-1] = static_cast(s-length); + } + else + { + space[length] = 0x80; + memset(PtrAdd(space, length+1), 0, s-length-1); + } + m_cipher.ProcessData(space, space, s); + AttachedTransformation()->Put(space, s); + } + else + { + if (length != s) + throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size"); + m_cipher.ProcessData(space, inString, s); + if (m_padding == PKCS_PADDING) + { + byte pad = space[s-1]; + if (pad < 1 || pad > s || FindIfNot(PtrAdd(space, s-pad), PtrAdd(space, s), pad) != PtrAdd(space, s)) + throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found"); + length = s-pad; + } + else if (m_padding == W3C_PADDING) + { + byte pad = space[s - 1]; + if (pad < 1 || pad > s) + throw InvalidCiphertext("StreamTransformationFilter: invalid W3C block padding found"); + length = s - pad; + } + else + { + while (length > 1 && space[length-1] == 0) + --length; + if (space[--length] != 0x80) + throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found"); + } + AttachedTransformation()->Put(space, length); + } + break; + + default: + CRYPTOPP_ASSERT(false); + } +} + +// ************************************************************* + +HashFilter::HashFilter(HashTransformation &hm, BufferedTransformation *attachment, bool putMessage, int truncatedDigestSize, const std::string &messagePutChannel, const std::string &hashPutChannel) + : m_hashModule(hm), m_putMessage(putMessage), m_digestSize(0), m_space(NULLPTR) + , m_messagePutChannel(messagePutChannel), m_hashPutChannel(hashPutChannel) +{ + m_digestSize = truncatedDigestSize < 0 ? m_hashModule.DigestSize() : truncatedDigestSize; + Detach(attachment); +} + +void HashFilter::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false); + int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1); + m_digestSize = s < 0 ? m_hashModule.DigestSize() : s; +} + +size_t HashFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) +{ + FILTER_BEGIN; + if (m_putMessage) + FILTER_OUTPUT3(1, 0, inString, length, 0, m_messagePutChannel); + if (inString && length) + m_hashModule.Update(inString, length); + if (messageEnd) + { + { + size_t size; + m_space = HelpCreatePutSpace(*AttachedTransformation(), m_hashPutChannel, m_digestSize, m_digestSize, size = m_digestSize); + m_hashModule.TruncatedFinal(m_space, m_digestSize); + } + FILTER_OUTPUT3(2, 0, m_space, m_digestSize, messageEnd, m_hashPutChannel); + } + FILTER_END_NO_MESSAGE_END; +} + +// ************************************************************* + +HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize) + : FilterWithBufferedInput(attachment) + , m_hashModule(hm), m_flags(0), m_digestSize(0), m_verified(false) +{ + FilterWithBufferedInput::IsolatedInitialize( + MakeParameters + (Name::HashVerificationFilterFlags(), flags) + (Name::TruncatedDigestSize(), truncatedDigestSize)); +} + +void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) +{ + m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS); + int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1); + m_digestSize = s < 0 ? m_hashModule.DigestSize() : s; + m_verified = false; + firstSize = m_flags & HASH_AT_BEGIN ? m_digestSize : 0; + blockSize = 1; + lastSize = m_flags & HASH_AT_BEGIN ? 0 : m_digestSize; +} + +void HashVerificationFilter::FirstPut(const byte *inString) +{ + if (m_flags & HASH_AT_BEGIN) + { + m_expectedHash.New(m_digestSize); + if (inString) {memcpy(m_expectedHash, inString, m_expectedHash.size());} + if (m_flags & PUT_HASH) + AttachedTransformation()->Put(inString, m_expectedHash.size()); + } +} + +void HashVerificationFilter::NextPutMultiple(const byte *inString, size_t length) +{ + m_hashModule.Update(inString, length); + if (m_flags & PUT_MESSAGE) + AttachedTransformation()->Put(inString, length); +} + +void HashVerificationFilter::LastPut(const byte *inString, size_t length) +{ + if (m_flags & HASH_AT_BEGIN) + { + CRYPTOPP_ASSERT(length == 0); + m_verified = m_hashModule.TruncatedVerify(m_expectedHash, m_digestSize); + } + else + { + m_verified = (length==m_digestSize && m_hashModule.TruncatedVerify(inString, length)); + if (m_flags & PUT_HASH) + AttachedTransformation()->Put(inString, length); + } + + if (m_flags & PUT_RESULT) + AttachedTransformation()->Put(m_verified); + + if ((m_flags & THROW_EXCEPTION) && !m_verified) + throw HashVerificationFailed(); +} + +// ************************************************************* + +AuthenticatedEncryptionFilter::AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, + bool putAAD, int truncatedDigestSize, const std::string &macChannel, BlockPaddingScheme padding) + : StreamTransformationFilter(c, attachment, padding, true) + , m_hf(c, new OutputProxy(*this, false), putAAD, truncatedDigestSize, AAD_CHANNEL, macChannel) +{ + CRYPTOPP_ASSERT(c.IsForwardTransformation()); +} + +void AuthenticatedEncryptionFilter::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_hf.IsolatedInitialize(parameters); + StreamTransformationFilter::IsolatedInitialize(parameters); +} + +byte * AuthenticatedEncryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size) +{ + if (channel.empty()) + return StreamTransformationFilter::CreatePutSpace(size); + + if (channel == AAD_CHANNEL) + return m_hf.CreatePutSpace(size); + + throw InvalidChannelName("AuthenticatedEncryptionFilter", channel); +} + +size_t AuthenticatedEncryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (channel.empty()) + return StreamTransformationFilter::Put2(begin, length, messageEnd, blocking); + + if (channel == AAD_CHANNEL) + return m_hf.Put2(begin, length, 0, blocking); + + throw InvalidChannelName("AuthenticatedEncryptionFilter", channel); +} + +void AuthenticatedEncryptionFilter::LastPut(const byte *inString, size_t length) +{ + StreamTransformationFilter::LastPut(inString, length); + m_hf.MessageEnd(); +} + +// ************************************************************* + +AuthenticatedDecryptionFilter::AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize, BlockPaddingScheme padding) + : FilterWithBufferedInput(attachment) + , m_hashVerifier(c, new OutputProxy(*this, false)) + , m_streamFilter(c, new OutputProxy(*this, false), padding, true) +{ + CRYPTOPP_ASSERT(!c.IsForwardTransformation() || c.IsSelfInverting()); + FilterWithBufferedInput::IsolatedInitialize( + MakeParameters + (Name::BlockPaddingScheme(), padding) + (Name::AuthenticatedDecryptionFilterFlags(), flags) + (Name::TruncatedDigestSize(), truncatedDigestSize)); +} + +void AuthenticatedDecryptionFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) +{ + word32 flags = parameters.GetValueWithDefault(Name::AuthenticatedDecryptionFilterFlags(), (word32)DEFAULT_FLAGS); + + m_hashVerifier.Initialize(CombinedNameValuePairs(parameters, MakeParameters(Name::HashVerificationFilterFlags(), flags))); + m_streamFilter.Initialize(parameters); + + firstSize = m_hashVerifier.m_firstSize; + blockSize = 1; + lastSize = m_hashVerifier.m_lastSize; +} + +byte * AuthenticatedDecryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size) +{ + if (channel.empty()) + return m_streamFilter.CreatePutSpace(size); + + if (channel == AAD_CHANNEL) + return m_hashVerifier.CreatePutSpace(size); + + throw InvalidChannelName("AuthenticatedDecryptionFilter", channel); +} + +size_t AuthenticatedDecryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (channel.empty()) + { + if (m_lastSize > 0) + m_hashVerifier.ForceNextPut(); + return FilterWithBufferedInput::Put2(begin, length, messageEnd, blocking); + } + + if (channel == AAD_CHANNEL) + return m_hashVerifier.Put2(begin, length, 0, blocking); + + throw InvalidChannelName("AuthenticatedDecryptionFilter", channel); +} + +void AuthenticatedDecryptionFilter::FirstPut(const byte *inString) +{ + m_hashVerifier.Put(inString, m_firstSize); +} + +void AuthenticatedDecryptionFilter::NextPutMultiple(const byte *inString, size_t length) +{ + m_streamFilter.Put(inString, length); +} + +void AuthenticatedDecryptionFilter::LastPut(const byte *inString, size_t length) +{ + m_streamFilter.MessageEnd(); + m_hashVerifier.PutMessageEnd(inString, length); +} + +// ************************************************************* + +void SignerFilter::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false); + m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng)); +} + +size_t SignerFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) +{ + FILTER_BEGIN; + m_messageAccumulator->Update(inString, length); + if (m_putMessage) + FILTER_OUTPUT(1, inString, length, 0); + if (messageEnd) + { + m_buf.New(m_signer.SignatureLength()); + m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf); + FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd); + m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng)); + } + FILTER_END_NO_MESSAGE_END; +} + +SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags) + : FilterWithBufferedInput(attachment) + , m_verifier(verifier), m_flags(0), m_verified(0) +{ + FilterWithBufferedInput::IsolatedInitialize( + MakeParameters + (Name::SignatureVerificationFilterFlags(), flags)); +} + +void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) +{ + m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS); + m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator()); + size_t size = m_verifier.SignatureLength(); + CRYPTOPP_ASSERT(size != 0); // TODO: handle recoverable signature scheme + m_verified = false; + firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0; + blockSize = 1; + lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size; +} + +void SignatureVerificationFilter::FirstPut(const byte *inString) +{ + if (m_flags & SIGNATURE_AT_BEGIN) + { + if (m_verifier.SignatureUpfront()) + m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength()); + else + { + m_signature.New(m_verifier.SignatureLength()); + if (inString) {memcpy(m_signature, inString, m_signature.size());} + } + + if (m_flags & PUT_SIGNATURE) + AttachedTransformation()->Put(inString, m_signature.size()); + } + else + { + CRYPTOPP_ASSERT(!m_verifier.SignatureUpfront()); + } +} + +void SignatureVerificationFilter::NextPutMultiple(const byte *inString, size_t length) +{ + m_messageAccumulator->Update(inString, length); + if (m_flags & PUT_MESSAGE) + AttachedTransformation()->Put(inString, length); +} + +void SignatureVerificationFilter::LastPut(const byte *inString, size_t length) +{ + if (m_flags & SIGNATURE_AT_BEGIN) + { + CRYPTOPP_ASSERT(length == 0); + m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size()); + m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator); + } + else + { + m_verifier.InputSignature(*m_messageAccumulator, inString, length); + m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator); + if (m_flags & PUT_SIGNATURE) + AttachedTransformation()->Put(inString, length); + } + + if (m_flags & PUT_RESULT) + AttachedTransformation()->Put(m_verified); + + if ((m_flags & THROW_EXCEPTION) && !m_verified) + throw SignatureVerificationFailed(); +} + +// ************************************************************* + +size_t Source::PumpAll2(bool blocking) +{ + unsigned int messageCount = UINT_MAX; + do { + RETURN_IF_NONZERO(PumpMessages2(messageCount, blocking)); + } while(messageCount == UINT_MAX); + + return 0; +} + +bool Store::GetNextMessage() +{ + if (!m_messageEnd && !AnyRetrievable()) + { + m_messageEnd=true; + return true; + } + else + return false; +} + +unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const +{ + if (m_messageEnd || count == 0) + return 0; + else + { + CopyTo(target, ULONG_MAX, channel); + if (GetAutoSignalPropagation()) + target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1); + return 1; + } +} + +void StringStore::StoreInitialize(const NameValuePairs ¶meters) +{ + ConstByteArrayParameter array; + if (!parameters.GetValue(Name::InputBuffer(), array)) + throw InvalidArgument("StringStore: missing InputBuffer argument"); + m_store = array.begin(); + m_length = array.size(); + m_count = 0; +} + +size_t StringStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + lword position = 0; + size_t blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking); + m_count += static_cast(position); + transferBytes = position; + return blockedBytes; +} + +size_t StringStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + size_t i = UnsignedMin(m_length, m_count+begin); + size_t len = UnsignedMin(m_length-i, end-begin); + size_t blockedBytes = target.ChannelPut2(channel, PtrAdd(m_store, i), len, 0, blocking); + if (!blockedBytes) + begin = PtrAdd(begin, len); + return blockedBytes; +} + +void RandomNumberStore::StoreInitialize(const NameValuePairs ¶meters) +{ + parameters.GetRequiredParameter("RandomNumberStore", "RandomNumberGeneratorPointer", m_rng); + int length; + parameters.GetRequiredIntParameter("RandomNumberStore", "RandomNumberStoreSize", length); + m_length = length; +} + +size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + if (!blocking) + throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object"); + + transferBytes = UnsignedMin(transferBytes, m_length - m_count); + m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes); + m_count += transferBytes; + + return 0; +} + +size_t NullStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + static const byte nullBytes[128] = {0}; + while (begin < end) + { + size_t len = (size_t)STDMIN(end-begin, lword(128)); + size_t blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking); + if (blockedBytes) + return blockedBytes; + begin = PtrAdd(begin, len); + } + return 0; +} + +size_t NullStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + lword begin = 0; + size_t blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking); + transferBytes = begin; m_size -= begin; + return blockedBytes; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/filters.h b/external/ours/library/crypto/src/shared/original/filters.h index b80c518a0..ee89c37a0 100755 --- a/external/ours/library/crypto/src/shared/original/filters.h +++ b/external/ours/library/crypto/src/shared/original/filters.h @@ -1,560 +1,1529 @@ -#ifndef CRYPTOPP_FILTERS_H -#define CRYPTOPP_FILTERS_H - -#include "cryptlib.h" -#include "misc.h" -#include "smartptr.h" -#include "queue.h" - -NAMESPACE_BEGIN(CryptoPP) - -/// provides an implementation of BufferedTransformation's attachment interface -class Filter : virtual public BufferedTransformation -{ -public: - Filter(BufferedTransformation *outQ); - - bool Attachable() {return true;} - BufferedTransformation *AttachedTransformation() {return m_outQueue.get();} - const BufferedTransformation *AttachedTransformation() const {return m_outQueue.get();} - void Detach(BufferedTransformation *newOut = nullptr); - -protected: - virtual void NotifyAttachmentChange() {} - void Insert(Filter *nextFilter); // insert filter after this one - -private: - void operator=(const Filter &); // assignment not allowed - - member_ptr m_outQueue; -}; - -//! . -class TransparentFilter : public Filter -{ -public: - TransparentFilter(BufferedTransformation *outQ=nullptr) : Filter(outQ) {} - void Put(byte inByte) {AttachedTransformation()->Put(inByte);} - void Put(const byte *inString, unsigned int length) {AttachedTransformation()->Put(inString, length);} -}; - -//! . -class OpaqueFilter : public Filter -{ -public: - OpaqueFilter(BufferedTransformation *outQ=nullptr) : Filter(outQ) {} - void Put(byte inByte) {} - void Put(const byte *inString, unsigned int length) {} -}; - -/*! FilterWithBufferedInput divides up 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). -*/ -class FilterWithBufferedInput : public Filter -{ -public: - /// firstSize and lastSize may be 0, blockSize must be at least 1 - FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *outQ); - void Put(byte inByte); - void Put(const byte *inString, unsigned int length); - void MessageEnd(int propagation=-1); - - /*! 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: - bool DidFirstPut() {return m_firstInputDone;} - - // FirstPut() is called if (firstSize != 0 and totalLength >= firstSize) - // or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received)) - virtual void FirstPut(const byte *inString) =0; - // NextPut() is called if totalLength >= firstSize+blockSize+lastSize - // length parameter is always blockSize unless blockSize == 1 - virtual void NextPut(const byte *inString, unsigned int length) =0; - // LastPut() is always called - // 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, unsigned int length) =0; - -private: - class BlockQueue - { - public: - BlockQueue(unsigned int blockSize, unsigned int maxBlocks); - void ResetQueue(unsigned int blockSize, unsigned int maxBlocks); - const byte *GetBlock(); - const byte *GetContigousBlocks(unsigned int &numberOfBlocks); - unsigned int GetAll(byte *outString); - void Put(const byte *inString, unsigned int length); - unsigned int CurrentSize() const {return m_size;} - unsigned int MaxSize() const {return m_buffer.size;} - - private: - SecByteBlock m_buffer; - unsigned int m_blockSize, m_maxBlocks, m_size; - byte *m_begin; - }; - - unsigned int m_firstSize, m_blockSize, m_lastSize; - bool m_firstInputDone; - BlockQueue m_queue; -}; - -//! . -class FilterWithInputQueue : public Filter -{ -public: - FilterWithInputQueue(BufferedTransformation *attachment) : Filter(attachment) {} - void Put(byte inByte) {m_inQueue.Put(inByte);} - void Put(const byte *inString, unsigned int length) {m_inQueue.Put(inString, length);} - -protected: - ByteQueue m_inQueue; -}; - -//! Filter Wrapper for StreamCipher -class StreamCipherFilter : public Filter -{ -public: - StreamCipherFilter(StreamCipher &c, - BufferedTransformation *outQueue = nullptr) - : cipher(c), Filter(outQueue) {} - - void Put(byte inByte) - {AttachedTransformation()->Put(cipher.ProcessByte(inByte));} - - void Put(const byte *inString, unsigned int length); - -private: - StreamCipher &cipher; -}; - -//! Filter Wrapper for HashModule -class HashFilter : public Filter -{ -public: - HashFilter(HashModule &hm, BufferedTransformation *outQueue = nullptr, bool putMessage=false) - : Filter(outQueue), m_hashModule(hm), m_putMessage(putMessage) {} - - void MessageEnd(int propagation=-1); - - void Put(byte inByte); - void Put(const byte *inString, unsigned int length); - -private: - HashModule &m_hashModule; - bool m_putMessage; -}; - -//! Filter Wrapper for HashModule -class HashVerifier : public FilterWithBufferedInput -{ -public: - class HashVerificationFailed : public BufferedTransformation::Err - { - public: - HashVerificationFailed() - : BufferedTransformation::Err(DATA_INTEGRITY_CHECK_FAILED, "HashVerifier: message hash not correct") {} - }; - - enum Flags {HASH_AT_BEGIN=1, PUT_MESSAGE=2, PUT_HASH=4, PUT_RESULT=8, THROW_EXCEPTION=16}; - HashVerifier(HashModule &hm, BufferedTransformation *outQueue = nullptr, word32 flags = HASH_AT_BEGIN | PUT_RESULT); - - bool GetLastResult() const {return m_verified;} - -protected: - void FirstPut(const byte *inString); - void NextPut(const byte *inString, unsigned int length); - void LastPut(const byte *inString, unsigned int length); - -private: - HashModule &m_hashModule; - word32 m_flags; - SecByteBlock m_expectedHash; - bool m_verified; -}; - -//! Filter Wrapper for PK_Signer -class SignerFilter : public Filter -{ -public: - SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *outQueue = nullptr) - : m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewMessageAccumulator()), Filter(outQueue) {} - - void MessageEnd(int propagation); - - void Put(byte inByte) - {m_messageAccumulator->Update(&inByte, 1);} - - void Put(const byte *inString, unsigned int length) - {m_messageAccumulator->Update(inString, length);} - -private: - RandomNumberGenerator &m_rng; - const PK_Signer &m_signer; - member_ptr m_messageAccumulator; -}; - -//! Filter Wrapper for PK_Verifier -class VerifierFilter : public Filter -{ -public: - VerifierFilter(const PK_Verifier &verifier, BufferedTransformation *outQueue = nullptr) - : m_verifier(verifier), m_messageAccumulator(verifier.NewMessageAccumulator()) - , m_signature(verifier.SignatureLength()), Filter(outQueue) {} - - // this function must be called before MessageEnd() - void PutSignature(const byte *sig); - - void MessageEnd(int propagation); - - void Put(byte inByte) - {m_messageAccumulator->Update(&inByte, 1);} - - void Put(const byte *inString, unsigned int length) - {m_messageAccumulator->Update(inString, length);} - -private: - const PK_Verifier &m_verifier; - member_ptr m_messageAccumulator; - SecByteBlock m_signature; -}; - -//! A BufferedTransformation that doesn't produce any retrievable output -class Sink : public BufferedTransformation -{ -}; - -//! . -class BitBucket : public Sink -{ -public: - void Put(byte) {} - void Put(const byte *, unsigned int) {} -}; - -extern BitBucket g_bitBucket; - -//! Redirect input to another BufferedTransformation without owning it -class Redirector : public Sink -{ -public: - Redirector() : m_target(nullptr), m_passSignal(true) {} - Redirector(BufferedTransformation &target, bool passSignal=true) : m_target(&target), m_passSignal(passSignal) {} - - void Redirect(BufferedTransformation &target) {m_target = ⌖} - void StopRedirect() {m_target = nullptr;} - bool GetPassSignal() const {return m_passSignal;} - void SetPassSignal(bool passSignal) {m_passSignal = passSignal;} - - void Put(byte b) - {if (m_target) m_target->Put(b);} - void Put(const byte *string, unsigned int len) - {if (m_target) m_target->Put(string, len);} - void Flush(bool completeFlush, int propagation=-1) - {if (m_target && m_passSignal) m_target->Flush(completeFlush, propagation);} - void MessageEnd(int propagation=-1) - {if (m_target && m_passSignal) m_target->MessageEnd(propagation);} - void MessageSeriesEnd(int propagation=-1) - {if (m_target && m_passSignal) m_target->MessageSeriesEnd(propagation);} - - void ChannelPut(const std::string &channel, byte b) - {if (m_target) m_target->ChannelPut(channel, b);} - void ChannelPut(const std::string &channel, const byte *string, unsigned int len) - {if (m_target) m_target->ChannelPut(channel, string, len);} - void ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1) - {if (m_target && m_passSignal) m_target->ChannelFlush(channel, completeFlush, propagation);} - void ChannelMessageEnd(const std::string &channel, int propagation=-1) - {if (m_target && m_passSignal) m_target->ChannelMessageEnd(channel, propagation);} - void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1) - {if (m_target && m_passSignal) m_target->ChannelMessageSeriesEnd(channel, propagation);} - -private: - BufferedTransformation *m_target; - bool m_passSignal; -}; - -// Used By ProxyFilter -class OutputProxy : public Sink -{ -public: - OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {} - - bool GetPassSignal() const {return m_passSignal;} - void SetPassSignal(bool passSignal) {m_passSignal = passSignal;} - - void Put(byte b) - {m_owner.AttachedTransformation()->Put(b);} - void Put(const byte *string, unsigned int len) - {m_owner.AttachedTransformation()->Put(string, len);} - void Flush(bool completeFlush, int propagation=-1) - {if (m_passSignal) m_owner.AttachedTransformation()->Flush(completeFlush, propagation);} - void MessageEnd(int propagation=-1) - {if (m_passSignal) m_owner.AttachedTransformation()->MessageEnd(propagation);} - void MessageSeriesEnd(int propagation=-1) - {if (m_passSignal) m_owner.AttachedTransformation()->MessageSeriesEnd(propagation);} - - void ChannelPut(const std::string &channel, byte b) - {m_owner.AttachedTransformation()->ChannelPut(channel, b);} - void ChannelPut(const std::string &channel, const byte *string, unsigned int len) - {m_owner.AttachedTransformation()->ChannelPut(channel, string, len);} - void ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1) - {if (m_passSignal) m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation);} - void ChannelMessageEnd(const std::string &channel, int propagation=-1) - {if (m_passSignal) m_owner.AttachedTransformation()->ChannelMessageEnd(channel, propagation);} - void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1) - {if (m_passSignal) m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation);} - -private: - BufferedTransformation &m_owner; - bool m_passSignal; -}; - -//! Base class for Filter classes that are proxies for a chain of other filters. -class ProxyFilter : public FilterWithBufferedInput -{ -public: - ProxyFilter(Filter *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *outQ); - - void Flush(bool completeFlush, int propagation=-1); - - void SetFilter(Filter *filter); - void NextPut(const byte *s, unsigned int len); - -protected: - member_ptr m_filter; - OutputProxy *m_proxy; -}; - -//! Append input to a string object -template -class StringSinkTemplate : public Sink -{ -public: - // VC60 workaround: no T::char_type - typedef typename T::traits_type::char_type char_type; - - StringSinkTemplate(T &output) - : m_output(output) {assert(sizeof(output[0])==1);} - void Put(byte b) - {m_output += (char_type)b;} - void Put(const byte *str, unsigned int bc) - {m_output.append((const char_type *)str, bc);} - -private: - T &m_output; -}; - -//! Append input to an std::string -typedef StringSinkTemplate StringSink; - -//! Copy input to a memory buffer -class ArraySink : public Sink -{ -public: - ArraySink(byte *buf, unsigned int size) : m_buf(buf), m_size(size), m_total(0) {} - - unsigned int AvailableSize() {return m_size - STDMIN(m_total, (unsigned long)m_size);} - unsigned long TotalPutLength() {return m_total;} - - void Put(byte b) - { - if (m_total < m_size) - m_buf[m_total] = b; - m_total++; - } - - void Put(const byte *str, unsigned int len) - { - if (m_total < m_size) - memcpy(m_buf+m_total, str, STDMIN(len, (unsigned int)(m_size-m_total))); - m_total += len; - } - -protected: - byte *m_buf; - unsigned int m_size; - unsigned long m_total; -}; - -//! Xor input to a memory buffer -class ArrayXorSink : public ArraySink -{ -public: - ArrayXorSink(byte *buf, unsigned int size) - : ArraySink(buf, size) {} - - void Put(byte b) - { - if (m_total < m_size) - m_buf[m_total] ^= b; - m_total++; - } - - void Put(const byte *str, unsigned int len) - { - if (m_total < m_size) - xorbuf(m_buf+m_total, str, STDMIN(len, (unsigned int)(m_size-m_total))); - m_total += len; - } -}; - -//! Provide implementation of SetAutoSignalPropagation and GetAutoSignalPropagation -class BufferedTransformationWithAutoSignal : virtual public BufferedTransformation -{ -public: - BufferedTransformationWithAutoSignal(int propagation=-1) : m_autoSignalPropagation(propagation) {} - - void SetAutoSignalPropagation(int propagation) - {m_autoSignalPropagation = propagation;} - int GetAutoSignalPropagation() const - {return m_autoSignalPropagation;} - -private: - int m_autoSignalPropagation; -}; - -//! A BufferedTransformation that only contains pre-existing output -class Store : public BufferedTransformationWithAutoSignal -{ -public: - Store() : m_messageEnd(false) {} - - void Put(byte) - {} - void Put(const byte *, unsigned int length) - {} - - virtual unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX) =0; - virtual unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const =0; - - unsigned int NumberOfMessages() const {return m_messageEnd ? 0 : 1;} - bool GetNextMessage(); - unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX) const; - -private: - bool m_messageEnd; -}; - -//! . -class StringStore : public Store -{ -public: - StringStore(const char *string) - : m_store((const byte *)string), m_length(strlen(string)), m_count(0) {} - StringStore(const byte *string, unsigned int length) - : m_store(string), m_length(length), m_count(0) {} - template StringStore(const T &string) - : m_store((const byte *)string.data()), m_length(string.length()), m_count(0) {assert(sizeof(string[0])==1);} - - unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX); - unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const; - -private: - const byte *m_store; - unsigned int m_length, m_count; -}; - -//! . -class RandomNumberStore : public Store -{ -public: - RandomNumberStore(RandomNumberGenerator &rng, unsigned long length) - : m_rng(rng), m_length(length), m_count(0) {} - - unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX); - unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const; - -private: - RandomNumberGenerator &m_rng; - unsigned long m_length, m_count; -}; - -//! A Filter that pumps data into its attachment as input -class Source : public Filter -{ -public: - Source(BufferedTransformation *outQ) - : Filter(outQ) {} - - virtual unsigned long Pump(unsigned long pumpMax=ULONG_MAX) =0; - virtual unsigned int PumpMessages(unsigned int count=UINT_MAX) {return 0;} - void PumpAll(); - - void Put(byte) - {Pump(1);} - void Put(const byte *, unsigned int length) - {Pump(length);} - void MessageEnd(int propagation=-1) - {PumpAll();} -}; - -//! Turn a Store into a Source -class GeneralSource : public Source -{ -public: - GeneralSource(BufferedTransformation &store, bool pumpAll, BufferedTransformation *outQueue = nullptr) - : Source(outQueue), m_store(store) - { - if (pumpAll) PumpAll(); - } - - unsigned long Pump(unsigned long pumpMax=ULONG_MAX) - {return m_store.TransferTo(*AttachedTransformation(), pumpMax);} - unsigned int PumpMessages(unsigned int count=UINT_MAX) - {return m_store.TransferMessagesTo(*AttachedTransformation(), count);} - -private: - BufferedTransformation &m_store; -}; - -//! . -class StringSource : public Source -{ -public: - StringSource(const char *string, bool pumpAll, BufferedTransformation *outQueue = nullptr); - StringSource(const byte *string, unsigned int length, bool pumpAll, BufferedTransformation *outQueue = nullptr); - -#ifdef __MWERKS__ // CW60 workaround - StringSource(const std::string &string, bool pumpAll, BufferedTransformation *outQueue = nullptr) -#else - template StringSource(const T &string, bool pumpAll, BufferedTransformation *outQueue = nullptr) -#endif - : Source(outQueue), m_store(string) - { - if (pumpAll) - PumpAll(); - } - - unsigned long Pump(unsigned long pumpMax=ULONG_MAX) - {return m_store.TransferTo(*AttachedTransformation(), pumpMax);} - unsigned int PumpMessages(unsigned int count=UINT_MAX) - {return m_store.TransferMessagesTo(*AttachedTransformation(), count);} - -private: - StringStore m_store; -}; - -//! . -class RandomNumberSource : public Source -{ -public: - RandomNumberSource(RandomNumberGenerator &rng, unsigned int length, bool pumpAll, BufferedTransformation *outQueue = nullptr); - - unsigned long Pump(unsigned long pumpMax=ULONG_MAX) - {return m_store.TransferTo(*AttachedTransformation(), pumpMax);} - unsigned int PumpMessages(unsigned int count=UINT_MAX) - {return m_store.TransferMessagesTo(*AttachedTransformation(), count);} - -private: - RandomNumberStore m_store; -}; - -NAMESPACE_END - -#endif +// 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 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. +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 Temporay 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 contructor creates a StreamTransformationFilter() for stream ciphers and + /// confidentiality-only block cipher modes of operation. If you are using an authenticated + /// encryption mode of operation, then use either AuthenticatedEncryptionFilter() or + /// AuthenticatedDecryptionFilter(). + /// \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 pipleline, ArraySink silently discards input if the buffer is full. +/// AvailableSize() can be used to determine how much space remains in the buffer. +/// TotalPutLength() can be used to determine how many bytes were processed. +/// \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 pipleline, ArrayXorSink silently discards input if the buffer is full. +/// AvailableSize() can be used to determine how much space remains in the buffer. +/// TotalPutLength() can be used to determine how many bytes were processed. +/// \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/external/ours/library/crypto/src/shared/original/fips140.cpp b/external/ours/library/crypto/src/shared/original/fips140.cpp new file mode 100755 index 000000000..4e137443c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/fips140.cpp @@ -0,0 +1,84 @@ +// fips140.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "fips140.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +// Define this to 1 to turn on FIPS 140-2 compliance features, including additional tests during +// startup, random number generation, and key generation. These tests may affect performance. +#ifndef CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 +#define CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 0 +#endif + +#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(OS_RNG_AVAILABLE)) +#error FIPS 140-2 compliance requires the availability of OS provided RNG. +#endif + +PowerUpSelfTestStatus g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_NOT_DONE; + +bool FIPS_140_2_ComplianceEnabled() +{ + return CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2; +} + +void SimulatePowerUpSelfTestFailure() +{ + g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_FAILED; +} + +PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus() +{ + return g_powerUpSelfTestStatus; +} + +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 +// One variable for all threads for compatibility. Previously this +// was a ThreadLocalStorage variable, which is per-thread. Also see +// https://github.com/weidai11/cryptopp/issues/208 +static bool s_inProgress = false; +#endif + +bool PowerUpSelfTestInProgressOnThisThread() +{ +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 + return s_inProgress; +#else + return false; +#endif +} + +void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress) +{ +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 + s_inProgress = inProgress; +#else + CRYPTOPP_UNUSED(inProgress); +#endif +} + +void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor) +{ +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 + EncryptionPairwiseConsistencyTest(encryptor, decryptor); +#else + CRYPTOPP_UNUSED(encryptor), CRYPTOPP_UNUSED(decryptor); +#endif +} + +void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier) +{ +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 + SignaturePairwiseConsistencyTest(signer, verifier); +#else + CRYPTOPP_UNUSED(signer), CRYPTOPP_UNUSED(verifier); +#endif +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/fips140.h b/external/ours/library/crypto/src/shared/original/fips140.h new file mode 100755 index 000000000..499e86801 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 Algortihm 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 Algortihm 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 Algortihm 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 offest 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/external/ours/library/crypto/src/shared/original/fipsalgt.cpp b/external/ours/library/crypto/src/shared/original/fipsalgt.cpp new file mode 100755 index 000000000..db0fc5384 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/fipsalgt.cpp @@ -0,0 +1,1293 @@ +// fipsalgt.cpp - originally written and placed in the public domain by Wei Dai + +// This file implements the various algorithm tests needed to pass FIPS 140 validation. +// They're preserved here (commented out) in case Crypto++ needs to be revalidated. + +#if 0 +#ifndef CRYPTOPP_IMPORTS +#define CRYPTOPP_DEFAULT_NO_DLL +#endif + +#include "dll.h" +#include "cryptlib.h" +#include "smartptr.h" +#include "filters.h" +#include "oids.h" + +USING_NAMESPACE(CryptoPP) + +class LineBreakParser : public AutoSignaling > +{ +public: + LineBreakParser(BufferedTransformation *attachment=NULLPTR, byte lineEnd='\n') + : m_lineEnd(lineEnd) {Detach(attachment);} + + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) + { + if (!blocking) + throw BlockingInputOnly("LineBreakParser"); + + unsigned int i, last = 0; + for (i=0; iPut2(begin+last, i-last, GetAutoSignalPropagation(), blocking); + last = i+1; + } + } + if (last != i) + AttachedTransformation()->Put2(begin+last, i-last, 0, blocking); + + if (messageEnd && GetAutoSignalPropagation()) + { + AttachedTransformation()->MessageEnd(GetAutoSignalPropagation()-1, blocking); + AttachedTransformation()->MessageSeriesEnd(GetAutoSignalPropagation()-1, blocking); + } + + return 0; + } + +private: + byte m_lineEnd; +}; + +class TestDataParser : public Unflushable +{ +public: + enum DataType {OTHER, COUNT, KEY_T, IV, INPUT, OUTPUT}; + + TestDataParser(std::string algorithm, std::string test, std::string mode, unsigned int feedbackSize, bool encrypt, BufferedTransformation *attachment) + : m_algorithm(algorithm), m_test(test), m_mode(mode), m_feedbackSize(feedbackSize) + , m_firstLine(true), m_blankLineTransition(0) + { + Detach(attachment); + + m_typeToName[COUNT] = "COUNT"; + + m_nameToType["COUNT"] = COUNT; + m_nameToType["KEY"] = KEY_T; + m_nameToType["KEYs"] = KEY_T; + m_nameToType["key"] = KEY_T; + m_nameToType["Key"] = KEY_T; + m_nameToType["IV"] = IV; + m_nameToType["IV1"] = IV; + m_nameToType["CV"] = IV; + m_nameToType["CV1"] = IV; + m_nameToType["IB"] = IV; + m_nameToType["TEXT"] = INPUT; + m_nameToType["RESULT"] = OUTPUT; + m_nameToType["Msg"] = INPUT; + m_nameToType["Seed"] = INPUT; + m_nameToType["V"] = INPUT; + m_nameToType["DT"] = IV; + SetEncrypt(encrypt); + + if (m_algorithm == "DSA" || m_algorithm == "ECDSA") + { + if (m_test == "PKV") + m_trigger = "Qy"; + else if (m_test == "KeyPair") + m_trigger = "N"; + else if (m_test == "SigGen") + m_trigger = "Msg"; + else if (m_test == "SigVer") + m_trigger = "S"; + else if (m_test == "PQGGen") + m_trigger = "N"; + else if (m_test == "PQGVer") + m_trigger = "H"; + } + else if (m_algorithm == "HMAC") + m_trigger = "Msg"; + else if (m_algorithm == "SHA") + m_trigger = (m_test == "MONTE") ? "Seed" : "Msg"; + else if (m_algorithm == "RNG") + m_trigger = "V"; + else if (m_algorithm == "RSA") + m_trigger = (m_test == "Ver") ? "S" : "Msg"; + } + + void SetEncrypt(bool encrypt) + { + m_encrypt = encrypt; + if (encrypt) + { + m_nameToType["PLAINTEXT"] = INPUT; + m_nameToType["CIPHERTEXT"] = OUTPUT; + m_nameToType["PT"] = INPUT; + m_nameToType["CT"] = OUTPUT; + } + else + { + m_nameToType["PLAINTEXT"] = OUTPUT; + m_nameToType["CIPHERTEXT"] = INPUT; + m_nameToType["PT"] = OUTPUT; + m_nameToType["CT"] = INPUT; + } + + if (m_algorithm == "AES" || m_algorithm == "TDES") + { + if (encrypt) + { + m_trigger = "PLAINTEXT"; + m_typeToName[OUTPUT] = "CIPHERTEXT"; + } + else + { + m_trigger = "CIPHERTEXT"; + m_typeToName[OUTPUT] = "PLAINTEXT"; + } + m_count = 0; + } + } + +protected: + void OutputData(std::string &output, const std::string &key, const std::string &data) + { + output += key; + output += "= "; + output += data; + output += "\n"; + } + + void OutputData(std::string &output, const std::string &key, int data) + { + OutputData(output, key, IntToString(data)); + } + + void OutputData(std::string &output, const std::string &key, const SecByteBlock &data) + { + output += key; + output += "= "; + HexEncoder(new StringSink(output), false).Put(data, data.size()); + output += "\n"; + } + + void OutputData(std::string &output, const std::string &key, const Integer &data, int size=-1) + { + SecByteBlock s(size < 0 ? data.MinEncodedSize() : size); + data.Encode(s, s.size()); + OutputData(output, key, s); + } + + void OutputData(std::string &output, const std::string &key, const PolynomialMod2 &data, int size=-1) + { + SecByteBlock s(size < 0 ? data.MinEncodedSize() : size); + data.Encode(s, s.size()); + OutputData(output, key, s); + } + + void OutputData(std::string &output, DataType t, const std::string &data) + { + if (m_algorithm == "SKIPJACK") + { + if (m_test == "KAT") + { + if (t == OUTPUT) + output = m_line + data + "\n"; + } + else + { + if (t != COUNT) + { + output += m_typeToName[t]; + output += "="; + } + output += data; + output += t == OUTPUT ? "\n" : " "; + } + } + else if (m_algorithm == "TDES" && t == KEY_T && m_typeToName[KEY_T].empty()) + { + output += "KEY1 = "; + output += data.substr(0, 16); + output += "\nKEY2 = "; + output += data.size() > 16 ? data.substr(16, 16) : data.substr(0, 16); + output += "\nKEY3 = "; + output += data.size() > 32 ? data.substr(32, 16) : data.substr(0, 16); + output += "\n"; + } + else + { + output += m_typeToName[t]; + output += " = "; + output += data; + output += "\n"; + } + } + + void OutputData(std::string &output, DataType t, int i) + { + OutputData(output, t, IntToString(i)); + } + + void OutputData(std::string &output, DataType t, const SecByteBlock &data) + { + std::string hexData; + StringSource(data.begin(), data.size(), true, new HexEncoder(new StringSink(hexData), false)); + OutputData(output, t, hexData); + } + + void OutputGivenData(std::string &output, DataType t, bool optional = false) + { + if (m_data.find(m_typeToName[t]) == m_data.end()) + { + if (optional) + return; + throw Exception(Exception::OTHER_ERROR, "TestDataParser: key not found: " + m_typeToName[t]); + } + + OutputData(output, t, m_data[m_typeToName[t]]); + } + + template + BlockCipher * NewBT(T *) + { + if (!m_encrypt && (m_mode == "ECB" || m_mode == "CBC")) + return new typename T::Decryption; + else + return new typename T::Encryption; + } + + template + SymmetricCipher * NewMode(T *, BlockCipher &bt, const byte *iv) + { + if (!m_encrypt) + return new typename T::Decryption(bt, iv, m_feedbackSize/8); + else + return new typename T::Encryption(bt, iv, m_feedbackSize/8); + } + + static inline void Xor(SecByteBlock &z, const SecByteBlock &x, const SecByteBlock &y) + { + CRYPTOPP_ASSERT(x.size() == y.size()); + z.resize(x.size()); + xorbuf(z, x, y, x.size()); + } + + SecByteBlock UpdateKey(SecByteBlock key, const SecByteBlock *text) + { + unsigned int innerCount = (m_algorithm == "AES") ? 1000 : 10000; + int keySize = key.size(), blockSize = text[0].size(); + SecByteBlock x(keySize); + for (int k=0; k + void EC_KeyPair(string &output, int n, const OID &oid) + { + DL_GroupParameters_EC params(oid); + for (int i=0; i priv; + DL_PublicKey_EC pub; + priv.Initialize(m_rng, params); + priv.MakePublicKey(pub); + + OutputData(output, "d ", priv.GetPrivateExponent()); + OutputData(output, "Qx ", pub.GetPublicElement().x, params.GetCurve().GetField().MaxElementByteLength()); + OutputData(output, "Qy ", pub.GetPublicElement().y, params.GetCurve().GetField().MaxElementByteLength()); + } + } + + template + void EC_SigGen(string &output, const OID &oid) + { + DL_GroupParameters_EC params(oid); + typename ECDSA::PrivateKey priv; + typename ECDSA::PublicKey pub; + priv.Initialize(m_rng, params); + priv.MakePublicKey(pub); + + typename ECDSA::Signer signer(priv); + SecByteBlock sig(signer.SignatureLength()); + StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size())))); + SecByteBlock R(sig, sig.size()/2), S(sig+sig.size()/2, sig.size()/2); + + OutputData(output, "Qx ", pub.GetPublicElement().x, params.GetCurve().GetField().MaxElementByteLength()); + OutputData(output, "Qy ", pub.GetPublicElement().y, params.GetCurve().GetField().MaxElementByteLength()); + OutputData(output, "R ", R); + OutputData(output, "S ", S); + } + + template + void EC_SigVer(string &output, const OID &oid) + { + SecByteBlock x(DecodeHex(m_data["Qx"])); + SecByteBlock y(DecodeHex(m_data["Qy"])); + Integer r((m_data["R"]+"h").c_str()); + Integer s((m_data["S"]+"h").c_str()); + + typename EC::FieldElement Qx(x, x.size()); + typename EC::FieldElement Qy(y, y.size()); + typename EC::Element Q(Qx, Qy); + + DL_GroupParameters_EC params(oid); + typename ECDSA::PublicKey pub; + pub.Initialize(params, Q); + typename ECDSA::Verifier verifier(pub); + + SecByteBlock sig(verifier.SignatureLength()); + r.Encode(sig, sig.size()/2); + s.Encode(sig+sig.size()/2, sig.size()/2); + + SignatureVerificationFilter filter(verifier); + filter.Put(sig, sig.size()); + StringSource(m_data["Msg"], true, new HexDecoder(new Redirector(filter, Redirector::DATA_ONLY))); + filter.MessageEnd(); + byte b; + filter.Get(b); + OutputData(output, "Result ", b ? "P" : "F"); + } + + template + static bool EC_PKV(RandomNumberGenerator &rng, const SecByteBlock &x, const SecByteBlock &y, const OID &oid) + { + typename EC::FieldElement Qx(x, x.size()); + typename EC::FieldElement Qy(y, y.size()); + typename EC::Element Q(Qx, Qy); + + DL_GroupParameters_EC params(oid); + typename ECDSA::PublicKey pub; + pub.Initialize(params, Q); + return pub.Validate(rng, 3); + } + + template + Result * CreateRSA2(const std::string &standard) + { + if (typeid(Result) == typeid(PK_Verifier)) + { + if (standard == "R") + return (Result *) new typename RSASS_ISO::Verifier; + else if (standard == "P") + return (Result *) new typename RSASS::Verifier; + else if (standard == "1") + return (Result *) new typename RSASS::Verifier; + } + else if (typeid(Result) == typeid(PK_Signer)) + { + if (standard == "R") + return (Result *) new typename RSASS_ISO::Signer; + else if (standard == "P") + return (Result *) new typename RSASS::Signer; + else if (standard == "1") + return (Result *) new typename RSASS::Signer; + } + + return NULLPTR; + } + + template + Result * CreateRSA(const std::string &standard, const std::string &hash) + { + if (hash == "1") + return CreateRSA2(standard); + else if (hash == "224") + return CreateRSA2(standard); + else if (hash == "256") + return CreateRSA2(standard); + else if (hash == "384") + return CreateRSA2(standard); + else if (hash == "512") + return CreateRSA2(standard); + else + return NULLPTR; + } + + virtual void DoTest() + { + std::string output; + + if (m_algorithm == "DSA") + { + if (m_test == "KeyPair") + { + DL_GroupParameters_DSA pqg; + int modLen = atol(m_bracketString.substr(6).c_str()); + pqg.GenerateRandomWithKeySize(m_rng, modLen); + + OutputData(output, "P ", pqg.GetModulus()); + OutputData(output, "Q ", pqg.GetSubgroupOrder()); + OutputData(output, "G ", pqg.GetSubgroupGenerator()); + + int n = atol(m_data["N"].c_str()); + for (int i=0; iPut((byte *)output.data(), output.size()); + output.resize(0); + } + } + else if (m_test == "PQGGen") + { + int n = atol(m_data["N"].c_str()); + for (int i=0; iPut((byte *)output.data(), output.size()); + output.resize(0); + } + } + else if (m_test == "SigGen") + { + std::string &encodedKey = m_data["PrivKey"]; + int modLen = atol(m_bracketString.substr(6).c_str()); + DSA::PrivateKey priv; + + if (!encodedKey.empty()) + { + StringStore s(encodedKey); + priv.BERDecode(s); + if (priv.GetGroupParameters().GetModulus().BitCount() != modLen) + encodedKey.clear(); + } + + if (encodedKey.empty()) + { + priv.Initialize(m_rng, modLen); + StringSink s(encodedKey); + priv.DEREncode(s); + OutputData(output, "P ", priv.GetGroupParameters().GetModulus()); + OutputData(output, "Q ", priv.GetGroupParameters().GetSubgroupOrder()); + OutputData(output, "G ", priv.GetGroupParameters().GetSubgroupGenerator()); + } + + DSA::Signer signer(priv); + DSA::Verifier pub(signer); + OutputData(output, "Msg ", m_data["Msg"]); + OutputData(output, "Y ", pub.GetKey().GetPublicElement()); + + SecByteBlock sig(signer.SignatureLength()); + StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size())))); + SecByteBlock R(sig, sig.size()/2), S(sig+sig.size()/2, sig.size()/2); + OutputData(output, "R ", R); + OutputData(output, "S ", S); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + else if (m_test == "SigVer") + { + Integer p((m_data["P"] + "h").c_str()); + Integer q((m_data["Q"] + "h").c_str()); + Integer g((m_data["G"] + "h").c_str()); + Integer y((m_data["Y"] + "h").c_str()); + DSA::Verifier verifier(p, q, g, y); + + HexDecoder filter(new SignatureVerificationFilter(verifier)); + StringSource(m_data["R"], true, new Redirector(filter, Redirector::DATA_ONLY)); + StringSource(m_data["S"], true, new Redirector(filter, Redirector::DATA_ONLY)); + StringSource(m_data["Msg"], true, new Redirector(filter, Redirector::DATA_ONLY)); + filter.MessageEnd(); + byte b; + filter.Get(b); + OutputData(output, "Result ", b ? "P" : "F"); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + else if (m_test == "PQGVer") + { + Integer p((m_data["P"] + "h").c_str()); + Integer q((m_data["Q"] + "h").c_str()); + Integer g((m_data["G"] + "h").c_str()); + Integer h((m_data["H"] + "h").c_str()); + int c = atol(m_data["c"].c_str()); + SecByteBlock seed(m_data["Seed"].size()/2); + StringSource(m_data["Seed"], true, new HexDecoder(new ArraySink(seed, seed.size()))); + + Integer p1, q1; + bool result = DSA::GeneratePrimes(seed, seed.size()*8, c, p1, 1024, q1, true); + result = result && (p1 == p && q1 == q); + result = result && g == a_exp_b_mod_c(h, (p-1)/q, p); + + OutputData(output, "Result ", result ? "P" : "F"); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + + return; + } + + if (m_algorithm == "ECDSA") + { + std::map name2oid; + name2oid["P-192"] = ASN1::secp192r1(); + name2oid["P-224"] = ASN1::secp224r1(); + name2oid["P-256"] = ASN1::secp256r1(); + name2oid["P-384"] = ASN1::secp384r1(); + name2oid["P-521"] = ASN1::secp521r1(); + name2oid["K-163"] = ASN1::sect163k1(); + name2oid["K-233"] = ASN1::sect233k1(); + name2oid["K-283"] = ASN1::sect283k1(); + name2oid["K-409"] = ASN1::sect409k1(); + name2oid["K-571"] = ASN1::sect571k1(); + name2oid["B-163"] = ASN1::sect163r2(); + name2oid["B-233"] = ASN1::sect233r1(); + name2oid["B-283"] = ASN1::sect283r1(); + name2oid["B-409"] = ASN1::sect409r1(); + name2oid["B-571"] = ASN1::sect571r1(); + + if (m_test == "PKV") + { + bool pass; + if (m_bracketString[0] == 'P') + pass = EC_PKV(m_rng, DecodeHex(m_data["Qx"]), DecodeHex(m_data["Qy"]), name2oid[m_bracketString]); + else + pass = EC_PKV(m_rng, DecodeHex(m_data["Qx"]), DecodeHex(m_data["Qy"]), name2oid[m_bracketString]); + + OutputData(output, "Result ", pass ? "P" : "F"); + } + else if (m_test == "KeyPair") + { + if (m_bracketString[0] == 'P') + EC_KeyPair(output, atol(m_data["N"].c_str()), name2oid[m_bracketString]); + else + EC_KeyPair(output, atol(m_data["N"].c_str()), name2oid[m_bracketString]); + } + else if (m_test == "SigGen") + { + if (m_bracketString[0] == 'P') + EC_SigGen(output, name2oid[m_bracketString]); + else + EC_SigGen(output, name2oid[m_bracketString]); + } + else if (m_test == "SigVer") + { + if (m_bracketString[0] == 'P') + EC_SigVer(output, name2oid[m_bracketString]); + else + EC_SigVer(output, name2oid[m_bracketString]); + } + + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + return; + } + + if (m_algorithm == "RSA") + { + std::string shaAlg = m_data["SHAAlg"].substr(3); + + if (m_test == "Ver") + { + Integer n((m_data["n"] + "h").c_str()); + Integer e((m_data["e"] + "h").c_str()); + RSA::PublicKey pub; + pub.Initialize(n, e); + + member_ptr pV(CreateRSA(m_mode, shaAlg)); + pV->AccessMaterial().AssignFrom(pub); + + HexDecoder filter(new SignatureVerificationFilter(*pV)); + for (unsigned int i=m_data["S"].size(); iSignatureLength()*2; i++) + filter.Put('0'); + StringSource(m_data["S"], true, new Redirector(filter, Redirector::DATA_ONLY)); + StringSource(m_data["Msg"], true, new Redirector(filter, Redirector::DATA_ONLY)); + filter.MessageEnd(); + byte b; + filter.Get(b); + OutputData(output, "Result ", b ? "P" : "F"); + } + else + { + CRYPTOPP_ASSERT(m_test == "Gen"); + int modLen = atol(m_bracketString.substr(6).c_str()); + std::string &encodedKey = m_data["PrivKey"]; + RSA::PrivateKey priv; + + if (!encodedKey.empty()) + { + StringStore s(encodedKey); + priv.BERDecode(s); + if (priv.GetModulus().BitCount() != modLen) + encodedKey.clear(); + } + + if (encodedKey.empty()) + { + priv.Initialize(m_rng, modLen); + StringSink s(encodedKey); + priv.DEREncode(s); + OutputData(output, "n ", priv.GetModulus()); + OutputData(output, "e ", priv.GetPublicExponent(), modLen/8); + } + + member_ptr pS(CreateRSA(m_mode, shaAlg)); + pS->AccessMaterial().AssignFrom(priv); + + SecByteBlock sig(pS->SignatureLength()); + StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, *pS, new ArraySink(sig, sig.size())))); + OutputData(output, "SHAAlg ", m_data["SHAAlg"]); + OutputData(output, "Msg ", m_data["Msg"]); + OutputData(output, "S ", sig); + } + + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + return; + } + + if (m_algorithm == "SHA") + { + member_ptr pHF; + + if (m_mode == "1") + pHF.reset(new SHA1); + else if (m_mode == "224") + pHF.reset(new SHA224); + else if (m_mode == "256") + pHF.reset(new SHA256); + else if (m_mode == "384") + pHF.reset(new SHA384); + else if (m_mode == "512") + pHF.reset(new SHA512); + + if (m_test == "MONTE") + { + SecByteBlock seed = m_data2[INPUT]; + SecByteBlock MD[1003]; + int i,j; + + for (j=0; j<100; j++) + { + MD[0] = MD[1] = MD[2] = seed; + for (i=3; i<1003; i++) + { + SecByteBlock Mi = MD[i-3] + MD[i-2] + MD[i-1]; + MD[i].resize(pHF->DigestSize()); + pHF->CalculateDigest(MD[i], Mi, Mi.size()); + } + seed = MD[1002]; + OutputData(output, "COUNT ", j); + OutputData(output, "MD ", seed); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + } + else + { + SecByteBlock tag(pHF->DigestSize()); + SecByteBlock &msg(m_data2[INPUT]); + int len = atol(m_data["Len"].c_str()); + StringSource(msg.begin(), len/8, true, new HashFilter(*pHF, new ArraySink(tag, tag.size()))); + OutputData(output, "MD ", tag); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + return; + } + + SecByteBlock &key = m_data2[KEY_T]; + + if (m_algorithm == "TDES") + { + if (!m_data["KEY1"].empty()) + { + const std::string keys[3] = {m_data["KEY1"], m_data["KEY2"], m_data["KEY3"]}; + key.resize(24); + HexDecoder hexDec(new ArraySink(key, key.size())); + for (int i=0; i<3; i++) + hexDec.Put((byte *)keys[i].data(), keys[i].size()); + + if (keys[0] == keys[2]) + { + if (keys[0] == keys[1]) + key.resize(8); + else + key.resize(16); + } + else + key.resize(24); + } + } + + if (m_algorithm == "RNG") + { + key.resize(24); + StringSource(m_data["Key1"] + m_data["Key2"] + m_data["Key3"], true, new HexDecoder(new ArraySink(key, key.size()))); + + SecByteBlock seed(m_data2[INPUT]), dt(m_data2[IV]), r(8); + X917RNG rng(new DES_EDE3::Encryption(key, key.size()), seed, dt); + + if (m_test == "MCT") + { + for (int i=0; i<10000; i++) + rng.GenerateBlock(r, r.size()); + } + else + { + rng.GenerateBlock(r, r.size()); + } + + OutputData(output, "R ", r); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + return; + } + + if (m_algorithm == "HMAC") + { + member_ptr pMAC; + + if (m_bracketString == "L=20") + pMAC.reset(new HMAC); + else if (m_bracketString == "L=28") + pMAC.reset(new HMAC); + else if (m_bracketString == "L=32") + pMAC.reset(new HMAC); + else if (m_bracketString == "L=48") + pMAC.reset(new HMAC); + else if (m_bracketString == "L=64") + pMAC.reset(new HMAC); + else + throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected HMAC bracket string: " + m_bracketString); + + pMAC->SetKey(key, key.size()); + int Tlen = atol(m_data["Tlen"].c_str()); + SecByteBlock tag(Tlen); + StringSource(m_data["Msg"], true, new HexDecoder(new HashFilter(*pMAC, new ArraySink(tag, Tlen), false, Tlen))); + OutputData(output, "Mac ", tag); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + return; + } + + member_ptr pBT; + if (m_algorithm == "DES") + pBT.reset(NewBT((DES*)0)); + else if (m_algorithm == "TDES") + { + if (key.size() == 8) + pBT.reset(NewBT((DES*)0)); + else if (key.size() == 16) + pBT.reset(NewBT((DES_EDE2*)0)); + else + pBT.reset(NewBT((DES_EDE3*)0)); + } + else if (m_algorithm == "SKIPJACK") + pBT.reset(NewBT((SKIPJACK*)0)); + else if (m_algorithm == "AES") + pBT.reset(NewBT((AES*)0)); + else + throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected algorithm: " + m_algorithm); + + if (!pBT->IsValidKeyLength(key.size())) + key.CleanNew(pBT->DefaultKeyLength()); // for Scbcvrct + pBT->SetKey(key.data(), key.size()); + + SecByteBlock &iv = m_data2[IV]; + if (iv.empty()) + iv.CleanNew(pBT->BlockSize()); + + member_ptr pCipher; + unsigned int K = m_feedbackSize; + + if (m_mode == "ECB") + pCipher.reset(NewMode((ECB_Mode_ExternalCipher*)0, *pBT, iv)); + else if (m_mode == "CBC") + pCipher.reset(NewMode((CBC_Mode_ExternalCipher*)0, *pBT, iv)); + else if (m_mode == "CFB") + pCipher.reset(NewMode((CFB_Mode_ExternalCipher*)0, *pBT, iv)); + else if (m_mode == "OFB") + pCipher.reset(NewMode((OFB_Mode_ExternalCipher*)0, *pBT, iv)); + else + throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode); + + bool encrypt = m_encrypt; + + if (m_test == "MONTE") + { + SecByteBlock KEY[401]; + KEY[0] = key; + int keySize = key.size(); + int blockSize = pBT->BlockSize(); + + std::vector IB(10001), OB(10001), PT(10001), CT(10001), RESULT(10001), TXT(10001), CV(10001); + PT[0] = GetData("PLAINTEXT"); + CT[0] = GetData("CIPHERTEXT"); + CV[0] = IB[0] = iv; + TXT[0] = GetData("TEXT"); + + int outerCount = (m_algorithm == "AES") ? 100 : 400; + int innerCount = (m_algorithm == "AES") ? 1000 : 10000; + + for (int i=0; iSetKey(KEY[i], keySize); + + for (int j=0; jProcessBlock(IB[j], CT[j]); + PT[j+1] = CT[j]; + } + else + { + IB[j] = CT[j]; + PT[j].resize(blockSize); + pBT->ProcessBlock(IB[j], PT[j]); + CT[j+1] = PT[j]; + } + } + else if (m_mode == "OFB") + { + OB[j].resize(blockSize); + pBT->ProcessBlock(IB[j], OB[j]); + Xor(RESULT[j], OB[j], TXT[j]); + TXT[j+1] = IB[j]; + IB[j+1] = OB[j]; + } + else if (m_mode == "CBC") + { + if (encrypt) + { + Xor(IB[j], PT[j], CV[j]); + CT[j].resize(blockSize); + pBT->ProcessBlock(IB[j], CT[j]); + PT[j+1] = CV[j]; + CV[j+1] = CT[j]; + } + else + { + IB[j] = CT[j]; + OB[j].resize(blockSize); + pBT->ProcessBlock(IB[j], OB[j]); + Xor(PT[j], OB[j], CV[j]); + CV[j+1] = CT[j]; + CT[j+1] = PT[j]; + } + } + else if (m_mode == "CFB") + { + if (encrypt) + { + OB[j].resize(blockSize); + pBT->ProcessBlock(IB[j], OB[j]); + AssignLeftMostBits(CT[j], OB[j], K); + Xor(CT[j], CT[j], PT[j]); + AssignLeftMostBits(PT[j+1], IB[j], K); + IB[j+1].resize(blockSize); + memcpy(IB[j+1], IB[j]+K/8, blockSize-K/8); + memcpy(IB[j+1]+blockSize-K/8, CT[j], K/8); + } + else + { + OB[j].resize(blockSize); + pBT->ProcessBlock(IB[j], OB[j]); + AssignLeftMostBits(PT[j], OB[j], K); + Xor(PT[j], PT[j], CT[j]); + IB[j+1].resize(blockSize); + memcpy(IB[j+1], IB[j]+K/8, blockSize-K/8); + memcpy(IB[j+1]+blockSize-K/8, CT[j], K/8); + AssignLeftMostBits(CT[j+1], OB[j], K); + } + } + else + throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode); + } + + OutputData(output, COUNT, IntToString(i)); + OutputData(output, KEY_T, KEY[i]); + if (m_mode == "CBC") + OutputData(output, IV, CV[0]); + if (m_mode == "OFB" || m_mode == "CFB") + OutputData(output, IV, IB[0]); + if (m_mode == "ECB" || m_mode == "CBC" || m_mode == "CFB") + { + if (encrypt) + { + OutputData(output, INPUT, PT[0]); + OutputData(output, OUTPUT, CT[innerCount-1]); + KEY[i+1] = UpdateKey(KEY[i], &CT[0]); + } + else + { + OutputData(output, INPUT, CT[0]); + OutputData(output, OUTPUT, PT[innerCount-1]); + KEY[i+1] = UpdateKey(KEY[i], &PT[0]); + } + PT[0] = PT[innerCount]; + IB[0] = IB[innerCount]; + CV[0] = CV[innerCount]; + CT[0] = CT[innerCount]; + } + else if (m_mode == "OFB") + { + OutputData(output, INPUT, TXT[0]); + OutputData(output, OUTPUT, RESULT[innerCount-1]); + KEY[i+1] = UpdateKey(KEY[i], &RESULT[0]); + Xor(TXT[0], TXT[0], IB[innerCount-1]); + IB[0] = OB[innerCount-1]; + } + output += "\n"; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + } + else if (m_test == "MCT") + { + SecByteBlock KEY[101]; + KEY[0] = key; + int keySize = key.size(); + int blockSize = pBT->BlockSize(); + + SecByteBlock ivs[101], inputs[1001], outputs[1001]; + ivs[0] = iv; + inputs[0] = m_data2[INPUT]; + + for (int i=0; i<100; i++) + { + pCipher->SetKey(KEY[i], keySize, MakeParameters(Name::IV(), (const byte *)ivs[i])(Name::FeedbackSize(), (int)K/8, false)); + + for (int j=0; j<1000; j++) + { + outputs[j] = inputs[j]; + pCipher->ProcessString(outputs[j], outputs[j].size()); + if (K==8 && m_mode == "CFB") + { + if (j<16) + inputs[j+1].Assign(ivs[i]+j, 1); + else + inputs[j+1] = outputs[j-16]; + } + else if (m_mode == "ECB") + inputs[j+1] = outputs[j]; + else if (j == 0) + inputs[j+1] = ivs[i]; + else + inputs[j+1] = outputs[j-1]; + } + + if (m_algorithm == "AES") + OutputData(output, COUNT, m_count++); + OutputData(output, KEY_T, KEY[i]); + if (m_mode != "ECB") + OutputData(output, IV, ivs[i]); + OutputData(output, INPUT, inputs[0]); + OutputData(output, OUTPUT, outputs[999]); + output += "\n"; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + + KEY[i+1] = UpdateKey(KEY[i], outputs); + ivs[i+1].CleanNew(pCipher->IVSize()); + ivs[i+1] = UpdateKey(ivs[i+1], outputs); + if (K==8 && m_mode == "CFB") + inputs[0] = outputs[999-16]; + else if (m_mode == "ECB") + inputs[0] = outputs[999]; + else + inputs[0] = outputs[998]; + } + } + else + { + CRYPTOPP_ASSERT(m_test == "KAT"); + + SecByteBlock &input = m_data2[INPUT]; + SecByteBlock result(input.size()); + member_ptr pFilter(new StreamTransformationFilter(*pCipher, new ArraySink(result, result.size()), StreamTransformationFilter::NO_PADDING)); + StringSource(input.data(), input.size(), true, pFilter.release()); + + OutputGivenData(output, COUNT, true); + OutputData(output, KEY_T, key); + OutputGivenData(output, IV, true); + OutputGivenData(output, INPUT); + OutputData(output, OUTPUT, result); + output += "\n"; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + } + } + + std::vector Tokenize(const std::string &line) + { + std::vector result; + std::string s; + for (unsigned int i=0; i") + { + CRYPTOPP_ASSERT(m_test == "sha"); + m_bracketString = m_line.substr(2, m_line.size()-4); + m_line = m_line.substr(0, 13) + "Hashes") + copyLine = true; + + if (m_line == "Put((byte *)m_line.data(), m_line.size(), blocking); + return false; + } + + std::vector tokens = Tokenize(m_line); + + if (m_algorithm == "DSA" && m_test == "sha") + { + for (unsigned int i = 0; i < tokens.size(); i++) + { + if (tokens[i] == "^") + DoTest(); + else if (tokens[i] != "") + m_compactString.push_back(atol(tokens[i].c_str())); + } + } + else + { + if (!m_line.empty() && ((m_algorithm == "RSA" && m_test != "Gen") || m_algorithm == "RNG" || m_algorithm == "HMAC" || m_algorithm == "SHA" || (m_algorithm == "ECDSA" && m_test != "KeyPair") || (m_algorithm == "DSA" && (m_test == "PQGVer" || m_test == "SigVer")))) + { + // copy input to output + std::string output = m_line + '\n'; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + } + + for (unsigned int i = 0; i < tokens.size(); i++) + { + if (m_firstLine && m_algorithm != "DSA") + { + if (tokens[i] == "Encrypt" || tokens[i] == "OFB") + SetEncrypt(true); + else if (tokens[i] == "Decrypt") + SetEncrypt(false); + else if (tokens[i] == "Modes") + m_test = "MONTE"; + } + else + { + if (tokens[i] != "=") + continue; + + if (i == 0) + throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected data: " + m_line); + + const std::string &key = tokens[i-1]; + std::string &data = m_data[key]; + data = (tokens.size() > i+1) ? tokens[i+1] : ""; + DataType t = m_nameToType[key]; + m_typeToName[t] = key; + m_data2[t] = DecodeHex(data); + + if (key == m_trigger || (t == OUTPUT && !m_data2[INPUT].empty() && !isspace(m_line[0]))) + DoTest(); + } + } + } + + m_firstLine = false; + + return false; + } + + inline const SecByteBlock & GetData(const std::string &key) + { + return m_data2[m_nameToType[key]]; + } + + static SecByteBlock DecodeHex(const std::string &data) + { + SecByteBlock data2(data.size() / 2); + StringSource(data, true, new HexDecoder(new ArraySink(data2, data2.size()))); + return data2; + } + + std::string m_algorithm, m_test, m_mode, m_line, m_bracketString, m_trigger; + unsigned int m_feedbackSize, m_blankLineTransition; + bool m_encrypt, m_firstLine; + + typedef std::map NameToTypeMap; + NameToTypeMap m_nameToType; + typedef std::map TypeToNameMap; + TypeToNameMap m_typeToName; + + typedef std::map Map; + Map m_data; // raw data + typedef std::map Map2; + Map2 m_data2; + int m_count; + + AutoSeededX917RNG m_rng; + std::vector m_compactString; +}; + +int FIPS_140_AlgorithmTest(int argc, char **argv) +{ + argc--; + argv++; + + std::string algorithm = argv[1]; + std::string pathname = argv[2]; + unsigned int i = pathname.find_last_of("\\/"); + std::string filename = pathname.substr(i == std::string::npos ? 0 : i+1); + std::string dirname = pathname.substr(0, i); + + if (algorithm == "auto") + { + string algTable[] = {"AES", "ECDSA", "DSA", "HMAC", "RNG", "RSA", "TDES", "SKIPJACK", "SHA"}; // order is important here + for (i=0; i 3) + { + std::string outDir = argv[3]; + + if (outDir == "auto") + { + if (dirname.substr(dirname.size()-3) == "req") + outDir = dirname.substr(0, dirname.size()-3) + "resp"; + } + + if (*outDir.rbegin() != '\\' && *outDir.rbegin() != '/') + outDir += '/'; + std::string outPathname = outDir + filename.substr(0, filename.size() - 3) + "rsp"; + pSink = new FileSink(outPathname.c_str(), false); + } + else + pSink = new FileSink(cout); + + FileSource(pathname.c_str(), true, new LineBreakParser(new TestDataParser(algorithm, test, mode, feedbackSize, encrypt, pSink)), false); + } + catch (...) + { + cout << "file: " << filename << endl; + throw; + } + return 0; +} + +extern int (*AdhocTest)(int argc, char *argv[]); +static int s_i = (AdhocTest = &FIPS_140_AlgorithmTest, 0); +#endif diff --git a/external/ours/library/crypto/src/shared/original/fipstest.cpp b/external/ours/library/crypto/src/shared/original/fipstest.cpp new file mode 100755 index 000000000..3e609f88f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/fipstest.cpp @@ -0,0 +1,652 @@ +// fipstest.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS + +#define CRYPTOPP_DEFAULT_NO_DLL +#include "dll.h" +#include "cryptlib.h" +#include "filters.h" +#include "smartptr.h" +#include "pkcspad.h" +#include "misc.h" + +// Simply disable CRYPTOPP_WIN32_AVAILABLE for Windows Phone and Windows Store apps +#ifdef CRYPTOPP_WIN32_AVAILABLE +# if defined(WINAPI_FAMILY) +# if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) +# undef CRYPTOPP_WIN32_AVAILABLE +# endif +# endif +#endif + +#ifdef CRYPTOPP_WIN32_AVAILABLE +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif + +#include + +#if defined(_MSC_VER) && _MSC_VER >= 1400 +# ifdef _M_IX86 +# define _CRT_DEBUGGER_HOOK _crt_debugger_hook +# else +# define _CRT_DEBUGGER_HOOK __crt_debugger_hook +# endif +# if _MSC_VER < 1900 +extern "C" {_CRTIMP void __cdecl _CRT_DEBUGGER_HOOK(int);} +# else +extern "C" {void __cdecl _CRT_DEBUGGER_HOOK(int); } +# endif +#endif +#endif // CRYPTOPP_WIN32_AVAILABLE + +#include +#include + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4100 4702) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +extern PowerUpSelfTestStatus g_powerUpSelfTestStatus; +SecByteBlock g_actualMac; +unsigned long g_macFileLocation = 0; + +// $ grep -iIR baseaddress *.*proj +// cryptdll.vcxproj: 0x42900000 +// cryptdll.vcxproj: 0x42900000 +// cryptdll.vcxproj: 0x42900000 +// cryptdll.vcxproj: 0x42900000 +const void* g_BaseAddressOfMAC = reinterpret_cast(0x42900000); + +// use a random dummy string here, to be searched/replaced later with the real MAC +static const byte s_moduleMac[CryptoPP::HMAC::DIGESTSIZE] = CRYPTOPP_DUMMY_DLL_MAC; +CRYPTOPP_COMPILE_ASSERT(sizeof(s_moduleMac) == CryptoPP::SHA1::DIGESTSIZE); + +#ifdef CRYPTOPP_WIN32_AVAILABLE +static HMODULE s_hModule = NULLPTR; +#endif + +const byte * CRYPTOPP_API GetActualMacAndLocation(unsigned int &macSize, unsigned int &fileLocation) +{ + macSize = (unsigned int)g_actualMac.size(); + fileLocation = g_macFileLocation; + return g_actualMac; +} + +void KnownAnswerTest(RandomNumberGenerator &rng, const char *output) +{ + EqualityComparisonFilter comparison; + + RandomNumberStore(rng, strlen(output)/2).TransferAllTo(comparison, "0"); + StringSource(output, true, new HexDecoder(new ChannelSwitch(comparison, "1"))); + + comparison.ChannelMessageSeriesEnd("0"); + comparison.ChannelMessageSeriesEnd("1"); +} + +template +void X917RNG_KnownAnswerTest( + const char *key, + const char *seed, + const char *deterministicTimeVector, + const char *output) +{ +#ifdef OS_RNG_AVAILABLE + std::string decodedKey, decodedSeed, decodedDeterministicTimeVector; + StringSource(key, true, new HexDecoder(new StringSink(decodedKey))); + StringSource(seed, true, new HexDecoder(new StringSink(decodedSeed))); + StringSource(deterministicTimeVector, true, new HexDecoder(new StringSink(decodedDeterministicTimeVector))); + + AutoSeededX917RNG rng(false, false); + rng.Reseed((const byte *)decodedKey.data(), decodedKey.size(), (const byte *)decodedSeed.data(), (const byte *)decodedDeterministicTimeVector.data()); + KnownAnswerTest(rng, output); +#else + throw 0; +#endif +} + +void KnownAnswerTest(StreamTransformation &encryption, StreamTransformation &decryption, const char *plaintext, const char *ciphertext) +{ + EqualityComparisonFilter comparison; + + StringSource(plaintext, true, new HexDecoder(new StreamTransformationFilter(encryption, new ChannelSwitch(comparison, "0"), StreamTransformationFilter::NO_PADDING))); + StringSource(ciphertext, true, new HexDecoder(new ChannelSwitch(comparison, "1"))); + + StringSource(ciphertext, true, new HexDecoder(new StreamTransformationFilter(decryption, new ChannelSwitch(comparison, "0"), StreamTransformationFilter::NO_PADDING))); + StringSource(plaintext, true, new HexDecoder(new ChannelSwitch(comparison, "1"))); + + comparison.ChannelMessageSeriesEnd("0"); + comparison.ChannelMessageSeriesEnd("1"); +} + +template +void SymmetricEncryptionKnownAnswerTest( + const char *key, + const char *hexIV, + const char *plaintext, + const char *ecb, + const char *cbc, + const char *cfb, + const char *ofb, + const char *ctr) +{ + std::string decodedKey; + StringSource(key, true, new HexDecoder(new StringSink(decodedKey))); + + typename CIPHER::Encryption encryption((const byte *)decodedKey.data(), decodedKey.size()); + typename CIPHER::Decryption decryption((const byte *)decodedKey.data(), decodedKey.size()); + + SecByteBlock iv(encryption.BlockSize()); + StringSource(hexIV, true, new HexDecoder(new ArraySink(iv, iv.size()))); + + if (ecb) + KnownAnswerTest(ECB_Mode_ExternalCipher::Encryption(encryption).Ref(), ECB_Mode_ExternalCipher::Decryption(decryption).Ref(), plaintext, ecb); + if (cbc) + KnownAnswerTest(CBC_Mode_ExternalCipher::Encryption(encryption, iv).Ref(), CBC_Mode_ExternalCipher::Decryption(decryption, iv).Ref(), plaintext, cbc); + if (cfb) + KnownAnswerTest(CFB_Mode_ExternalCipher::Encryption(encryption, iv).Ref(), CFB_Mode_ExternalCipher::Decryption(encryption, iv).Ref(), plaintext, cfb); + if (ofb) + KnownAnswerTest(OFB_Mode_ExternalCipher::Encryption(encryption, iv).Ref(), OFB_Mode_ExternalCipher::Decryption(encryption, iv).Ref(), plaintext, ofb); + if (ctr) + KnownAnswerTest(CTR_Mode_ExternalCipher::Encryption(encryption, iv).Ref(), CTR_Mode_ExternalCipher::Decryption(encryption, iv).Ref(), plaintext, ctr); +} + +void KnownAnswerTest(HashTransformation &hash, const char *message, const char *digest) +{ + EqualityComparisonFilter comparison; + StringSource(digest, true, new HexDecoder(new ChannelSwitch(comparison, "1"))); + StringSource(message, true, new HashFilter(hash, new ChannelSwitch(comparison, "0"))); + + comparison.ChannelMessageSeriesEnd("0"); + comparison.ChannelMessageSeriesEnd("1"); +} + +template +void SecureHashKnownAnswerTest(const char *message, const char *digest) +{ + HASH hash; + KnownAnswerTest(hash, message, digest); +} + +template +void MAC_KnownAnswerTest(const char *key, const char *message, const char *digest) +{ + std::string decodedKey; + StringSource(key, true, new HexDecoder(new StringSink(decodedKey))); + + MAC mac((const byte *)decodedKey.data(), decodedKey.size()); + KnownAnswerTest(mac, message, digest); +} + +template +void SignatureKnownAnswerTest(const char *key, const char *message, const char *signature) +{ + typename SCHEME::Signer signer(StringSource(key, true, new HexDecoder).Ref()); + typename SCHEME::Verifier verifier(signer); + + RandomPool rng; + EqualityComparisonFilter comparison; + + StringSource(message, true, new SignerFilter(rng, signer, new ChannelSwitch(comparison, "0"))); + StringSource(signature, true, new HexDecoder(new ChannelSwitch(comparison, "1"))); + + comparison.ChannelMessageSeriesEnd("0"); + comparison.ChannelMessageSeriesEnd("1"); + + SignatureVerificationFilter verifierFilter(verifier, NULLPTR, SignatureVerificationFilter::SIGNATURE_AT_BEGIN | SignatureVerificationFilter::THROW_EXCEPTION); + StringSource(signature, true, new HexDecoder(new Redirector(verifierFilter, Redirector::DATA_ONLY))); + StringSource(message, true, new Redirector(verifierFilter)); +} + +void EncryptionPairwiseConsistencyTest(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor) +{ + try + { + RandomPool rng; + const char *testMessage ="test message"; + std::string ciphertext, decrypted; + + StringSource( + testMessage, + true, + new PK_EncryptorFilter( + rng, + encryptor, + new StringSink(ciphertext))); + + if (ciphertext == testMessage) + throw 0; + + StringSource( + ciphertext, + true, + new PK_DecryptorFilter( + rng, + decryptor, + new StringSink(decrypted))); + + if (decrypted != testMessage) + throw 0; + } + catch (...) + { + throw SelfTestFailure(encryptor.AlgorithmName() + ": pairwise consistency test failed"); + } +} + +void SignaturePairwiseConsistencyTest(const PK_Signer &signer, const PK_Verifier &verifier) +{ + try + { + RandomPool rng; + + StringSource( + "test message", + true, + new SignerFilter( + rng, + signer, + new SignatureVerificationFilter(verifier, NULLPTR, SignatureVerificationFilter::THROW_EXCEPTION), + true)); + } + catch (...) + { + throw SelfTestFailure(signer.AlgorithmName() + ": pairwise consistency test failed"); + } +} + +template +void SignaturePairwiseConsistencyTest(const char *key) +{ + typename SCHEME::Signer signer(StringSource(key, true, new HexDecoder).Ref()); + typename SCHEME::Verifier verifier(signer); + + SignaturePairwiseConsistencyTest(signer, verifier); +} + +MessageAuthenticationCode * NewIntegrityCheckingMAC() +{ + byte key[] = {0x47, 0x1E, 0x33, 0x96, 0x65, 0xB1, 0x6A, 0xED, 0x0B, 0xF8, 0x6B, 0xFD, 0x01, 0x65, 0x05, 0xCC}; + return new HMAC(key, sizeof(key)); +} + +bool IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac, unsigned long *pMacFileLocation) +{ + member_ptr mac(NewIntegrityCheckingMAC()); + unsigned int macSize = mac->DigestSize(); + + SecByteBlock tempMac; + SecByteBlock &actualMac = pActualMac ? *pActualMac : tempMac; + actualMac.resize(macSize); + + unsigned long tempLocation = 0; + unsigned long &macFileLocation = pMacFileLocation ? *pMacFileLocation : tempLocation; + macFileLocation = 0; + + MeterFilter verifier(new HashFilter(*mac, new ArraySink(actualMac, actualMac.size()))); +// MeterFilter verifier(new FileSink("c:\\dt.tmp")); + std::ifstream moduleStream; + +#ifdef CRYPTOPP_WIN32_AVAILABLE + HMODULE h = NULLPTR; + { + const size_t FIPS_MODULE_MAX_PATH = 2*MAX_PATH; + char moduleFilenameBuf[FIPS_MODULE_MAX_PATH] = ""; + if (moduleFilename == NULLPTR) + { +#if (_MSC_VER >= 1400 && !defined(_STLPORT_VERSION)) // ifstream doesn't support wide filename on other compilers + wchar_t wideModuleFilename[FIPS_MODULE_MAX_PATH]; + if (GetModuleFileNameW(s_hModule, wideModuleFilename, FIPS_MODULE_MAX_PATH) > 0) + { + moduleStream.open(wideModuleFilename, std::ios::in | std::ios::binary); + h = GetModuleHandleW(wideModuleFilename); + } + else +#endif + { + GetModuleFileNameA(s_hModule, moduleFilenameBuf, FIPS_MODULE_MAX_PATH); + moduleFilename = moduleFilenameBuf; + } + } +#endif + if (moduleFilename != NULLPTR) + { + moduleStream.open(moduleFilename, std::ios::in | std::ios::binary); +#ifdef CRYPTOPP_WIN32_AVAILABLE + h = GetModuleHandleA(moduleFilename); + moduleFilename = NULLPTR; + } +#endif + } + +#ifdef CRYPTOPP_WIN32_AVAILABLE + if (h == g_BaseAddressOfMAC) + { + std::ostringstream oss; + oss << "Crypto++ DLL loaded at base address " << std::hex << h << ".\n"; + OutputDebugStringA(oss.str().c_str()); + } + else + { + std::ostringstream oss; + oss << "Crypto++ DLL integrity check may fail. Expected module base address is "; + oss << std::hex << g_BaseAddressOfMAC << ", but module loaded at " << h << ".\n"; + OutputDebugStringA(oss.str().c_str()); + } +#endif + + if (!moduleStream) + { +#ifdef CRYPTOPP_WIN32_AVAILABLE + OutputDebugStringA("Crypto++ DLL integrity check failed. Cannot open file for reading."); +#endif + return false; + } + FileStore file(moduleStream); + +#ifdef CRYPTOPP_WIN32_AVAILABLE + // try to hash from memory first + const byte *memBase = (const byte *)h; + const IMAGE_DOS_HEADER *ph = (IMAGE_DOS_HEADER *)memBase; + const IMAGE_NT_HEADERS *phnt = (IMAGE_NT_HEADERS *)(memBase + ph->e_lfanew); + const IMAGE_SECTION_HEADER *phs = IMAGE_FIRST_SECTION(phnt); + DWORD nSections = phnt->FileHeader.NumberOfSections; + size_t currentFilePos = 0; + + size_t checksumPos = (byte *)&phnt->OptionalHeader.CheckSum - memBase; + size_t checksumSize = sizeof(phnt->OptionalHeader.CheckSum); + size_t certificateTableDirectoryPos = (byte *)&phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] - memBase; + size_t certificateTableDirectorySize = sizeof(phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]); + size_t certificateTablePos = phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; + size_t certificateTableSize = phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size; + + verifier.AddRangeToSkip(0, checksumPos, checksumSize); + verifier.AddRangeToSkip(0, certificateTableDirectoryPos, certificateTableDirectorySize); + verifier.AddRangeToSkip(0, certificateTablePos, certificateTableSize); + + while (nSections--) + { + switch (phs->Characteristics) + { + default: + break; + case IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ: + case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ: + unsigned int sectionSize = STDMIN(phs->SizeOfRawData, phs->Misc.VirtualSize); + const byte *sectionMemStart = memBase + phs->VirtualAddress; + unsigned int sectionFileStart = phs->PointerToRawData; + size_t subSectionStart = 0, nextSubSectionStart; + + do + { + const byte *subSectionMemStart = sectionMemStart + subSectionStart; + size_t subSectionFileStart = sectionFileStart + subSectionStart; + size_t subSectionSize = sectionSize - subSectionStart; + nextSubSectionStart = 0; + + unsigned int entriesToReadFromDisk[] = {IMAGE_DIRECTORY_ENTRY_IMPORT, IMAGE_DIRECTORY_ENTRY_IAT}; + for (unsigned int i=0; iOptionalHeader.DataDirectory[entriesToReadFromDisk[i]]; + const byte *entryMemStart = memBase + entry.VirtualAddress; + if (subSectionMemStart <= entryMemStart && entryMemStart < subSectionMemStart + subSectionSize) + { + subSectionSize = entryMemStart - subSectionMemStart; + nextSubSectionStart = entryMemStart - sectionMemStart + entry.Size; + } + } + + // Visual Studio 2019 is MSC_VER == 1920 + // https://dev.to/yumetodo/list-of-mscver-and-mscfullver-8nds +#if (_MSC_VER >= 1400 && _MSC_VER < 1920) && (defined(_M_IX86) || defined(_M_X64)) + // first byte of _CRT_DEBUGGER_HOOK gets modified in memory by the debugger invisibly, so read it from file + if (IsDebuggerPresent()) + { + if (subSectionMemStart <= (byte *)&_CRT_DEBUGGER_HOOK && (byte *)&_CRT_DEBUGGER_HOOK < subSectionMemStart + subSectionSize) + { + subSectionSize = (byte *)&_CRT_DEBUGGER_HOOK - subSectionMemStart; + nextSubSectionStart = (byte *)&_CRT_DEBUGGER_HOOK - sectionMemStart + 1; + } + } +#endif + + if (subSectionMemStart <= expectedModuleMac && expectedModuleMac < subSectionMemStart + subSectionSize) + { + // found stored MAC + macFileLocation = (unsigned long)(subSectionFileStart + (expectedModuleMac - subSectionMemStart)); + verifier.AddRangeToSkip(0, macFileLocation, macSize); + } + + file.TransferTo(verifier, subSectionFileStart - currentFilePos); + verifier.Put(subSectionMemStart, subSectionSize); + file.Skip(subSectionSize); + currentFilePos = subSectionFileStart + subSectionSize; + subSectionStart = nextSubSectionStart; + } while (nextSubSectionStart != 0); + } + phs++; + } +#endif + file.TransferAllTo(verifier); + +#ifdef CRYPTOPP_WIN32_AVAILABLE + // if that fails (could be caused by debug breakpoints or DLL base relocation modifying image in memory), + // hash from disk instead + if (!VerifyBufsEqual(expectedModuleMac, actualMac, macSize)) + { + OutputDebugStringA("Crypto++ DLL in-memory integrity check failed. This may be caused by debug breakpoints or DLL relocation.\n"); + moduleStream.clear(); + moduleStream.seekg(0); + verifier.Initialize(MakeParameters(Name::OutputBuffer(), ByteArrayParameter(actualMac, (unsigned int)actualMac.size()))); +// verifier.Initialize(MakeParameters(Name::OutputFileName(), (const char *)"c:\\dt2.tmp")); + verifier.AddRangeToSkip(0, checksumPos, checksumSize); + verifier.AddRangeToSkip(0, certificateTableDirectoryPos, certificateTableDirectorySize); + verifier.AddRangeToSkip(0, certificateTablePos, certificateTableSize); + verifier.AddRangeToSkip(0, macFileLocation, macSize); + FileStore(moduleStream).TransferAllTo(verifier); + } +#endif + + if (VerifyBufsEqual(expectedModuleMac, actualMac, macSize)) + return true; + +#ifdef CRYPTOPP_WIN32_AVAILABLE + std::string hexMac; + HexEncoder(new StringSink(hexMac)).PutMessageEnd(actualMac, actualMac.size()); + OutputDebugStringA((("Crypto++ DLL integrity check failed. Actual MAC is: " + hexMac) + ".\n").c_str()); +#endif + return false; +} + +void DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac) +{ + g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_NOT_DONE; + SetPowerUpSelfTestInProgressOnThisThread(true); + + try + { + if (FIPS_140_2_ComplianceEnabled() || expectedModuleMac != NULLPTR) + { + if (!IntegrityCheckModule(moduleFilename, expectedModuleMac, &g_actualMac, &g_macFileLocation)) + throw 0; // throw here so we break in the debugger, this will be caught right away + } + + // algorithm tests + + X917RNG_KnownAnswerTest( + "2b7e151628aed2a6abf7158809cf4f3c", // key + "000102030405060708090a0b0c0d0e0f", // seed + "00000000000000000000000000000001", // time vector + "D176EDD27493B0395F4D10546232B0693DC7061C03C3A554F09CECF6F6B46D945A"); // output + + SymmetricEncryptionKnownAnswerTest( + "385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E", + "C141B5FCCD28DC8A", + "6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68", + "64EAAD4ACBB9CEAD6C7615E7C7E4792FE587D91F20C7D2F4", + "6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9", + "E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B", + "E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62", + "E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371"); + + SymmetricEncryptionKnownAnswerTest( + "1555E5531C3A169B2D65", + "6EC9795701F49864", + "00AFA48E9621E52E8CBDA312660184EDDB1F33D9DACDA8DA", + "DBEC73562EFCAEB56204EB8AE9557EBF77473FBB52D17CD1", + "0C7B0B74E21F99B8F2C8DF37879F6C044967F42A796DCA8B", + "79FDDA9724E36CC2E023E9A5C717A8A8A7FDA465CADCBF63", + "79FDDA9724E36CC26CACBD83C1ABC06EAF5B249BE5B1E040", + "79FDDA9724E36CC211B0AEC607B95A96BCDA318440B82F49"); + + SymmetricEncryptionKnownAnswerTest( + "2b7e151628aed2a6abf7158809cf4f3c", + "000102030405060708090a0b0c0d0e0f", + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", // plaintext + "3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf43b1cd7f598ece23881b00e3ed0306887b0c785e27e8ad3f8223207104725dd4", // ecb + "7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120eca307586e1a7", // cbc + "3b3fd92eb72dad20333449f8e83cfb4ac8a64537a0b3a93fcde3cdad9f1ce58b26751f67a3cbb140b1808cf187a4f4dfc04b05357c5d1c0eeac4c66f9ff7f2e6", // cfb + "3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e", // ofb + NULLPTR); + + SymmetricEncryptionKnownAnswerTest( + "2b7e151628aed2a6abf7158809cf4f3c", + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", + NULLPTR, + NULLPTR, + NULLPTR, + NULLPTR, + "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"); // ctr + + + SecureHashKnownAnswerTest( + "abc", + "A9993E364706816ABA3E25717850C26C9CD0D89D"); + + SecureHashKnownAnswerTest( + "abc", + "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"); + + SecureHashKnownAnswerTest( + "abc", + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); + + SecureHashKnownAnswerTest( + "abc", + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"); + + SecureHashKnownAnswerTest( + "abc", + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); + + MAC_KnownAnswerTest >( + "303132333435363738393a3b3c3d3e3f40414243", + "Sample #2", + "0922d3405faa3d194f82a45830737d5cc6c75d24"); + + const char *keyRSA1 = + "30820150020100300d06092a864886f70d01010105000482013a3082013602010002400a66791dc6988168de7ab77419bb7fb0" + "c001c62710270075142942e19a8d8c51d053b3e3782a1de5dc5af4ebe99468170114a1dfe67cdc9a9af55d655620bbab0203010001" + "02400123c5b61ba36edb1d3679904199a89ea80c09b9122e1400c09adcf7784676d01d23356a7d44d6bd8bd50e94bfc723fa" + "87d8862b75177691c11d757692df8881022033d48445c859e52340de704bcdda065fbb4058d740bd1d67d29e9c146c11cf61" + "0220335e8408866b0fd38dc7002d3f972c67389a65d5d8306566d5c4f2a5aa52628b0220045ec90071525325d3d46db79695e9af" + "acc4523964360e02b119baa366316241022015eb327360c7b60d12e5e2d16bdcd97981d17fba6b70db13b20b436e24eada590220" + "2ca6366d72781dfa24d34a9a24cbc2ae927a9958af426563ff63fb11658a461d"; + + const char *keyRSA2 = + "30820273020100300D06092A864886F70D01010105000482025D3082025902010002818100D40AF9" + "A2B713034249E5780056D70FC7DE75D76E44565AA6A6B8ED9646F3C19F9E254D72D7DE6E49DB2264" + "0C1D05AB9E2A5F901D8F3FE1F7AE02CEE2ECCE54A40ABAE55A004692752E70725AEEE7CDEA67628A" + "82A9239B4AB660C2BC56D9F01E90CBAAB9BF0FC8E17173CEFC5709A29391A7DDF3E0B758691AAF30" + "725B292F4F020111027F18C0BA087D082C45D75D3594E0767E4820818EB35612B80CEAB8C880ACA5" + "44B6876DFFEF85A576C0D45B551AFAA1FD63209CD745DF75C5A0F0B580296EA466CD0338207E4752" + "FF4E7DB724D8AE18CE5CF4153BB94C27869FBB50E64F02546E4B02997A0B8623E64017CC770759C6" + "695DB649EEFD829D688D441BCC4E7348F1024100EF86DD7AF3F32CDE8A9F6564E43A559A0C9F8BAD" + "36CC25330548B347AC158A345631FA90F7B873C36EFFAE2F7823227A3F580B5DD18304D5932751E7" + "43E9234F024100E2A039854B55688740E32A51DF4AF88613D91A371CF8DDD95D780A89D7CF2119A9" + "54F1AC0F3DCDB2F6959926E6D9D37D8BC07A4C634DE6F16315BD5F0DAC340102407ECEEDB9903572" + "1B76909F174BA6698DCA72953D957B22C0A871C8531EDE3A1BB52984A719BC010D1CA57A555DB83F" + "6DE54CBAB932AEC652F38D497A6F3F30CF024100854F30E4FF232E6DADB2CD99926855F484255AB7" + "01FBCDCB27EC426F33A7046972AA700ADBCA008763DF87440F52F4E070531AC385B55AAC1C2AE7DD" + "8F9278F1024100C313F4AF9E4A9DE1253C21080CE524251560C111550772FD08690F13FBE658342E" + "BD2D41C9DCB12374E871B1839E26CAE252E1AE3DAAD5F1EE1F42B4D0EE7581"; + + SignatureKnownAnswerTest >( + keyRSA1, + "Everyone gets Friday off.", + "0610761F95FFD1B8F29DA34212947EC2AA0E358866A722F03CC3C41487ADC604A48FF54F5C6BEDB9FB7BD59F82D6E55D8F3174BA361B2214B2D74E8825E04E81"); + + SignatureKnownAnswerTest >( + keyRSA2, + "test", + "32F6BA41C8930DE71EE67F2627172CC539EDE04267FDE03AC295E3C50311F26C3B275D3AF513AC96" + "8EE493BAB7DA3A754661D1A7C4A0D1A2B7EE8B313AACD8CB8BFBC5C15EFB0EF15C86A9334A1E87AD" + "291EB961B5CA0E84930429B28780816AA94F96FC2367B71E2D2E4866FA966795B147F00600E5207E" + "2F189C883B37477C"); + + SignaturePairwiseConsistencyTest( + "3082014A0201003082012B06072A8648CE3804013082011E02818100F468699A6F6EBCC0120D3B34C8E007F125EC7D81F763B8D0F33869AE3BD6B9F2ECCC7DF34DF84C0307449E9B85D30D57194BCCEB310F48141914DD13A077AAF9B624A6CBE666BBA1D7EBEA95B5BA6F54417FD5D4E4220C601E071D316A24EA814E8B0122DBF47EE8AEEFD319EBB01DD95683F10DBB4FEB023F8262A07EAEB7FD02150082AD4E034DA6EEACDFDAE68C36F2BAD614F9E53B02818071AAF73361A26081529F7D84078ADAFCA48E031DB54AD57FB1A833ADBD8672328AABAA0C756247998D7A5B10DACA359D231332CE8120B483A784FE07D46EEBFF0D7D374A10691F78653E6DC29E27CCB1B174923960DFE5B959B919B2C3816C19251832AFD8E35D810E598F82877ABF7D40A041565168BD7F0E21E3FE2A8D8C1C0416021426EBA66E846E755169F84A1DA981D86502405DDF"); + + SignaturePairwiseConsistencyTest >( + "302D020100301006072A8648CE3D020106052B8104000404163014020101040F0070337065E1E196980A9D00E37211"); + + SignaturePairwiseConsistencyTest >( + "3039020100301306072A8648CE3D020106082A8648CE3D030101041F301D02010104182BB8A13C8B867010BD9471D9E81FDB01ABD0538C64D6249A"); + + SignaturePairwiseConsistencyTest >(keyRSA1); + } + catch (...) + { + g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_FAILED; + goto done; + } + + g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_PASSED; + +done: + SetPowerUpSelfTestInProgressOnThisThread(false); + return; +} + +#ifdef CRYPTOPP_WIN32_AVAILABLE + +void DoDllPowerUpSelfTest() +{ + CryptoPP::DoPowerUpSelfTest(NULLPTR, s_moduleMac); +} + +#else + +void DoDllPowerUpSelfTest() +{ + throw NotImplemented("DoDllPowerUpSelfTest() only available on Windows"); +} + +#endif // #ifdef CRYPTOPP_WIN32_AVAILABLE + +NAMESPACE_END + +#ifdef CRYPTOPP_WIN32_AVAILABLE + +// DllMain needs to be in the global namespace +BOOL APIENTRY DllMain(HANDLE hModule, + DWORD dwReason, + LPVOID /*lpReserved*/) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + CryptoPP::s_hModule = (HMODULE)hModule; + CryptoPP::DoDllPowerUpSelfTest(); + } + return TRUE; +} + +#endif // #ifdef CRYPTOPP_WIN32_AVAILABLE + +#endif // #ifndef CRYPTOPP_IMPORTS diff --git a/external/ours/library/crypto/src/shared/original/fltrimpl.h b/external/ours/library/crypto/src/shared/original/fltrimpl.h new file mode 100755 index 000000000..4fc4224b5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/fltrimpl.h @@ -0,0 +1,87 @@ +#ifndef CRYPTOPP_FLTRIMPL_H +#define CRYPTOPP_FLTRIMPL_H + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4100) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-value" +#endif + +#define FILTER_BEGIN \ + switch (m_continueAt) \ + { \ + 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: \ + 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: \ + 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: \ + 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) + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic pop +#endif + +#endif diff --git a/external/ours/library/crypto/src/shared/original/gcm.cpp b/external/ours/library/crypto/src/shared/original/gcm.cpp new file mode 100755 index 000000000..380dc7802 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gcm.cpp @@ -0,0 +1,852 @@ +// gcm.cpp - originally written and placed in the public domain by Wei Dai. +// ARM and Aarch64 added by Jeffrey Walton. The ARM carryless +// multiply routines are less efficient because they shadow x86. +// The precomputed key table integration makes it tricky to use the +// more efficient ARMv8 implementation of the multiply and reduce. + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM gcm.cpp" to generate MASM code + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS +#ifndef CRYPTOPP_GENERATE_X64_MASM + +// Visual Studio .Net 2003 compiler crash +#if defined(_MSC_VER) && (_MSC_VER < 1400) +# pragma optimize("", off) +#endif + +#include "gcm.h" +#include "cpu.h" + +#if defined(CRYPTOPP_DISABLE_GCM_ASM) +# undef CRYPTOPP_X86_ASM_AVAILABLE +# undef CRYPTOPP_X32_ASM_AVAILABLE +# undef CRYPTOPP_X64_ASM_AVAILABLE +# undef CRYPTOPP_SSE2_ASM_AVAILABLE +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +// Different assemblers accept different mnemonics: 'movd eax, xmm0' vs +// 'movd rax, xmm0' vs 'mov eax, xmm0' vs 'mov rax, xmm0' +#if defined(CRYPTOPP_DISABLE_MIXED_ASM) +// 'movd eax, xmm0' only. REG_WORD() macro not used. Clang path. +# define USE_MOVD_REG32 1 +#elif defined(__GNUC__) || defined(_MSC_VER) +// 'movd eax, xmm0' or 'movd rax, xmm0'. REG_WORD() macro supplies REG32 or REG64. +# define USE_MOVD_REG32_OR_REG64 1 +#else +// 'mov eax, xmm0' or 'mov rax, xmm0'. REG_WORD() macro supplies REG32 or REG64. +# define USE_MOV_REG32_OR_REG64 1 +#endif +#endif // CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 + +word16 GCM_Base::s_reductionTable[256]; +volatile bool GCM_Base::s_reductionTableInitialized = false; + +void GCM_Base::GCTR::IncrementCounterBy256() +{ + IncrementCounterByOne(m_counterArray+BlockSize()-4, 3); +} + +static inline void Xor16(byte *a, const byte *b, const byte *c) +{ + CRYPTOPP_ASSERT(IsAlignedOn(a,GetAlignmentOf())); + CRYPTOPP_ASSERT(IsAlignedOn(b,GetAlignmentOf())); + CRYPTOPP_ASSERT(IsAlignedOn(c,GetAlignmentOf())); + ((word64 *)(void *)a)[0] = ((word64 *)(void *)b)[0] ^ ((word64 *)(void *)c)[0]; + ((word64 *)(void *)a)[1] = ((word64 *)(void *)b)[1] ^ ((word64 *)(void *)c)[1]; +} + +#if CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE +// SunCC 5.10-5.11 compiler crash. Move GCM_Xor16_SSE2 out-of-line, and place in +// a source file with a SSE architecture switch. Also see GH #226 and GH #284. +extern void GCM_Xor16_SSE2(byte *a, const byte *b, const byte *c); +#endif // SSE2 + +#if CRYPTOPP_ARM_NEON_AVAILABLE +extern void GCM_Xor16_NEON(byte *a, const byte *b, const byte *c); +#endif + +#if CRYPTOPP_POWER8_AVAILABLE +extern void GCM_Xor16_POWER8(byte *a, const byte *b, const byte *c); +#endif + +#if CRYPTOPP_CLMUL_AVAILABLE +extern void GCM_SetKeyWithoutResync_CLMUL(const byte *hashKey, byte *mulTable, unsigned int tableSize); +extern size_t GCM_AuthenticateBlocks_CLMUL(const byte *data, size_t len, const byte *mtable, byte *hbuffer); +const unsigned int s_cltableSizeInBlocks = 8; +extern void GCM_ReverseHashBufferIfNeeded_CLMUL(byte *hashBuffer); +#endif // CRYPTOPP_CLMUL_AVAILABLE + +#if CRYPTOPP_ARM_PMULL_AVAILABLE +extern void GCM_SetKeyWithoutResync_PMULL(const byte *hashKey, byte *mulTable, unsigned int tableSize); +extern size_t GCM_AuthenticateBlocks_PMULL(const byte *data, size_t len, const byte *mtable, byte *hbuffer); +const unsigned int s_cltableSizeInBlocks = 8; +extern void GCM_ReverseHashBufferIfNeeded_PMULL(byte *hashBuffer); +#endif // CRYPTOPP_ARM_PMULL_AVAILABLE + +#if CRYPTOPP_POWER8_VMULL_AVAILABLE +extern void GCM_SetKeyWithoutResync_VMULL(const byte *hashKey, byte *mulTable, unsigned int tableSize); +extern size_t GCM_AuthenticateBlocks_VMULL(const byte *data, size_t len, const byte *mtable, byte *hbuffer); +const unsigned int s_cltableSizeInBlocks = 8; +extern void GCM_ReverseHashBufferIfNeeded_VMULL(byte *hashBuffer); +#endif // CRYPTOPP_POWER8_VMULL_AVAILABLE + +void GCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) +{ + BlockCipher &blockCipher = AccessBlockCipher(); + blockCipher.SetKey(userKey, keylength, params); + + // GCM is only defined for 16-byte block ciphers at the moment. + // However, variable blocksize support means we have to defer + // blocksize checks to runtime after the key is set. Also see + // https://github.com/weidai11/cryptopp/issues/408. + const unsigned int blockSize = blockCipher.BlockSize(); + CRYPTOPP_ASSERT(blockSize == REQUIRED_BLOCKSIZE); + if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE) + throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16"); + + int tableSize, i, j, k; + +#if CRYPTOPP_CLMUL_AVAILABLE + if (HasCLMUL()) + { + // Avoid "parameter not used" error and suppress Coverity finding + (void)params.GetIntValue(Name::TableSize(), tableSize); + tableSize = s_cltableSizeInBlocks * blockSize; + CRYPTOPP_ASSERT(tableSize > static_cast(blockSize)); + } + else +#elif CRYPTOPP_ARM_PMULL_AVAILABLE + if (HasPMULL()) + { + // Avoid "parameter not used" error and suppress Coverity finding + (void)params.GetIntValue(Name::TableSize(), tableSize); + tableSize = s_cltableSizeInBlocks * blockSize; + CRYPTOPP_ASSERT(tableSize > static_cast(blockSize)); + } + else +#elif CRYPTOPP_POWER8_VMULL_AVAILABLE + if (HasPMULL()) + { + // Avoid "parameter not used" error and suppress Coverity finding + (void)params.GetIntValue(Name::TableSize(), tableSize); + tableSize = s_cltableSizeInBlocks * blockSize; + CRYPTOPP_ASSERT(tableSize > static_cast(blockSize)); + } + else +#endif + { + if (params.GetIntValue(Name::TableSize(), tableSize)) + tableSize = (tableSize >= 64*1024) ? 64*1024 : 2*1024; + else + tableSize = (GetTablesOption() == GCM_64K_Tables) ? 64*1024 : 2*1024; + + //#if defined(_MSC_VER) && (_MSC_VER < 1400) + // VC 2003 workaround: compiler generates bad code for 64K tables + //tableSize = 2*1024; + //#endif + } + + m_buffer.resize(3*blockSize + tableSize); + byte *mulTable = MulTable(); + byte *hashKey = HashKey(); + memset(hashKey, 0, REQUIRED_BLOCKSIZE); + blockCipher.ProcessBlock(hashKey); + +#if CRYPTOPP_CLMUL_AVAILABLE + if (HasCLMUL()) + { + GCM_SetKeyWithoutResync_CLMUL(hashKey, mulTable, tableSize); + return; + } +#elif CRYPTOPP_ARM_PMULL_AVAILABLE + if (HasPMULL()) + { + GCM_SetKeyWithoutResync_PMULL(hashKey, mulTable, tableSize); + return; + } +#elif CRYPTOPP_POWER8_VMULL_AVAILABLE + if (HasPMULL()) + { + GCM_SetKeyWithoutResync_VMULL(hashKey, mulTable, tableSize); + return; + } +#endif + + word64 V0, V1; + typedef BlockGetAndPut Block; + Block::Get(hashKey)(V0)(V1); + + if (tableSize == 64*1024) + { + for (i=0; i<128; i++) + { + k = i%8; + Block::Put(NULLPTR, mulTable+(i/8)*256*16+(size_t(1)<<(11-k)))(V0)(V1); + + int x = (int)V1 & 1; + V1 = (V1>>1) | (V0<<63); + V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0); + } + + for (i=0; i<16; i++) + { + memset(mulTable+i*256*16, 0, 16); +#if CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + for (j=2; j<=0x80; j*=2) + for (k=1; k>1) | (V0<<63); + V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0); + } + + for (i=0; i<4; i++) + { + memset(mulTable+i*256, 0, 16); + memset(mulTable+1024+i*256, 0, 16); +#if CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + for (j=2; j<=8; j*=2) + for (k=1; k= HASH_BLOCKSIZE) + { + len = GCM_Base::AuthenticateBlocks(iv, len); + iv += (origLen - len); + } + + if (len > 0) + { + memcpy(m_buffer, iv, len); + memset(m_buffer+len, 0, HASH_BLOCKSIZE-len); + GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE); + } + + PutBlock(NULLPTR, m_buffer)(0)(origLen*8); + GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE); + + ReverseHashBufferIfNeeded(); + } + + if (m_state >= State_IVSet) + m_ctr.Resynchronize(hashBuffer, REQUIRED_BLOCKSIZE); + else + m_ctr.SetCipherWithIV(cipher, hashBuffer); + + m_ctr.Seek(HASH_BLOCKSIZE); + + memset(hashBuffer, 0, HASH_BLOCKSIZE); +} + +unsigned int GCM_Base::OptimalDataAlignment() const +{ + return +#if CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) + HasSSE2() ? 16 : +#elif CRYPTOPP_ARM_NEON_AVAILABLE + HasNEON() ? 4 : +#elif CRYPTOPP_POWER8_AVAILABLE + HasPower8() ? 16 : +#endif + GetBlockCipher().OptimalDataAlignment(); +} + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code +#endif + +#endif // Not CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void GCM_AuthenticateBlocks_2K_SSE2(const byte *data, size_t blocks, word64 *hashBuffer, const word16 *reductionTable); +void GCM_AuthenticateBlocks_64K_SSE2(const byte *data, size_t blocks, word64 *hashBuffer); +} +#endif + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +size_t GCM_Base::AuthenticateBlocks(const byte *data, size_t len) +{ +#if CRYPTOPP_CLMUL_AVAILABLE + if (HasCLMUL()) + { + return GCM_AuthenticateBlocks_CLMUL(data, len, MulTable(), HashBuffer()); + } +#elif CRYPTOPP_ARM_PMULL_AVAILABLE + if (HasPMULL()) + { + return GCM_AuthenticateBlocks_PMULL(data, len, MulTable(), HashBuffer()); + } +#elif CRYPTOPP_POWER8_VMULL_AVAILABLE + if (HasPMULL()) + { + return GCM_AuthenticateBlocks_VMULL(data, len, MulTable(), HashBuffer()); + } +#endif + + typedef BlockGetAndPut Block; + word64 *hashBuffer = (word64 *)(void *)HashBuffer(); + CRYPTOPP_ASSERT(IsAlignedOn(hashBuffer,GetAlignmentOf())); + + switch (2*(m_buffer.size()>=64*1024) +#if CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) + + HasSSE2() +//#elif CRYPTOPP_ARM_NEON_AVAILABLE +// + HasNEON() +#endif + ) + { + case 0: // non-SSE2 and 2K tables + { + byte *mulTable = MulTable(); + word64 x0 = hashBuffer[0], x1 = hashBuffer[1]; + + do + { + word64 y0, y1, a0, a1, b0, b1, c0, c1, d0, d1; + Block::Get(data)(y0)(y1); + x0 ^= y0; + x1 ^= y1; + + data += HASH_BLOCKSIZE; + len -= HASH_BLOCKSIZE; + + #define READ_TABLE_WORD64_COMMON(a, b, c, d) *(word64 *)(void *)(mulTable+(a*1024)+(b*256)+c+d*8) + + #if (CRYPTOPP_LITTLE_ENDIAN) + #if CRYPTOPP_BOOL_SLOW_WORD64 + word32 z0 = (word32)x0; + word32 z1 = (word32)(x0>>32); + word32 z2 = (word32)x1; + word32 z3 = (word32)(x1>>32); + #define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((d%2), c, (d?(z##c>>((d?d-1:0)*4))&0xf0:(z##c&0xf)<<4), e) + #else + #define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((d%2), c, ((d+8*b)?(x##a>>(((d+8*b)?(d+8*b)-1:1)*4))&0xf0:(x##a&0xf)<<4), e) + #endif + #define GF_MOST_SIG_8BITS(a) (a##1 >> 7*8) + #define GF_SHIFT_8(a) a##1 = (a##1 << 8) ^ (a##0 >> 7*8); a##0 <<= 8; + #else + #define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((1-d%2), c, ((15-d-8*b)?(x##a>>(((15-d-8*b)?(15-d-8*b)-1:0)*4))&0xf0:(x##a&0xf)<<4), e) + #define GF_MOST_SIG_8BITS(a) (a##1 & 0xff) + #define GF_SHIFT_8(a) a##1 = (a##1 >> 8) ^ (a##0 << 7*8); a##0 >>= 8; + #endif + + #define GF_MUL_32BY128(op, a, b, c) \ + a0 op READ_TABLE_WORD64(a, b, c, 0, 0) ^ READ_TABLE_WORD64(a, b, c, 1, 0); \ + a1 op READ_TABLE_WORD64(a, b, c, 0, 1) ^ READ_TABLE_WORD64(a, b, c, 1, 1); \ + b0 op READ_TABLE_WORD64(a, b, c, 2, 0) ^ READ_TABLE_WORD64(a, b, c, 3, 0); \ + b1 op READ_TABLE_WORD64(a, b, c, 2, 1) ^ READ_TABLE_WORD64(a, b, c, 3, 1); \ + c0 op READ_TABLE_WORD64(a, b, c, 4, 0) ^ READ_TABLE_WORD64(a, b, c, 5, 0); \ + c1 op READ_TABLE_WORD64(a, b, c, 4, 1) ^ READ_TABLE_WORD64(a, b, c, 5, 1); \ + d0 op READ_TABLE_WORD64(a, b, c, 6, 0) ^ READ_TABLE_WORD64(a, b, c, 7, 0); \ + d1 op READ_TABLE_WORD64(a, b, c, 6, 1) ^ READ_TABLE_WORD64(a, b, c, 7, 1); \ + + GF_MUL_32BY128(=, 0, 0, 0) + GF_MUL_32BY128(^=, 0, 1, 1) + GF_MUL_32BY128(^=, 1, 0, 2) + GF_MUL_32BY128(^=, 1, 1, 3) + + word32 r = (word32)s_reductionTable[GF_MOST_SIG_8BITS(d)] << 16; + GF_SHIFT_8(d) + c0 ^= d0; c1 ^= d1; + r ^= (word32)s_reductionTable[GF_MOST_SIG_8BITS(c)] << 8; + GF_SHIFT_8(c) + b0 ^= c0; b1 ^= c1; + r ^= s_reductionTable[GF_MOST_SIG_8BITS(b)]; + GF_SHIFT_8(b) + a0 ^= b0; a1 ^= b1; + a0 ^= ConditionalByteReverse(LITTLE_ENDIAN_ORDER, r); + x0 = a0; x1 = a1; + } + while (len >= HASH_BLOCKSIZE); + + hashBuffer[0] = x0; hashBuffer[1] = x1; + return len; + } + + case 2: // non-SSE2 and 64K tables + { + byte *mulTable = MulTable(); + word64 x0 = hashBuffer[0], x1 = hashBuffer[1]; + + do + { + word64 y0, y1, a0, a1; + Block::Get(data)(y0)(y1); + x0 ^= y0; + x1 ^= y1; + + data += HASH_BLOCKSIZE; + len -= HASH_BLOCKSIZE; + + #undef READ_TABLE_WORD64_COMMON + #undef READ_TABLE_WORD64 + + #define READ_TABLE_WORD64_COMMON(a, c, d) *(word64 *)(void *)(mulTable+(a)*256*16+(c)+(d)*8) + + #if (CRYPTOPP_LITTLE_ENDIAN) + #if CRYPTOPP_BOOL_SLOW_WORD64 + word32 z0 = (word32)x0; + word32 z1 = (word32)(x0>>32); + word32 z2 = (word32)x1; + word32 z3 = (word32)(x1>>32); + #define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, (d?(z##c>>((d?d:1)*8-4))&0xff0:(z##c&0xff)<<4), e) + #else + #define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, ((d+4*(c%2))?(x##b>>(((d+4*(c%2))?(d+4*(c%2)):1)*8-4))&0xff0:(x##b&0xff)<<4), e) + #endif + #else + #define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, ((7-d-4*(c%2))?(x##b>>(((7-d-4*(c%2))?(7-d-4*(c%2)):1)*8-4))&0xff0:(x##b&0xff)<<4), e) + #endif + + #define GF_MUL_8BY128(op, b, c, d) \ + a0 op READ_TABLE_WORD64(b, c, d, 0);\ + a1 op READ_TABLE_WORD64(b, c, d, 1);\ + + GF_MUL_8BY128(=, 0, 0, 0) + GF_MUL_8BY128(^=, 0, 0, 1) + GF_MUL_8BY128(^=, 0, 0, 2) + GF_MUL_8BY128(^=, 0, 0, 3) + GF_MUL_8BY128(^=, 0, 1, 0) + GF_MUL_8BY128(^=, 0, 1, 1) + GF_MUL_8BY128(^=, 0, 1, 2) + GF_MUL_8BY128(^=, 0, 1, 3) + GF_MUL_8BY128(^=, 1, 2, 0) + GF_MUL_8BY128(^=, 1, 2, 1) + GF_MUL_8BY128(^=, 1, 2, 2) + GF_MUL_8BY128(^=, 1, 2, 3) + GF_MUL_8BY128(^=, 1, 3, 0) + GF_MUL_8BY128(^=, 1, 3, 1) + GF_MUL_8BY128(^=, 1, 3, 2) + GF_MUL_8BY128(^=, 1, 3, 3) + + x0 = a0; x1 = a1; + } + while (len >= HASH_BLOCKSIZE); + + hashBuffer[0] = x0; hashBuffer[1] = x1; + return len; + } +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE + case 1: // SSE2 and 2K tables + GCM_AuthenticateBlocks_2K_SSE2(data, len/16, hashBuffer, s_reductionTable); + return len % 16; + case 3: // SSE2 and 64K tables + GCM_AuthenticateBlocks_64K_SSE2(data, len/16, hashBuffer); + return len % 16; +#endif + +#if CRYPTOPP_SSE2_ASM_AVAILABLE + case 1: // SSE2 and 2K tables + { + #ifdef __GNUC__ + __asm__ __volatile__ + ( + INTEL_NOPREFIX + #elif defined(CRYPTOPP_GENERATE_X64_MASM) + ALIGN 8 + GCM_AuthenticateBlocks_2K_SSE2 PROC FRAME + rex_push_reg rsi + push_reg rdi + push_reg rbx + .endprolog + mov rsi, r8 + mov r11, r9 + #else + AS2( mov WORD_REG(cx), data ) + AS2( mov WORD_REG(dx), len ) + AS2( mov WORD_REG(si), hashBuffer ) + AS2( shr WORD_REG(dx), 4 ) + #endif + + #if CRYPTOPP_BOOL_X32 + AS1(push rbx) + AS1(push rbp) + #else + AS_PUSH_IF86( bx) + AS_PUSH_IF86( bp) + #endif + + #ifdef __GNUC__ + AS2( mov AS_REG_7, WORD_REG(di)) + #elif CRYPTOPP_BOOL_X86 + AS2( lea AS_REG_7, s_reductionTable) + #endif + + AS2( movdqa xmm0, [WORD_REG(si)] ) + + #define MUL_TABLE_0 WORD_REG(si) + 32 + #define MUL_TABLE_1 WORD_REG(si) + 32 + 1024 + #define RED_TABLE AS_REG_7 + + ASL(0) + AS2( movdqu xmm4, [WORD_REG(cx)] ) + AS2( pxor xmm0, xmm4 ) + + AS2( movd ebx, xmm0 ) + AS2( mov eax, AS_HEX(f0f0f0f0) ) + AS2( and eax, ebx ) + AS2( shl ebx, 4 ) + AS2( and ebx, AS_HEX(f0f0f0f0) ) + AS2( movzx edi, ah ) + AS2( movdqa xmm5, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] ) + AS2( movzx edi, al ) + AS2( movdqa xmm4, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] ) + AS2( shr eax, 16 ) + AS2( movzx edi, ah ) + AS2( movdqa xmm3, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] ) + AS2( movzx edi, al ) + AS2( movdqa xmm2, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] ) + + #define SSE2_MUL_32BITS(i) \ + AS2( psrldq xmm0, 4 )\ + AS2( movd eax, xmm0 )\ + AS2( and eax, AS_HEX(f0f0f0f0) )\ + AS2( movzx edi, bh )\ + AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\ + AS2( movzx edi, bl )\ + AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\ + AS2( shr ebx, 16 )\ + AS2( movzx edi, bh )\ + AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\ + AS2( movzx edi, bl )\ + AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\ + AS2( movd ebx, xmm0 )\ + AS2( shl ebx, 4 )\ + AS2( and ebx, AS_HEX(f0f0f0f0) )\ + AS2( movzx edi, ah )\ + AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\ + AS2( movzx edi, al )\ + AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\ + AS2( shr eax, 16 )\ + AS2( movzx edi, ah )\ + AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\ + AS2( movzx edi, al )\ + AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\ + + SSE2_MUL_32BITS(1) + SSE2_MUL_32BITS(2) + SSE2_MUL_32BITS(3) + + AS2( movzx edi, bh ) + AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] ) + AS2( movzx edi, bl ) + AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] ) + AS2( shr ebx, 16 ) + AS2( movzx edi, bh ) + AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] ) + AS2( movzx edi, bl ) + AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] ) + + AS2( movdqa xmm0, xmm3 ) + AS2( pslldq xmm3, 1 ) + AS2( pxor xmm2, xmm3 ) + AS2( movdqa xmm1, xmm2 ) + AS2( pslldq xmm2, 1 ) + AS2( pxor xmm5, xmm2 ) + + AS2( psrldq xmm0, 15 ) +#if USE_MOVD_REG32 + AS2( movd edi, xmm0 ) +#elif USE_MOV_REG32_OR_REG64 + AS2( mov WORD_REG(di), xmm0 ) +#else // GNU Assembler + AS2( movd WORD_REG(di), xmm0 ) +#endif + AS2( movzx eax, WORD PTR [RED_TABLE + WORD_REG(di)*2] ) + AS2( shl eax, 8 ) + + AS2( movdqa xmm0, xmm5 ) + AS2( pslldq xmm5, 1 ) + AS2( pxor xmm4, xmm5 ) + + AS2( psrldq xmm1, 15 ) +#if USE_MOVD_REG32 + AS2( movd edi, xmm1 ) +#elif USE_MOV_REG32_OR_REG64 + AS2( mov WORD_REG(di), xmm1 ) +#else + AS2( movd WORD_REG(di), xmm1 ) +#endif + AS2( xor ax, WORD PTR [RED_TABLE + WORD_REG(di)*2] ) + AS2( shl eax, 8 ) + + AS2( psrldq xmm0, 15 ) +#if USE_MOVD_REG32 + AS2( movd edi, xmm0 ) +#elif USE_MOV_REG32_OR_REG64 + AS2( mov WORD_REG(di), xmm0 ) +#else + AS2( movd WORD_REG(di), xmm0 ) +#endif + AS2( xor ax, WORD PTR [RED_TABLE + WORD_REG(di)*2] ) + + AS2( movd xmm0, eax ) + AS2( pxor xmm0, xmm4 ) + + AS2( add WORD_REG(cx), 16 ) + AS2( sub WORD_REG(dx), 1 ) + // ATT_NOPREFIX + ASJ( jnz, 0, b ) + INTEL_NOPREFIX + AS2( movdqa [WORD_REG(si)], xmm0 ) + + #if CRYPTOPP_BOOL_X32 + AS1(pop rbp) + AS1(pop rbx) + #else + AS_POP_IF86( bp) + AS_POP_IF86( bx) + #endif + + #ifdef __GNUC__ + ATT_PREFIX + : + : "c" (data), "d" (len/16), "S" (hashBuffer), "D" (s_reductionTable) + : "memory", "cc", "%eax" + #if CRYPTOPP_BOOL_X64 + , "%ebx", "%r11" + #endif + ); + #elif defined(CRYPTOPP_GENERATE_X64_MASM) + pop rbx + pop rdi + pop rsi + ret + GCM_AuthenticateBlocks_2K_SSE2 ENDP + #endif + + return len%16; + } + case 3: // SSE2 and 64K tables + { + #ifdef __GNUC__ + __asm__ __volatile__ + ( + INTEL_NOPREFIX + #elif defined(CRYPTOPP_GENERATE_X64_MASM) + ALIGN 8 + GCM_AuthenticateBlocks_64K_SSE2 PROC FRAME + rex_push_reg rsi + push_reg rdi + .endprolog + mov rsi, r8 + #else + AS2( mov WORD_REG(cx), data ) + AS2( mov WORD_REG(dx), len ) + AS2( mov WORD_REG(si), hashBuffer ) + AS2( shr WORD_REG(dx), 4 ) + #endif + + AS2( movdqa xmm0, [WORD_REG(si)] ) + + #undef MUL_TABLE + #define MUL_TABLE(i,j) WORD_REG(si) + 32 + (i*4+j)*256*16 + + ASL(1) + AS2( movdqu xmm1, [WORD_REG(cx)] ) + AS2( pxor xmm1, xmm0 ) + AS2( pxor xmm0, xmm0 ) + + #undef SSE2_MUL_32BITS + #define SSE2_MUL_32BITS(i) \ + AS2( movd eax, xmm1 )\ + AS2( psrldq xmm1, 4 )\ + AS2( movzx edi, al )\ + AS2( add WORD_REG(di), WORD_REG(di) )\ + AS2( pxor xmm0, [MUL_TABLE(i,0) + WORD_REG(di)*8] )\ + AS2( movzx edi, ah )\ + AS2( add WORD_REG(di), WORD_REG(di) )\ + AS2( pxor xmm0, [MUL_TABLE(i,1) + WORD_REG(di)*8] )\ + AS2( shr eax, 16 )\ + AS2( movzx edi, al )\ + AS2( add WORD_REG(di), WORD_REG(di) )\ + AS2( pxor xmm0, [MUL_TABLE(i,2) + WORD_REG(di)*8] )\ + AS2( movzx edi, ah )\ + AS2( add WORD_REG(di), WORD_REG(di) )\ + AS2( pxor xmm0, [MUL_TABLE(i,3) + WORD_REG(di)*8] )\ + + SSE2_MUL_32BITS(0) + SSE2_MUL_32BITS(1) + SSE2_MUL_32BITS(2) + SSE2_MUL_32BITS(3) + + AS2( add WORD_REG(cx), 16 ) + AS2( sub WORD_REG(dx), 1 ) + // ATT_NOPREFIX + ASJ( jnz, 1, b ) + INTEL_NOPREFIX + AS2( movdqa [WORD_REG(si)], xmm0 ) + + #ifdef __GNUC__ + ATT_PREFIX + : + : "c" (data), "d" (len/16), "S" (hashBuffer) + : "memory", "cc", "%edi", "%eax" + ); + #elif defined(CRYPTOPP_GENERATE_X64_MASM) + pop rdi + pop rsi + ret + GCM_AuthenticateBlocks_64K_SSE2 ENDP + #endif + + return len%16; + } +#endif +#ifndef CRYPTOPP_GENERATE_X64_MASM + } + + return len%16; +} + +void GCM_Base::AuthenticateLastHeaderBlock() +{ + if (m_bufferedDataLength > 0) + { + memset(m_buffer+m_bufferedDataLength, 0, HASH_BLOCKSIZE-m_bufferedDataLength); + m_bufferedDataLength = 0; + GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE); + } +} + +void GCM_Base::AuthenticateLastConfidentialBlock() +{ + GCM_Base::AuthenticateLastHeaderBlock(); + PutBlock(NULLPTR, m_buffer)(m_totalHeaderLength*8)(m_totalMessageLength*8); + GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE); +} + +void GCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize) +{ + m_ctr.Seek(0); + ReverseHashBufferIfNeeded(); + m_ctr.ProcessData(mac, HashBuffer(), macSize); +} + +NAMESPACE_END + +#endif // Not CRYPTOPP_GENERATE_X64_MASM +#endif diff --git a/external/ours/library/crypto/src/shared/original/gcm.h b/external/ours/library/crypto/src/shared/original/gcm.h new file mode 100755 index 000000000..a9302eec5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/gcm_simd.cpp b/external/ours/library/crypto/src/shared/original/gcm_simd.cpp new file mode 100755 index 000000000..32823e127 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gcm_simd.cpp @@ -0,0 +1,734 @@ +// gcm_simd.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// Original x86 CLMUL by Wei Dai. ARM and POWER8 +// PMULL and VMULL by JW, UB and MR. +// +// This source file uses intrinsics to gain access to SSE4.2 and +// ARMv8a CRC-32 and CRC-32C instructions. A separate source file +// is needed because additional CXXFLAGS are required to enable +// the appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" +#include "misc.h" + +#if defined(CRYPTOPP_DISABLE_GCM_ASM) +# undef CRYPTOPP_X86_ASM_AVAILABLE +# undef CRYPTOPP_X32_ASM_AVAILABLE +# undef CRYPTOPP_X64_ASM_AVAILABLE +# undef CRYPTOPP_SSE2_ASM_AVAILABLE +#endif + +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +# include +# include +#endif + +#if (CRYPTOPP_CLMUL_AVAILABLE) +# include +# include +#endif + +#if (CRYPTOPP_ARM_NEON_HEADER) +# include +# include +#endif + +#if defined(CRYPTOPP_ARM_PMULL_AVAILABLE) +# include "arm_simd.h" +#endif + +#if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +# include "ppc_simd.h" +#endif + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#ifndef EXCEPTION_EXECUTE_HANDLER +# define EXCEPTION_EXECUTE_HANDLER 1 +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char GCM_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +// ************************* Feature Probes ************************* // + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); + + static jmp_buf s_jmpSIGILL; + static void SigIllHandler(int) + { + longjmp(s_jmpSIGILL, 1); + } +} +#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY + +#if (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8) +bool CPU_ProbePMULL() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (CRYPTOPP_ARM_PMULL_AVAILABLE) +# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) + volatile bool result = true; + __try + { + // Linaro is missing a lot of pmull gear. Also see http://github.com/weidai11/cryptopp/issues/233. + const uint64_t wa1[]={0,0x9090909090909090}, wb1[]={0,0xb0b0b0b0b0b0b0b0}; + const uint64x2_t a1=vld1q_u64(wa1), b1=vld1q_u64(wb1); + + const uint8_t wa2[]={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0}, + wb2[]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0}; + const uint8x16_t a2=vld1q_u8(wa2), b2=vld1q_u8(wb2); + + const uint64x2_t r1 = PMULL_00(a1, b1); + const uint64x2_t r2 = PMULL_11(vreinterpretq_u64_u8(a2), + vreinterpretq_u64_u8(b2)); + + result = !!(vgetq_lane_u64(r1,0) == 0x5300530053005300 && + vgetq_lane_u64(r1,1) == 0x5300530053005300 && + vgetq_lane_u64(r2,0) == 0x6c006c006c006c00 && + vgetq_lane_u64(r2,1) == 0x6c006c006c006c00); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + return result; +# else + + // longjmp and clobber warnings. Volatile is required. + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + // Linaro is missing a lot of pmull gear. Also see http://github.com/weidai11/cryptopp/issues/233. + const uint64_t wa1[]={0,0x9090909090909090}, wb1[]={0,0xb0b0b0b0b0b0b0b0}; + const uint64x2_t a1=vld1q_u64(wa1), b1=vld1q_u64(wb1); + + const uint8_t wa2[]={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0}, + wb2[]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0}; + const uint8x16_t a2=vld1q_u8(wa2), b2=vld1q_u8(wb2); + + const uint64x2_t r1 = PMULL_00(a1, b1); + const uint64x2_t r2 = PMULL_11(vreinterpretq_u64_u8(a2), + vreinterpretq_u64_u8(b2)); + + result = !!(vgetq_lane_u64(r1,0) == 0x5300530053005300 && + vgetq_lane_u64(r1,1) == 0x5300530053005300 && + vgetq_lane_u64(r2,0) == 0x6c006c006c006c00 && + vgetq_lane_u64(r2,1) == 0x6c006c006c006c00); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_ARM_PMULL_AVAILABLE +} +#endif // ARM32 or ARM64 + +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) +bool CPU_ProbePMULL() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (CRYPTOPP_POWER8_VMULL_AVAILABLE) + // longjmp and clobber warnings. Volatile is required. + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + const uint64_t wa1[]={0,W64LIT(0x9090909090909090)}, + wb1[]={0,W64LIT(0xb0b0b0b0b0b0b0b0)}; + const uint64x2_p a1=VecLoad(wa1), b1=VecLoad(wb1); + + const uint8_t wa2[]={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0}, + wb2[]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0}; + const uint32x4_p a2=VecLoad(wa2), b2=VecLoad(wb2); + + const uint64x2_p r1 = VecIntelMultiply11(a1, b1); + const uint64x2_p r2 = VecIntelMultiply11((uint64x2_p)a2, (uint64x2_p)b2); + + const uint64_t wc1[]={W64LIT(0x5300530053005300), W64LIT(0x5300530053005300)}, + wc2[]={W64LIT(0x6c006c006c006c00), W64LIT(0x6c006c006c006c00)}; + const uint64x2_p c1=VecLoad(wc1), c2=VecLoad(wc2); + + result = !!(VecEqual(r1, c1) && VecEqual(r2, c2)); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +#else + return false; +#endif // CRYPTOPP_POWER8_VMULL_AVAILABLE +} +#endif // PPC32 or PPC64 + +// *************************** ARM NEON *************************** // + +#if CRYPTOPP_ARM_NEON_AVAILABLE +void GCM_Xor16_NEON(byte *a, const byte *b, const byte *c) +{ + vst1q_u8(a, veorq_u8(vld1q_u8(b), vld1q_u8(c))); +} +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +#if CRYPTOPP_ARM_PMULL_AVAILABLE + +// Swaps high and low 64-bit words +inline uint64x2_t SwapWords(const uint64x2_t& data) +{ + return (uint64x2_t)vcombine_u64( + vget_high_u64(data), vget_low_u64(data)); +} + +uint64x2_t GCM_Reduce_PMULL(uint64x2_t c0, uint64x2_t c1, uint64x2_t c2, const uint64x2_t &r) +{ + c1 = veorq_u64(c1, VEXT_U8<8>(vdupq_n_u64(0), c0)); + c1 = veorq_u64(c1, PMULL_01(c0, r)); + c0 = VEXT_U8<8>(c0, vdupq_n_u64(0)); + c0 = vshlq_n_u64(veorq_u64(c0, c1), 1); + c0 = PMULL_00(c0, r); + c2 = veorq_u64(c2, c0); + c2 = veorq_u64(c2, VEXT_U8<8>(c1, vdupq_n_u64(0))); + c1 = vshrq_n_u64(vcombine_u64(vget_low_u64(c1), vget_low_u64(c2)), 63); + c2 = vshlq_n_u64(c2, 1); + + return veorq_u64(c2, c1); +} + +uint64x2_t GCM_Multiply_PMULL(const uint64x2_t &x, const uint64x2_t &h, const uint64x2_t &r) +{ + const uint64x2_t c0 = PMULL_00(x, h); + const uint64x2_t c1 = veorq_u64(PMULL_10(x, h), PMULL_01(x, h)); + const uint64x2_t c2 = PMULL_11(x, h); + + return GCM_Reduce_PMULL(c0, c1, c2, r); +} + +void GCM_SetKeyWithoutResync_PMULL(const byte *hashKey, byte *mulTable, unsigned int tableSize) +{ + const uint64x2_t r = {0xe100000000000000ull, 0xc200000000000000ull}; + const uint64x2_t t = vreinterpretq_u64_u8(vrev64q_u8(vld1q_u8(hashKey))); + const uint64x2_t h0 = vextq_u64(t, t, 1); + + uint64x2_t h = h0; + unsigned int i; + for (i=0; i= 16) + { + size_t i=0, s = UnsignedMin(len/16U, 8U); + uint64x2_t d1, d2 = vreinterpretq_u64_u8(vrev64q_u8(vld1q_u8(data+(s-1)*16U))); + uint64x2_t c0 = vdupq_n_u64(0); + uint64x2_t c1 = vdupq_n_u64(0); + uint64x2_t c2 = vdupq_n_u64(0); + + while (true) + { + const uint64x2_t h0 = vld1q_u64(CONST_UINT64_CAST(mtable+(i+0)*16)); + const uint64x2_t h1 = vld1q_u64(CONST_UINT64_CAST(mtable+(i+1)*16)); + const uint64x2_t h2 = veorq_u64(h0, h1); + + if (++i == s) + { + const uint64x2_t t1 = vreinterpretq_u64_u8(vrev64q_u8(vld1q_u8(data))); + d1 = veorq_u64(vextq_u64(t1, t1, 1), x); + c0 = veorq_u64(c0, PMULL_00(d1, h0)); + c2 = veorq_u64(c2, PMULL_10(d1, h1)); + d1 = veorq_u64(d1, SwapWords(d1)); + c1 = veorq_u64(c1, PMULL_00(d1, h2)); + + break; + } + + d1 = vreinterpretq_u64_u8(vrev64q_u8(vld1q_u8(data+(s-i)*16-8))); + c0 = veorq_u64(c0, PMULL_10(d2, h0)); + c2 = veorq_u64(c2, PMULL_10(d1, h1)); + d2 = veorq_u64(d2, d1); + c1 = veorq_u64(c1, PMULL_10(d2, h2)); + + if (++i == s) + { + const uint64x2_t t2 = vreinterpretq_u64_u8(vrev64q_u8(vld1q_u8(data))); + d1 = veorq_u64(vextq_u64(t2, t2, 1), x); + c0 = veorq_u64(c0, PMULL_01(d1, h0)); + c2 = veorq_u64(c2, PMULL_11(d1, h1)); + d1 = veorq_u64(d1, SwapWords(d1)); + c1 = veorq_u64(c1, PMULL_01(d1, h2)); + + break; + } + + const uint64x2_t t3 = vreinterpretq_u64_u8(vrev64q_u8(vld1q_u8(data+(s-i)*16-8))); + d2 = vextq_u64(t3, t3, 1); + c0 = veorq_u64(c0, PMULL_01(d1, h0)); + c2 = veorq_u64(c2, PMULL_01(d2, h1)); + d1 = veorq_u64(d1, d2); + c1 = veorq_u64(c1, PMULL_01(d1, h2)); + } + data += s*16; + len -= s*16; + + c1 = veorq_u64(veorq_u64(c1, c0), c2); + x = GCM_Reduce_PMULL(c0, c1, c2, r); + } + + vst1q_u64(UINT64_CAST(hbuffer), x); + return len; +} + +void GCM_ReverseHashBufferIfNeeded_PMULL(byte *hashBuffer) +{ + if (GetNativeByteOrder() != BIG_ENDIAN_ORDER) + { + const uint8x16_t x = vrev64q_u8(vld1q_u8(hashBuffer)); + vst1q_u8(hashBuffer, vextq_u8(x, x, 8)); + } +} +#endif // CRYPTOPP_ARM_PMULL_AVAILABLE + +// ***************************** SSE ***************************** // + +#if CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE +// SunCC 5.10-5.11 compiler crash. Move GCM_Xor16_SSE2 out-of-line, and place in +// a source file with a SSE architecture switch. Also see GH #226 and GH #284. +void GCM_Xor16_SSE2(byte *a, const byte *b, const byte *c) +{ +# if CRYPTOPP_SSE2_ASM_AVAILABLE && defined(__GNUC__) + asm ("movdqa %1, %%xmm0; pxor %2, %%xmm0; movdqa %%xmm0, %0;" + : "=m" (a[0]) : "m"(b[0]), "m"(c[0])); +# else // CRYPTOPP_SSE2_INTRIN_AVAILABLE + _mm_store_si128(M128_CAST(a), _mm_xor_si128( + _mm_load_si128(CONST_M128_CAST(b)), + _mm_load_si128(CONST_M128_CAST(c)))); +# endif +} +#endif // CRYPTOPP_SSE2_ASM_AVAILABLE + +#if CRYPTOPP_CLMUL_AVAILABLE + +#if 0 +// preserved for testing +void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) +{ + word64 Z0=0, Z1=0, V0, V1; + + typedef BlockGetAndPut Block; + Block::Get(a)(V0)(V1); + + for (int i=0; i<16; i++) + { + for (int j=0x80; j!=0; j>>=1) + { + int x = b[i] & j; + Z0 ^= x ? V0 : 0; + Z1 ^= x ? V1 : 0; + x = (int)V1 & 1; + V1 = (V1>>1) | (V0<<63); + V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0); + } + } + Block::Put(NULLPTR, c)(Z0)(Z1); +} + +__m128i _mm_clmulepi64_si128(const __m128i &a, const __m128i &b, int i) +{ + word64 A[1] = {ByteReverse(((word64*)&a)[i&1])}; + word64 B[1] = {ByteReverse(((word64*)&b)[i>>4])}; + + PolynomialMod2 pa((byte *)A, 8); + PolynomialMod2 pb((byte *)B, 8); + PolynomialMod2 c = pa*pb; + + __m128i output; + for (int i=0; i<16; i++) + ((byte *)&output)[i] = c.GetByte(i); + return output; +} +#endif // Testing + +// Swaps high and low 64-bit words +inline __m128i SwapWords(const __m128i& val) +{ + return _mm_shuffle_epi32(val, _MM_SHUFFLE(1, 0, 3, 2)); +} + +// SunCC 5.11-5.15 compiler crash. Make the function inline +// and parameters non-const. Also see GH #188 and GH #224. +inline __m128i GCM_Reduce_CLMUL(__m128i c0, __m128i c1, __m128i c2, const __m128i& r) +{ + /* + The polynomial to be reduced is c0 * x^128 + c1 * x^64 + c2. c0t below refers to the most + significant half of c0 as a polynomial, which, due to GCM's bit reflection, are in the + rightmost bit positions, and the lowest byte addresses. + + c1 ^= c0t * 0xc200000000000000 + c2t ^= c0t + t = shift (c1t ^ c0b) left 1 bit + c2 ^= t * 0xe100000000000000 + c2t ^= c1b + shift c2 left 1 bit and xor in lowest bit of c1t + */ + c1 = _mm_xor_si128(c1, _mm_slli_si128(c0, 8)); + c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(c0, r, 0x10)); + c0 = _mm_xor_si128(c1, _mm_srli_si128(c0, 8)); + c0 = _mm_slli_epi64(c0, 1); + c0 = _mm_clmulepi64_si128(c0, r, 0); + c2 = _mm_xor_si128(c2, c0); + c2 = _mm_xor_si128(c2, _mm_srli_si128(c1, 8)); + c1 = _mm_unpacklo_epi64(c1, c2); + c1 = _mm_srli_epi64(c1, 63); + c2 = _mm_slli_epi64(c2, 1); + return _mm_xor_si128(c2, c1); +} + +// SunCC 5.13-5.14 compiler crash. Don't make the function inline. +// This is in contrast to GCM_Reduce_CLMUL, which must be inline. +__m128i GCM_Multiply_CLMUL(const __m128i &x, const __m128i &h, const __m128i &r) +{ + const __m128i c0 = _mm_clmulepi64_si128(x,h,0); + const __m128i c1 = _mm_xor_si128(_mm_clmulepi64_si128(x,h,1), _mm_clmulepi64_si128(x,h,0x10)); + const __m128i c2 = _mm_clmulepi64_si128(x,h,0x11); + + return GCM_Reduce_CLMUL(c0, c1, c2, r); +} + +void GCM_SetKeyWithoutResync_CLMUL(const byte *hashKey, byte *mulTable, unsigned int tableSize) +{ + const __m128i r = _mm_set_epi32(0xc2000000, 0x00000000, 0xe1000000, 0x00000000); + const __m128i m = _mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f); + __m128i h0 = _mm_shuffle_epi8(_mm_load_si128(CONST_M128_CAST(hashKey)), m), h = h0; + + unsigned int i; + for (i=0; i= 16) + { + size_t i=0, s = UnsignedMin(len/16, 8U); + __m128i d1 = _mm_loadu_si128(CONST_M128_CAST(data+(s-1)*16)); + __m128i d2 = _mm_shuffle_epi8(d1, m2); + __m128i c0 = _mm_setzero_si128(); + __m128i c1 = _mm_setzero_si128(); + __m128i c2 = _mm_setzero_si128(); + + while (true) + { + const __m128i h0 = _mm_load_si128(CONST_M128_CAST(mtable+(i+0)*16)); + const __m128i h1 = _mm_load_si128(CONST_M128_CAST(mtable+(i+1)*16)); + const __m128i h2 = _mm_xor_si128(h0, h1); + + if (++i == s) + { + d1 = _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(data)), m1); + d1 = _mm_xor_si128(d1, x); + c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d1, h0, 0)); + c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d1, h1, 1)); + d1 = _mm_xor_si128(d1, SwapWords(d1)); + c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d1, h2, 0)); + break; + } + + d1 = _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(data+(s-i)*16-8)), m2); + c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d2, h0, 1)); + c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d1, h1, 1)); + d2 = _mm_xor_si128(d2, d1); + c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d2, h2, 1)); + + if (++i == s) + { + d1 = _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(data)), m1); + d1 = _mm_xor_si128(d1, x); + c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d1, h0, 0x10)); + c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d1, h1, 0x11)); + d1 = _mm_xor_si128(d1, SwapWords(d1)); + c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d1, h2, 0x10)); + break; + } + + d2 = _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(data+(s-i)*16-8)), m1); + c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d1, h0, 0x10)); + c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d2, h1, 0x10)); + d1 = _mm_xor_si128(d1, d2); + c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d1, h2, 0x10)); + } + data += s*16; + len -= s*16; + + c1 = _mm_xor_si128(_mm_xor_si128(c1, c0), c2); + x = GCM_Reduce_CLMUL(c0, c1, c2, r); + } + + _mm_store_si128(M128_CAST(hbuffer), x); + return len; +} + +void GCM_ReverseHashBufferIfNeeded_CLMUL(byte *hashBuffer) +{ + // SSSE3 instruction, but only used with CLMUL + const __m128i mask = _mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f); + _mm_storeu_si128(M128_CAST(hashBuffer), _mm_shuffle_epi8( + _mm_loadu_si128(CONST_M128_CAST(hashBuffer)), mask)); +} +#endif // CRYPTOPP_CLMUL_AVAILABLE + +// ***************************** POWER8 ***************************** // + +#if CRYPTOPP_POWER8_AVAILABLE +void GCM_Xor16_POWER8(byte *a, const byte *b, const byte *c) +{ + VecStore(VecXor(VecLoad(b), VecLoad(c)), a); +} +#endif // CRYPTOPP_POWER8_AVAILABLE + +#if CRYPTOPP_POWER8_VMULL_AVAILABLE + +uint64x2_p GCM_Reduce_VMULL(uint64x2_p c0, uint64x2_p c1, uint64x2_p c2, uint64x2_p r) +{ + const uint64x2_p m1 = {1,1}, m63 = {63,63}; + + c1 = VecXor(c1, VecShiftRightOctet<8>(c0)); + c1 = VecXor(c1, VecIntelMultiply10(c0, r)); + c0 = VecXor(c1, VecShiftLeftOctet<8>(c0)); + c0 = VecIntelMultiply00(vec_sl(c0, m1), r); + c2 = VecXor(c2, c0); + c2 = VecXor(c2, VecShiftLeftOctet<8>(c1)); + c1 = vec_sr(vec_mergeh(c1, c2), m63); + c2 = vec_sl(c2, m1); + + return VecXor(c2, c1); +} + +inline uint64x2_p GCM_Multiply_VMULL(uint64x2_p x, uint64x2_p h, uint64x2_p r) +{ + const uint64x2_p c0 = VecIntelMultiply00(x, h); + const uint64x2_p c1 = VecXor(VecIntelMultiply01(x, h), VecIntelMultiply10(x, h)); + const uint64x2_p c2 = VecIntelMultiply11(x, h); + + return GCM_Reduce_VMULL(c0, c1, c2, r); +} + +inline uint64x2_p LoadHashKey(const byte *hashKey) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint64x2_p key = (uint64x2_p)VecLoad(hashKey); + const uint8x16_p mask = {8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7}; + return VecPermute(key, key, mask); +#else + const uint64x2_p key = (uint64x2_p)VecLoad(hashKey); + const uint8x16_p mask = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0}; + return VecPermute(key, key, mask); +#endif +} + +void GCM_SetKeyWithoutResync_VMULL(const byte *hashKey, byte *mulTable, unsigned int tableSize) +{ + const uint64x2_p r = {0xe100000000000000ull, 0xc200000000000000ull}; + uint64x2_p h = LoadHashKey(hashKey), h0 = h; + + unsigned int i; + uint64_t temp[2]; + + for (i=0; i +inline T SwapWords(const T& data) +{ + return (T)VecRotateLeftOctet<8>(data); +} + +inline uint64x2_p LoadBuffer1(const byte *dataBuffer) +{ +#if (CRYPTOPP_BIG_ENDIAN) + return (uint64x2_p)VecLoad(dataBuffer); +#else + const uint64x2_p data = (uint64x2_p)VecLoad(dataBuffer); + const uint8x16_p mask = {7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8}; + return VecPermute(data, data, mask); +#endif +} + +inline uint64x2_p LoadBuffer2(const byte *dataBuffer) +{ +#if (CRYPTOPP_BIG_ENDIAN) + return (uint64x2_p)SwapWords(VecLoadBE(dataBuffer)); +#else + return (uint64x2_p)VecLoadBE(dataBuffer); +#endif +} + +size_t GCM_AuthenticateBlocks_VMULL(const byte *data, size_t len, const byte *mtable, byte *hbuffer) +{ + const uint64x2_p r = {0xe100000000000000ull, 0xc200000000000000ull}; + uint64x2_p x = (uint64x2_p)VecLoad(hbuffer); + + while (len >= 16) + { + size_t i=0, s = UnsignedMin(len/16, 8U); + uint64x2_p d1, d2 = LoadBuffer1(data+(s-1)*16); + uint64x2_p c0 = {0}, c1 = {0}, c2 = {0}; + + while (true) + { + const uint64x2_p h0 = (uint64x2_p)VecLoad(mtable+(i+0)*16); + const uint64x2_p h1 = (uint64x2_p)VecLoad(mtable+(i+1)*16); + const uint64x2_p h2 = (uint64x2_p)VecXor(h0, h1); + + if (++i == s) + { + d1 = LoadBuffer2(data); + d1 = VecXor(d1, x); + c0 = VecXor(c0, VecIntelMultiply00(d1, h0)); + c2 = VecXor(c2, VecIntelMultiply01(d1, h1)); + d1 = VecXor(d1, SwapWords(d1)); + c1 = VecXor(c1, VecIntelMultiply00(d1, h2)); + break; + } + + d1 = LoadBuffer1(data+(s-i)*16-8); + c0 = VecXor(c0, VecIntelMultiply01(d2, h0)); + c2 = VecXor(c2, VecIntelMultiply01(d1, h1)); + d2 = VecXor(d2, d1); + c1 = VecXor(c1, VecIntelMultiply01(d2, h2)); + + if (++i == s) + { + d1 = LoadBuffer2(data); + d1 = VecXor(d1, x); + c0 = VecXor(c0, VecIntelMultiply10(d1, h0)); + c2 = VecXor(c2, VecIntelMultiply11(d1, h1)); + d1 = VecXor(d1, SwapWords(d1)); + c1 = VecXor(c1, VecIntelMultiply10(d1, h2)); + break; + } + + d2 = LoadBuffer2(data+(s-i)*16-8); + c0 = VecXor(c0, VecIntelMultiply10(d1, h0)); + c2 = VecXor(c2, VecIntelMultiply10(d2, h1)); + d1 = VecXor(d1, d2); + c1 = VecXor(c1, VecIntelMultiply10(d1, h2)); + } + data += s*16; + len -= s*16; + + c1 = VecXor(VecXor(c1, c0), c2); + x = GCM_Reduce_VMULL(c0, c1, c2, r); + } + + VecStore(x, hbuffer); + return len; +} + +void GCM_ReverseHashBufferIfNeeded_VMULL(byte *hashBuffer) +{ + const uint64x2_p mask = {0x08090a0b0c0d0e0full, 0x0001020304050607ull}; + VecStore(VecPermute(VecLoad(hashBuffer), mask), hashBuffer); +} +#endif // CRYPTOPP_POWER8_VMULL_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/gf256.cpp b/external/ours/library/crypto/src/shared/original/gf256.cpp new file mode 100755 index 000000000..c432344f3 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gf256.cpp @@ -0,0 +1,34 @@ +// gf256.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "gf256.h" + +NAMESPACE_BEGIN(CryptoPP) + +GF256::Element GF256::Multiply(Element a, Element b) const +{ + word result = 0, t = b; + + for (unsigned int i=0; i<8; i++) + { + result <<= 1; + if (result & 0x100) + result ^= m_modulus; + + t <<= 1; + if (t & 0x100) + result ^= a; + } + + return (GF256::Element) result; +} + +GF256::Element GF256::MultiplicativeInverse(Element a) const +{ + Element result = a; + for (int i=1; i<7; i++) + result = Multiply(Square(result), a); + return Square(result); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/gf256.h b/external/ours/library/crypto/src/shared/original/gf256.h new file mode 100755 index 000000000..9cef8309f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/gf2_32.cpp b/external/ours/library/crypto/src/shared/original/gf2_32.cpp new file mode 100755 index 000000000..51d10a49d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gf2_32.cpp @@ -0,0 +1,99 @@ +// gf2_32.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "misc.h" +#include "gf2_32.h" + +NAMESPACE_BEGIN(CryptoPP) + +GF2_32::Element GF2_32::Multiply(Element a, Element b) const +{ + word32 table[4]; + table[0] = 0; + table[1] = m_modulus; + if (a & 0x80000000) + { + table[2] = m_modulus ^ (a<<1); + table[3] = a<<1; + } + else + { + table[2] = a<<1; + table[3] = m_modulus ^ (a<<1); + } + +#if CRYPTOPP_FAST_ROTATE(32) + b = rotrConstant<30>(b); + word32 result = table[b&2]; + + for (int i=29; i>=0; --i) + { + b = rotlConstant<1>(b); + result = (result<<1) ^ table[(b&2) + (result>>31)]; + } + + return (b&1) ? result ^ a : result; +#else + word32 result = table[(b>>30) & 2]; + + for (int i=29; i>=0; --i) + result = (result<<1) ^ table[((b>>i)&2) + (result>>31)]; + + return (b&1) ? result ^ a : result; +#endif +} + +GF2_32::Element GF2_32::MultiplicativeInverse(Element a) const +{ + if (a <= 1) // 1 is a special case + return a; + + // warning - don't try to adapt this algorithm for another situation + word32 g0=m_modulus, g1=a, g2=a; + word32 v0=0, v1=1, v2=1; + + CRYPTOPP_ASSERT(g1); + + while (!(g2 & 0x80000000)) + { + g2 <<= 1; + v2 <<= 1; + } + + g2 <<= 1; + v2 <<= 1; + + g0 ^= g2; + v0 ^= v2; + + while (g0 != 1) + { + if (g1 < g0 || ((g0^g1) < g0 && (g0^g1) < g1)) + { + CRYPTOPP_ASSERT(BitPrecision(g1) <= BitPrecision(g0)); + g2 = g1; + v2 = v1; + } + else + { + CRYPTOPP_ASSERT(BitPrecision(g1) > BitPrecision(g0)); + g2 = g0; g0 = g1; g1 = g2; + v2 = v0; v0 = v1; v1 = v2; + } + + while ((g0^g2) >= g2) + { + CRYPTOPP_ASSERT(BitPrecision(g0) > BitPrecision(g2)); + g2 <<= 1; + v2 <<= 1; + } + + CRYPTOPP_ASSERT(BitPrecision(g0) == BitPrecision(g2)); + g0 ^= g2; + v0 ^= v2; + } + + return v0; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/gf2_32.h b/external/ours/library/crypto/src/shared/original/gf2_32.h new file mode 100755 index 000000000..f0d229dff --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/gf2n.cpp b/external/ours/library/crypto/src/shared/original/gf2n.cpp new file mode 100755 index 000000000..452e69825 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gf2n.cpp @@ -0,0 +1,1070 @@ +// gf2n.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "cryptlib.h" +#include "algebra.h" +#include "randpool.h" +#include "filters.h" +#include "smartptr.h" +#include "words.h" +#include "misc.h" +#include "gf2n.h" +#include "oids.h" +#include "asn.h" +#include "cpu.h" + +#include + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::PolynomialMod2; + +#if defined(HAVE_GCC_INIT_PRIORITY) + const PolynomialMod2 g_zero __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 60))) = PolynomialMod2(); + const PolynomialMod2 g_one __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 61))) = PolynomialMod2(1); +#elif defined(HAVE_MSC_INIT_PRIORITY) + #pragma warning(disable: 4075) + #pragma init_seg(".CRT$XCU") + const PolynomialMod2 g_zero; + const PolynomialMod2 g_one(1); + #pragma warning(default: 4075) +#elif defined(HAVE_XLC_INIT_PRIORITY) + #pragma priority(290) + const PolynomialMod2 g_zero; + const PolynomialMod2 g_one(1); +#endif + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if (CRYPTOPP_CLMUL_AVAILABLE) +extern CRYPTOPP_DLL void GF2NT_233_Multiply_Reduce_CLMUL(const word* pA, const word* pB, word* pC); +extern CRYPTOPP_DLL void GF2NT_233_Square_Reduce_CLMUL(const word* pA, word* pC); +#endif + +#if (CRYPTOPP_ARM_PMULL_AVAILABLE) +extern void GF2NT_233_Multiply_Reduce_ARMv8(const word* pA, const word* pB, word* pC); +extern void GF2NT_233_Square_Reduce_ARMv8(const word* pA, word* pC); +#endif + +#if (CRYPTOPP_POWER8_VMULL_AVAILABLE) && 0 +extern void GF2NT_233_Multiply_Reduce_POWER8(const word* pA, const word* pB, word* pC); +extern void GF2NT_233_Square_Reduce_POWER8(const word* pA, word* pC); +#endif + +PolynomialMod2::PolynomialMod2() +{ +} + +PolynomialMod2::PolynomialMod2(word value, size_t bitLength) + : reg(BitsToWords(bitLength)) +{ + CRYPTOPP_ASSERT(value==0 || reg.size()>0); + + if (reg.size() > 0) + { + reg[0] = value; + SetWords(reg+1, 0, reg.size()-1); + } +} + +PolynomialMod2::PolynomialMod2(const PolynomialMod2& t) + : reg(t.reg.size()) +{ + CopyWords(reg, t.reg, reg.size()); +} + +void PolynomialMod2::Randomize(RandomNumberGenerator &rng, size_t nbits) +{ + const size_t nbytes = nbits/8 + 1; + SecByteBlock buf(nbytes); + rng.GenerateBlock(buf, nbytes); + buf[0] = (byte)Crop(buf[0], nbits % 8); + Decode(buf, nbytes); +} + +PolynomialMod2 PolynomialMod2::AllOnes(size_t bitLength) +{ + PolynomialMod2 result((word)0, bitLength); + SetWords(result.reg, ~(word(0)), result.reg.size()); + if (bitLength%WORD_BITS) + result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS); + return result; +} + +void PolynomialMod2::SetBit(size_t n, int value) +{ + if (value) + { + reg.CleanGrow(n/WORD_BITS + 1); + reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS)); + } + else + { + if (n/WORD_BITS < reg.size()) + reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS)); + } +} + +byte PolynomialMod2::GetByte(size_t n) const +{ + if (n/WORD_SIZE >= reg.size()) + return 0; + else + return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); +} + +void PolynomialMod2::SetByte(size_t n, byte value) +{ + reg.CleanGrow(BytesToWords(n+1)); + reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE)); + reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE)); +} + +PolynomialMod2 PolynomialMod2::Monomial(size_t i) +{ + PolynomialMod2 r((word)0, i+1); + r.SetBit(i); + return r; +} + +PolynomialMod2 PolynomialMod2::Trinomial(size_t t0, size_t t1, size_t t2) +{ + PolynomialMod2 r((word)0, t0+1); + r.SetBit(t0); + r.SetBit(t1); + r.SetBit(t2); + return r; +} + +PolynomialMod2 PolynomialMod2::Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4) +{ + PolynomialMod2 r((word)0, t0+1); + r.SetBit(t0); + r.SetBit(t1); + r.SetBit(t2); + r.SetBit(t3); + r.SetBit(t4); + return r; +} + +template +struct NewPolynomialMod2 +{ + PolynomialMod2 * operator()() const + { + return new PolynomialMod2(i); + } +}; + +const PolynomialMod2 &PolynomialMod2::Zero() +{ +#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY) || defined(HAVE_XLC_INIT_PRIORITY) + return g_zero; +#elif defined(CRYPTOPP_CXX11_STATIC_INIT) + static const PolynomialMod2 g_zero; + return g_zero; +#else + return Singleton().Ref(); +#endif +} + +const PolynomialMod2 &PolynomialMod2::One() +{ +#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY) || defined(HAVE_XLC_INIT_PRIORITY) + return g_one; +#elif defined(CRYPTOPP_CXX11_STATIC_INIT) + static const PolynomialMod2 g_one(1); + return g_one; +#else + return Singleton >().Ref(); +#endif +} + +void PolynomialMod2::Decode(const byte *input, size_t inputLen) +{ + StringStore store(input, inputLen); + Decode(store, inputLen); +} + +void PolynomialMod2::Encode(byte *output, size_t outputLen) const +{ + ArraySink sink(output, outputLen); + Encode(sink, outputLen); +} + +void PolynomialMod2::Decode(BufferedTransformation &bt, size_t inputLen) +{ + CRYPTOPP_ASSERT(bt.MaxRetrievable() >= inputLen); + if (bt.MaxRetrievable() < inputLen) + throw InvalidArgument("PolynomialMod2: input length is too small"); + + reg.CleanNew(BytesToWords(inputLen)); + + for (size_t i=inputLen; i > 0; i--) + { + byte b; + (void)bt.Get(b); + reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8; + } +} + +void PolynomialMod2::Encode(BufferedTransformation &bt, size_t outputLen) const +{ + for (size_t i=outputLen; i > 0; i--) + bt.Put(GetByte(i-1)); +} + +void PolynomialMod2::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const +{ + DERGeneralEncoder enc(bt, OCTET_STRING); + Encode(enc, length); + enc.MessageEnd(); +} + +void PolynomialMod2::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length) +{ + BERGeneralDecoder dec(bt, OCTET_STRING); + if (!dec.IsDefiniteLength() || dec.RemainingLength() != length) + BERDecodeError(); + Decode(dec, length); + dec.MessageEnd(); +} + +unsigned int PolynomialMod2::WordCount() const +{ + return (unsigned int)CountWords(reg, reg.size()); +} + +unsigned int PolynomialMod2::ByteCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]); + else + return 0; +} + +unsigned int PolynomialMod2::BitCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]); + else + return 0; +} + +unsigned int PolynomialMod2::Parity() const +{ + unsigned i; + word temp=0; + for (i=0; i= reg.size()) + { + PolynomialMod2 result((word)0, b.reg.size()*WORD_BITS); + XorWords(result.reg, reg, b.reg, reg.size()); + CopyWords(result.reg+reg.size(), b.reg+reg.size(), b.reg.size()-reg.size()); + return result; + } + else + { + PolynomialMod2 result((word)0, reg.size()*WORD_BITS); + XorWords(result.reg, reg, b.reg, b.reg.size()); + CopyWords(result.reg+b.reg.size(), reg+b.reg.size(), reg.size()-b.reg.size()); + return result; + } +} + +PolynomialMod2 PolynomialMod2::And(const PolynomialMod2 &b) const +{ + PolynomialMod2 result((word)0, WORD_BITS*STDMIN(reg.size(), b.reg.size())); + AndWords(result.reg, reg, b.reg, result.reg.size()); + return result; +} + +PolynomialMod2 PolynomialMod2::Times(const PolynomialMod2 &b) const +{ + PolynomialMod2 result((word)0, BitCount() + b.BitCount()); + + for (int i=b.Degree(); i>=0; i--) + { + result <<= 1; + if (b[i]) + XorWords(result.reg, reg, reg.size()); + } + return result; +} + +PolynomialMod2 PolynomialMod2::Squared() const +{ + static const word map[16] = {0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85}; + + PolynomialMod2 result((word)0, 2*reg.size()*WORD_BITS); + + for (unsigned i=0; i> (j/2)) % 16] << j; + + for (j=0; j> (j/2 + WORD_BITS/2)) % 16] << j; + } + + return result; +} + +void PolynomialMod2::Divide(PolynomialMod2 &remainder, PolynomialMod2 "ient, + const PolynomialMod2 ÷nd, const PolynomialMod2 &divisor) +{ + if (!divisor) + throw PolynomialMod2::DivideByZero(); + + int degree = divisor.Degree(); + remainder.reg.CleanNew(BitsToWords(degree+1)); + if (dividend.BitCount() >= divisor.BitCount()) + quotient.reg.CleanNew(BitsToWords(dividend.BitCount() - divisor.BitCount() + 1)); + else + quotient.reg.CleanNew(0); + + for (int i=dividend.Degree(); i>=0; i--) + { + remainder <<= 1; + remainder.reg[0] |= dividend[i]; + if (remainder[degree]) + { + remainder -= divisor; + quotient.SetBit(i); + } + } +} + +PolynomialMod2 PolynomialMod2::DividedBy(const PolynomialMod2 &b) const +{ + PolynomialMod2 remainder, quotient; + PolynomialMod2::Divide(remainder, quotient, *this, b); + return quotient; +} + +PolynomialMod2 PolynomialMod2::Modulo(const PolynomialMod2 &b) const +{ + PolynomialMod2 remainder, quotient; + PolynomialMod2::Divide(remainder, quotient, *this, b); + return remainder; +} + +PolynomialMod2& PolynomialMod2::operator<<=(unsigned int n) +{ +#if defined(CRYPTOPP_DEBUG) + int x=0; CRYPTOPP_UNUSED(x); + CRYPTOPP_ASSERT(SafeConvert(n,x)); +#endif + + if (!reg.size()) + return *this; + + int i; + word u; + word carry=0; + word *r=reg; + + if (n==1) // special case code for most frequent case + { + i = (int)reg.size(); + while (i--) + { + u = *r; + *r = (u << 1) | carry; + carry = u >> (WORD_BITS-1); + r++; + } + + if (carry) + { + reg.Grow(reg.size()+1); + reg[reg.size()-1] = carry; + } + + return *this; + } + + const int shiftWords = n / WORD_BITS; + const int shiftBits = n % WORD_BITS; + + if (shiftBits) + { + i = (int)reg.size(); + while (i--) + { + u = *r; + *r = (u << shiftBits) | carry; + carry = u >> (WORD_BITS-shiftBits); + r++; + } + } + + if (carry) + { + // Thanks to Apatryda, http://github.com/weidai11/cryptopp/issues/64 + const size_t carryIndex = reg.size(); + reg.Grow(reg.size()+shiftWords+!!shiftBits); + reg[carryIndex] = carry; + } + else + reg.Grow(reg.size()+shiftWords); + + if (shiftWords) + { + for (i = (int)reg.size()-1; i>=shiftWords; i--) + reg[i] = reg[i-shiftWords]; + for (; i>=0; i--) + reg[i] = 0; + } + + return *this; +} + +PolynomialMod2& PolynomialMod2::operator>>=(unsigned int n) +{ + if (!reg.size()) + return *this; + + int shiftWords = n / WORD_BITS; + int shiftBits = n % WORD_BITS; + + size_t i; + word u; + word carry=0; + word *r=reg+reg.size()-1; + + if (shiftBits) + { + i = reg.size(); + while (i--) + { + u = *r; + *r = (u >> shiftBits) | carry; + carry = u << (WORD_BITS-shiftBits); + r--; + } + } + + if (shiftWords) + { + for (i=0; i>(unsigned int n) const +{ + PolynomialMod2 result(*this); + return result>>=n; +} + +bool PolynomialMod2::operator!() const +{ + for (unsigned i=0; i s(a.BitCount()/bits+1); + unsigned i; + + static const char upper[]="0123456789ABCDEF"; + static const char lower[]="0123456789abcdef"; + const char* const vec = (out.flags() & std::ios::uppercase) ? upper : lower; + + for (i=0; i*bits < a.BitCount(); i++) + { + int digit=0; + for (int j=0; j().Gcd(a, b); +} + +PolynomialMod2 PolynomialMod2::InverseMod(const PolynomialMod2 &modulus) const +{ + typedef EuclideanDomainOf Domain; + return QuotientRing(Domain(), modulus).MultiplicativeInverse(*this); +} + +bool PolynomialMod2::IsIrreducible() const +{ + signed int d = Degree(); + if (d <= 0) + return false; + + PolynomialMod2 t(2), u(t); + for (int i=1; i<=d/2; i++) + { + u = u.Squared()%(*this); + if (!Gcd(u+t, *this).IsUnit()) + return false; + } + return true; +} + +// ******************************************************** + +GF2NP::GF2NP(const PolynomialMod2 &modulus) + : QuotientRing >(EuclideanDomainOf(), modulus), m(modulus.Degree()) +{ +} + +GF2NP::Element GF2NP::SquareRoot(const Element &a) const +{ + Element r = a; + for (unsigned int i=1; i c1 && c1 > c2 && c2==0); +} + +const GF2NT::Element& GF2NT::MultiplicativeInverse(const Element &a) const +{ + if (t0-t1 < WORD_BITS) + return GF2NP::MultiplicativeInverse(a); + + SecWordBlock T(m_modulus.reg.size() * 4); + word *b = T; + word *c = T+m_modulus.reg.size(); + word *f = T+2*m_modulus.reg.size(); + word *g = T+3*m_modulus.reg.size(); + size_t bcLen=1, fgLen=m_modulus.reg.size(); + unsigned int k=0; + + SetWords(T, 0, 3*m_modulus.reg.size()); + b[0]=1; + CRYPTOPP_ASSERT(a.reg.size() <= m_modulus.reg.size()); + CopyWords(f, a.reg, a.reg.size()); + CopyWords(g, m_modulus.reg, m_modulus.reg.size()); + + while (1) + { + word t=f[0]; + while (!t) + { + ShiftWordsRightByWords(f, fgLen, 1); + if (c[bcLen-1]) + bcLen++; + CRYPTOPP_ASSERT(bcLen <= m_modulus.reg.size()); + ShiftWordsLeftByWords(c, bcLen, 1); + k+=WORD_BITS; + t=f[0]; + } + + unsigned int i=0; + while (t%2 == 0) + { + t>>=1; + i++; + } + k+=i; + + if (t==1 && CountWords(f, fgLen)==1) + break; + + if (i==1) + { + ShiftWordsRightByBits(f, fgLen, 1); + t=ShiftWordsLeftByBits(c, bcLen, 1); + } + else + { + ShiftWordsRightByBits(f, fgLen, i); + t=ShiftWordsLeftByBits(c, bcLen, i); + } + if (t) + { + c[bcLen] = t; + bcLen++; + CRYPTOPP_ASSERT(bcLen <= m_modulus.reg.size()); + } + + if (f[fgLen-1]==0 && g[fgLen-1]==0) + fgLen--; + + if (f[fgLen-1] < g[fgLen-1]) + { + std::swap(f, g); + std::swap(b, c); + } + + XorWords(f, g, fgLen); + XorWords(b, c, bcLen); + } + + while (k >= WORD_BITS) + { + word temp = b[0]; + // right shift b + for (unsigned i=0; i+1> j) & 1) << (t1 + j); + const unsigned int shift = t1 + j; + CRYPTOPP_ASSERT(shift < WORD_BITS); + temp ^= (shift < WORD_BITS) ? (((temp >> j) & 1) << shift) : 0; + } + else + b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS; + + if (t1 % WORD_BITS) + b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS); + + if (t0%WORD_BITS) + { + b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS; + b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS); + } + else + b[t0/WORD_BITS-1] ^= temp; + + k -= WORD_BITS; + } + + if (k) + { + word temp = b[0] << (WORD_BITS - k); + ShiftWordsRightByBits(b, BitsToWords(m), k); + + if (t1 < WORD_BITS) + { + for (unsigned int j=0; j> j) & 1) << (t1 + j); + const unsigned int shift = t1 + j; + CRYPTOPP_ASSERT(shift < WORD_BITS); + temp ^= (shift < WORD_BITS) ? (((temp >> j) & 1) << shift) : 0; + } + } + else + { + b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS; + } + + if (t1 % WORD_BITS) + b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS); + + if (t0%WORD_BITS) + { + b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS; + b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS); + } + else + b[t0/WORD_BITS-1] ^= temp; + } + + CopyWords(result.reg.begin(), b, result.reg.size()); + return result; +} + +const GF2NT::Element& GF2NT::Multiply(const Element &a, const Element &b) const +{ + size_t aSize = STDMIN(a.reg.size(), result.reg.size()); + Element r((word)0, m); + + for (int i=m-1; i>=0; i--) + { + if (r[m-1]) + { + ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1); + XorWords(r.reg.begin(), m_modulus.reg, r.reg.size()); + } + else + ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1); + + if (b[i]) + XorWords(r.reg.begin(), a.reg, aSize); + } + + if (m%WORD_BITS) + r.reg.begin()[r.reg.size()-1] = (word)Crop(r.reg[r.reg.size()-1], m%WORD_BITS); + + CopyWords(result.reg.begin(), r.reg.begin(), result.reg.size()); + return result; +} + +const GF2NT::Element& GF2NT::Reduced(const Element &a) const +{ + if (t0-t1 < WORD_BITS) + return m_domain.Mod(a, m_modulus); + + SecWordBlock b(a.reg); + + size_t i; + for (i=b.size()-1; i>=BitsToWords(t0); i--) + { + word temp = b[i]; + + if (t0%WORD_BITS) + { + b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS; + b[i-t0/WORD_BITS-1] ^= temp << (WORD_BITS - t0%WORD_BITS); + } + else + b[i-t0/WORD_BITS] ^= temp; + + if ((t0-t1)%WORD_BITS) + { + b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS; + b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS); + } + else + b[i-(t0-t1)/WORD_BITS] ^= temp; + } + + if (i==BitsToWords(t0)-1 && t0%WORD_BITS) + { + word mask = ((word)1<<(t0%WORD_BITS))-1; + word temp = b[i] & ~mask; + b[i] &= mask; + + b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS; + + if ((t0-t1)%WORD_BITS) + { + b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS; + if ((t0-t1)%WORD_BITS > t0%WORD_BITS) + b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS); + else + CRYPTOPP_ASSERT(temp << (WORD_BITS - (t0-t1)%WORD_BITS) == 0); + } + else + b[i-(t0-t1)/WORD_BITS] ^= temp; + } + + SetWords(result.reg.begin(), 0, result.reg.size()); + CopyWords(result.reg.begin(), b, STDMIN(b.size(), result.reg.size())); + return result; +} + +void GF2NP::DEREncodeElement(BufferedTransformation &out, const Element &a) const +{ + a.DEREncodeAsOctetString(out, MaxElementByteLength()); +} + +void GF2NP::BERDecodeElement(BufferedTransformation &in, Element &a) const +{ + a.BERDecodeAsOctetString(in, MaxElementByteLength()); +} + +void GF2NT::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + ASN1::characteristic_two_field().DEREncode(seq); + DERSequenceEncoder parameters(seq); + DEREncodeUnsigned(parameters, m); + ASN1::tpBasis().DEREncode(parameters); + DEREncodeUnsigned(parameters, t1); + parameters.MessageEnd(); + seq.MessageEnd(); +} + +void GF2NPP::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + ASN1::characteristic_two_field().DEREncode(seq); + DERSequenceEncoder parameters(seq); + DEREncodeUnsigned(parameters, m); + ASN1::ppBasis().DEREncode(parameters); + DERSequenceEncoder pentanomial(parameters); + DEREncodeUnsigned(pentanomial, t3); + DEREncodeUnsigned(pentanomial, t2); + DEREncodeUnsigned(pentanomial, t1); + pentanomial.MessageEnd(); + parameters.MessageEnd(); + seq.MessageEnd(); +} + +GF2NP * BERDecodeGF2NP(BufferedTransformation &bt) +{ + member_ptr result; + + BERSequenceDecoder seq(bt); + if (OID(seq) != ASN1::characteristic_two_field()) + BERDecodeError(); + BERSequenceDecoder parameters(seq); + unsigned int m; + BERDecodeUnsigned(parameters, m); + OID oid(parameters); + if (oid == ASN1::tpBasis()) + { + unsigned int t1; + BERDecodeUnsigned(parameters, t1); + result.reset(new GF2NT(m, t1, 0)); + } + else if (oid == ASN1::ppBasis()) + { + unsigned int t1, t2, t3; + BERSequenceDecoder pentanomial(parameters); + BERDecodeUnsigned(pentanomial, t3); + BERDecodeUnsigned(pentanomial, t2); + BERDecodeUnsigned(pentanomial, t1); + pentanomial.MessageEnd(); + result.reset(new GF2NPP(m, t3, t2, t1, 0)); + } + else + { + BERDecodeError(); + return NULLPTR; + } + parameters.MessageEnd(); + seq.MessageEnd(); + + return result.release(); +} + +// ******************************************************** + +GF2NT233::GF2NT233(unsigned int c0, unsigned int c1, unsigned int c2) + : GF2NT(c0, c1, c2) +{ + CRYPTOPP_ASSERT(c0 > c1 && c1 > c2 && c2==0); +} + +const GF2NT::Element& GF2NT233::Multiply(const Element &a, const Element &b) const +{ +#if (CRYPTOPP_CLMUL_AVAILABLE) + if (HasCLMUL()) + { + CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256); + CRYPTOPP_ASSERT(b.reg.size()*WORD_BITS == 256); + CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256); + + const word* pA = a.reg.begin(); + const word* pB = b.reg.begin(); + word* pR = result.reg.begin(); + + GF2NT_233_Multiply_Reduce_CLMUL(pA, pB, pR); + return result; + } + else +#elif (CRYPTOPP_ARM_PMULL_AVAILABLE) + if (HasPMULL()) + { + CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256); + CRYPTOPP_ASSERT(b.reg.size()*WORD_BITS == 256); + CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256); + + const word* pA = a.reg.begin(); + const word* pB = b.reg.begin(); + word* pR = result.reg.begin(); + + GF2NT_233_Multiply_Reduce_ARMv8(pA, pB, pR); + return result; + } + else +#elif (CRYPTOPP_POWER8_VMULL_AVAILABLE) && 0 + if (HasPMULL()) + { + CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256); + CRYPTOPP_ASSERT(b.reg.size()*WORD_BITS == 256); + CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256); + + const word* pA = a.reg.begin(); + const word* pB = b.reg.begin(); + word* pR = result.reg.begin(); + + GF2NT_233_Multiply_Reduce_POWER8(pA, pB, pR); + return result; + } + else +#endif + + return GF2NT::Multiply(a, b); +} + +const GF2NT::Element& GF2NT233::Square(const Element &a) const +{ +#if (CRYPTOPP_CLMUL_AVAILABLE) + if (HasCLMUL()) + { + CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256); + CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256); + + const word* pA = a.reg.begin(); + word* pR = result.reg.begin(); + + GF2NT_233_Square_Reduce_CLMUL(pA, pR); + return result; + } + else +#elif (CRYPTOPP_ARM_PMULL_AVAILABLE) + if (HasPMULL()) + { + CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256); + CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256); + + const word* pA = a.reg.begin(); + word* pR = result.reg.begin(); + + GF2NT_233_Square_Reduce_ARMv8(pA, pR); + return result; + } + else +#elif (CRYPTOPP_POWER8_VMULL_AVAILABLE) && 0 + if (HasPMULL()) + { + CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256); + CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256); + + const word* pA = a.reg.begin(); + word* pR = result.reg.begin(); + + GF2NT_233_Square_Reduce_POWER8(pA, pR); + return result; + } + else +#endif + + return GF2NT::Square(a); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/gf2n.h b/external/ours/library/crypto/src/shared/original/gf2n.h new file mode 100755 index 000000000..86cf3b4c0 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gf2n.h @@ -0,0 +1,404 @@ +// 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 Excpetion 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 + 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 + 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/external/ours/library/crypto/src/shared/original/gf2n_simd.cpp b/external/ours/library/crypto/src/shared/original/gf2n_simd.cpp new file mode 100755 index 000000000..e65439848 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gf2n_simd.cpp @@ -0,0 +1,614 @@ +// gf2n_simd.cpp - written and placed in the public domain by Jeffrey Walton +// Also based on PCLMULQDQ code by Jankowski, Laurent and +// O'Mahony from Intel (see reference below). +// +// This source file uses intrinsics and built-ins to gain access to +// CLMUL, ARMv8a, and Power8 instructions. A separate source file is +// needed because additional CXXFLAGS are required to enable the +// appropriate instructions sets in some build configurations. +// +// Several speedups were taken from Intel Polynomial Multiplication +// Instruction and its Usage for Elliptic Curve Cryptography, by +// Krzysztof Jankowski, Pierre Laurent and Aidan O'Mahony, +// https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/polynomial-multiplication-instructions-paper.pdf +// There may be more speedups available, see https://eprint.iacr.org/2011/589.pdf. +// The IACR paper performs some optimizations that the compiler is +// expected to perform, like Common Subexpression Elimination to save +// on variables (among others). Note that the compiler may miss the +// optimization so the IACR paper is useful. However, the code is GPL3 +// and toxic for some users of the library, so it is not used here... + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "gf2n.h" + +#if (CRYPTOPP_CLMUL_AVAILABLE) +# include +# include +#endif + +#if (CRYPTOPP_ARM_PMULL_AVAILABLE) +# include "arm_simd.h" +#endif + +#if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +# include "ppc_simd.h" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char GF2N_SIMD_FNAME[] = __FILE__; + +ANONYMOUS_NAMESPACE_BEGIN + +// ************************** ARMv8 ************************** // + +using CryptoPP::word; + +#if (CRYPTOPP_ARM_PMULL_AVAILABLE) + +// c1c0 = a * b +inline void +F2N_Multiply_128x128_ARMv8(uint64x2_t& c1, uint64x2_t& c0, const uint64x2_t& a, const uint64x2_t& b) +{ + uint64x2_t t1, t2, z0={0}; + + c0 = PMULL_00(a, b); + c1 = PMULL_11(a, b); + t1 = vmovq_n_u64(vgetq_lane_u64(a, 1)); + t1 = veorq_u64(a, t1); + t2 = vmovq_n_u64(vgetq_lane_u64(b, 1)); + t2 = veorq_u64(b, t2); + t1 = PMULL_00(t1, t2); + t1 = veorq_u64(c0, t1); + t1 = veorq_u64(c1, t1); + t2 = t1; + t1 = vextq_u64(z0, t1, 1); + t2 = vextq_u64(t2, z0, 1); + c0 = veorq_u64(c0, t1); + c1 = veorq_u64(c1, t2); +} + +// c3c2c1c0 = a1a0 * b1b0 +inline void +F2N_Multiply_256x256_ARMv8(uint64x2_t& c3, uint64x2_t& c2, uint64x2_t& c1, uint64x2_t& c0, + const uint64x2_t& b1, const uint64x2_t& b0, const uint64x2_t& a1, const uint64x2_t& a0) +{ + uint64x2_t c4, c5; + uint64x2_t x0=a0, x1=a1, y0=b0, y1=b1; + + F2N_Multiply_128x128_ARMv8(c1, c0, x0, y0); + F2N_Multiply_128x128_ARMv8(c3, c2, x1, y1); + + x0 = veorq_u64(x0, x1); + y0 = veorq_u64(y0, y1); + + F2N_Multiply_128x128_ARMv8(c5, c4, x0, y0); + + c4 = veorq_u64(c4, c0); + c4 = veorq_u64(c4, c2); + c5 = veorq_u64(c5, c1); + c5 = veorq_u64(c5, c3); + c1 = veorq_u64(c1, c4); + c2 = veorq_u64(c2, c5); +} + +// c3c2c1c0 = a1a0 * a1a0 +inline void +F2N_Square_256_ARMv8(uint64x2_t& c3, uint64x2_t& c2, uint64x2_t& c1, + uint64x2_t& c0, const uint64x2_t& a1, const uint64x2_t& a0) +{ + c0 = PMULL_00(a0, a0); + c1 = PMULL_11(a0, a0); + c2 = PMULL_00(a1, a1); + c3 = PMULL_11(a1, a1); +} + +// x = (x << n), z = 0 +template +inline uint64x2_t ShiftLeft128_ARMv8(uint64x2_t x) +{ + uint64x2_t u=x, v, z={0}; + x = vshlq_n_u64(x, N); + u = vshrq_n_u64(u, (64-N)); + v = vcombine_u64(vget_low_u64(z), vget_low_u64(u)); + x = vorrq_u64(x, v); + return x; +} + +// c1c0 = c3c2c1c0 MOD p. This is a Barrett reduction. Reading at +// Intel paper or https://github.com/antonblanchard/crc32-vpmsum. +inline void +GF2NT_233_Reduce_ARMv8(uint64x2_t& c3, uint64x2_t& c2, uint64x2_t& c1, uint64x2_t& c0) +{ + const unsigned int mask[4] = { + 0xffffffff, 0xffffffff, 0xffffffff, 0x000001ff, + }; + + uint64x2_t b3, b2, b1, /*b0,*/ a1, a0, m0, z0={0}; + m0 = vreinterpretq_u64_u32(vld1q_u32(mask)); + b1 = c1; a1 = c1; + a0 = vcombine_u64(vget_low_u64(c1), vget_low_u64(z0)); + a1 = vshlq_n_u64(a1, 23); + a1 = vshrq_n_u64(a1, 23); + c1 = vorrq_u64(a1, a0); + b2 = vshrq_n_u64(c2, (64-23)); + c3 = ShiftLeft128_ARMv8<23>(c3); + a0 = vcombine_u64(vget_high_u64(b2), vget_high_u64(z0)); + c3 = vorrq_u64(c3, a0); + b1 = vshrq_n_u64(b1, (64-23)); + c2 = ShiftLeft128_ARMv8<23>(c2); + a0 = vcombine_u64(vget_high_u64(b1), vget_high_u64(z0)); + c2 = vorrq_u64(c2, a0); + b3 = c3; + b2 = vshrq_n_u64(c2, (64-10)); + b3 = ShiftLeft128_ARMv8<10>(b3); + a0 = vcombine_u64(vget_high_u64(b2), vget_high_u64(z0)); + b3 = vorrq_u64(b3, a0); + a0 = vcombine_u64(vget_high_u64(c3), vget_high_u64(z0)); + b3 = veorq_u64(b3, a0); + b1 = vshrq_n_u64(b3, (64-23)); + b3 = ShiftLeft128_ARMv8<23>(b3); + b3 = vcombine_u64(vget_high_u64(b3), vget_high_u64(z0)); + b3 = vorrq_u64(b3, b1); + c2 = veorq_u64(c2, b3); + b3 = c3; + b2 = vshrq_n_u64(c2, (64-10)); + b3 = ShiftLeft128_ARMv8<10>(b3); + b2 = vcombine_u64(vget_high_u64(b2), vget_high_u64(z0)); + b3 = vorrq_u64(b3, b2); + b2 = c2; + b2 = ShiftLeft128_ARMv8<10>(b2); + a0 = vcombine_u64(vget_low_u64(z0), vget_low_u64(b2)); + c2 = veorq_u64(c2, a0); + a0 = vcombine_u64(vget_low_u64(z0), vget_low_u64(b3)); + a1 = vcombine_u64(vget_high_u64(b2), vget_high_u64(z0)); + a0 = vorrq_u64(a0, a1); + c3 = veorq_u64(c3, a0); + c0 = veorq_u64(c0, c2); + c1 = veorq_u64(c1, c3); + c1 = vandq_u64(c1, m0); +} + +#endif + +// ************************** SSE ************************** // + +#if (CRYPTOPP_CLMUL_AVAILABLE) + +using CryptoPP::word; + +// c1c0 = a * b +inline void +F2N_Multiply_128x128_CLMUL(__m128i& c1, __m128i& c0, const __m128i& a, const __m128i& b) +{ + __m128i t1, t2; + + c0 = _mm_clmulepi64_si128(a, b, 0x00); + c1 = _mm_clmulepi64_si128(a, b, 0x11); + t1 = _mm_shuffle_epi32(a, 0xEE); + t1 = _mm_xor_si128(a, t1); + t2 = _mm_shuffle_epi32(b, 0xEE); + t2 = _mm_xor_si128(b, t2); + t1 = _mm_clmulepi64_si128(t1, t2, 0x00); + t1 = _mm_xor_si128(c0, t1); + t1 = _mm_xor_si128(c1, t1); + t2 = t1; + t1 = _mm_slli_si128(t1, 8); + t2 = _mm_srli_si128(t2, 8); + c0 = _mm_xor_si128(c0, t1); + c1 = _mm_xor_si128(c1, t2); +} + +// c3c2c1c0 = a1a0 * b1b0 +inline void +F2N_Multiply_256x256_CLMUL(__m128i& c3, __m128i& c2, __m128i& c1, __m128i& c0, + const __m128i& b1, const __m128i& b0, const __m128i& a1, const __m128i& a0) +{ + __m128i c4, c5; + __m128i x0=a0, x1=a1, y0=b0, y1=b1; + + F2N_Multiply_128x128_CLMUL(c1, c0, x0, y0); + F2N_Multiply_128x128_CLMUL(c3, c2, x1, y1); + + x0 = _mm_xor_si128(x0, x1); + y0 = _mm_xor_si128(y0, y1); + + F2N_Multiply_128x128_CLMUL(c5, c4, x0, y0); + + c4 = _mm_xor_si128(c4, c0); + c4 = _mm_xor_si128(c4, c2); + c5 = _mm_xor_si128(c5, c1); + c5 = _mm_xor_si128(c5, c3); + c1 = _mm_xor_si128(c1, c4); + c2 = _mm_xor_si128(c2, c5); +} + +// c3c2c1c0 = a1a0 * a1a0 +inline void +F2N_Square_256_CLMUL(__m128i& c3, __m128i& c2, __m128i& c1, + __m128i& c0, const __m128i& a1, const __m128i& a0) +{ + c0 = _mm_clmulepi64_si128(a0, a0, 0x00); + c1 = _mm_clmulepi64_si128(a0, a0, 0x11); + c2 = _mm_clmulepi64_si128(a1, a1, 0x00); + c3 = _mm_clmulepi64_si128(a1, a1, 0x11); +} + +// x = (x << n), z = 0 +template +inline __m128i ShiftLeft128_SSE(__m128i x, const __m128i& z) +{ + __m128i u=x, v; + x = _mm_slli_epi64(x, N); + u = _mm_srli_epi64(u, (64-N)); + v = _mm_unpacklo_epi64(z, u); + x = _mm_or_si128(x, v); + return x; +} + +// c1c0 = c3c2c1c0 MOD p. This is a Barrett reduction. Reading at +// Intel paper or https://github.com/antonblanchard/crc32-vpmsum. +inline void +GF2NT_233_Reduce_CLMUL(__m128i& c3, __m128i& c2, __m128i& c1, __m128i& c0) +{ + const unsigned int m[4] = { + 0xffffffff, 0xffffffff, 0xffffffff, 0x000001ff + }; + + __m128i b3, b2, b1, /*b0,*/ a1, a0, m0, z0; + m0 = _mm_set_epi32(m[3], m[2], m[1], m[0]); + z0 = _mm_setzero_si128(); + b1 = c1; a1 = c1; + a0 = _mm_move_epi64(c1); + a1 = _mm_slli_epi64(a1, 23); + a1 = _mm_srli_epi64(a1, 23); + c1 = _mm_or_si128(a1, a0); + b2 = _mm_srli_epi64(c2, (64-23)); + c3 = ShiftLeft128_SSE<23>(c3, z0); + a0 = _mm_unpackhi_epi64(b2, z0); + c3 = _mm_or_si128(c3, a0); + b1 = _mm_srli_epi64(b1, (64-23)); + c2 = ShiftLeft128_SSE<23>(c2, z0); + a0 = _mm_unpackhi_epi64(b1, z0); + c2 = _mm_or_si128(c2, a0); + b3 = c3; + b2 = _mm_srli_epi64(c2, (64-10)); + b3 = ShiftLeft128_SSE<10>(b3, z0); + a0 = _mm_unpackhi_epi64(b2, z0); + b3 = _mm_or_si128(b3, a0); + a0 = _mm_unpackhi_epi64(c3, z0); + b3 = _mm_xor_si128(b3, a0); + b1 = _mm_srli_epi64(b3, (64-23)); + b3 = ShiftLeft128_SSE<23>(b3, z0); + b3 = _mm_unpackhi_epi64(b3, z0); + b3 = _mm_or_si128(b3, b1); + c2 = _mm_xor_si128(c2, b3); + b3 = c3; + b2 = _mm_srli_epi64(c2, (64-10)); + b3 = ShiftLeft128_SSE<10>(b3, z0); + b2 = _mm_unpackhi_epi64(b2, z0); + b3 = _mm_or_si128(b3, b2); + b2 = c2; + b2 = ShiftLeft128_SSE<10>(b2, z0); + a0 = _mm_unpacklo_epi64(z0, b2); + c2 = _mm_xor_si128(c2, a0); + a0 = _mm_unpacklo_epi64(z0, b3); + a1 = _mm_unpackhi_epi64(b2, z0); + a0 = _mm_or_si128(a0, a1); + c3 = _mm_xor_si128(c3, a0); + c0 = _mm_xor_si128(c0, c2); + c1 = _mm_xor_si128(c1, c3); + c1 = _mm_and_si128(c1, m0); +} + +#endif + +// ************************* Power8 ************************* // + +#if (CRYPTOPP_POWER8_VMULL_AVAILABLE) && 0 + +using CryptoPP::byte; +using CryptoPP::word; +using CryptoPP::uint8x16_p; +using CryptoPP::uint64x2_p; + +using CryptoPP::VecLoad; +using CryptoPP::VecStore; + +using CryptoPP::VecOr; +using CryptoPP::VecXor; +using CryptoPP::VecAnd; + +using CryptoPP::VecPermute; +using CryptoPP::VecMergeLow; +using CryptoPP::VecMergeHigh; +using CryptoPP::VecShiftLeft; +using CryptoPP::VecShiftRight; + +using CryptoPP::VecIntelMultiply00; +using CryptoPP::VecIntelMultiply11; + +// c1c0 = a * b +inline void +F2N_Multiply_128x128_POWER8(uint64x2_p& c1, uint64x2_p& c0, const uint64x2_p& a, const uint64x2_p& b) +{ + uint64x2_p t1, t2; + const uint64x2_p z0={0}; + + c0 = VecIntelMultiply00(a, b); + c1 = VecIntelMultiply11(a, b); + t1 = VecMergeLow(a, a); + t1 = VecXor(a, t1); + t2 = VecMergeLow(b, b); + t2 = VecXor(b, t2); + t1 = VecIntelMultiply00(t1, t2); + t1 = VecXor(c0, t1); + t1 = VecXor(c1, t1); + t2 = t1; + t1 = VecMergeHigh(z0, t1); + t2 = VecMergeLow(t2, z0); + c0 = VecXor(c0, t1); + c1 = VecXor(c1, t2); +} + +// c3c2c1c0 = a1a0 * b1b0 +inline void +F2N_Multiply_256x256_POWER8(uint64x2_p& c3, uint64x2_p& c2, uint64x2_p& c1, uint64x2_p& c0, + const uint64x2_p& b1, const uint64x2_p& b0, const uint64x2_p& a1, const uint64x2_p& a0) +{ + uint64x2_p c4, c5; + uint64x2_p x0=a0, x1=a1, y0=b0, y1=b1; + + F2N_Multiply_128x128_POWER8(c1, c0, x0, y0); + F2N_Multiply_128x128_POWER8(c3, c2, x1, y1); + + x0 = VecXor(x0, x1); + y0 = VecXor(y0, y1); + + F2N_Multiply_128x128_POWER8(c5, c4, x0, y0); + + c4 = VecXor(c4, c0); + c4 = VecXor(c4, c2); + c5 = VecXor(c5, c1); + c5 = VecXor(c5, c3); + c1 = VecXor(c1, c4); + c2 = VecXor(c2, c5); +} + +// c3c2c1c0 = a1a0 * a1a0 +inline void +F2N_Square_256_POWER8(uint64x2_p& c3, uint64x2_p& c2, uint64x2_p& c1, + uint64x2_p& c0, const uint64x2_p& a1, const uint64x2_p& a0) +{ + c0 = VecIntelMultiply00(a0, a0); + c1 = VecIntelMultiply11(a0, a0); + c2 = VecIntelMultiply00(a1, a1); + c3 = VecIntelMultiply11(a1, a1); +} + +// x = (x << n), z = 0 +template +inline uint64x2_p ShiftLeft128_POWER8(uint64x2_p x) +{ + uint64x2_p u=x, v; + const uint64x2_p z={0}; + + x = VecShiftLeft(x); + u = VecShiftRight<64-N>(u); + v = VecMergeHigh(z, u); + x = VecOr(x, v); + return x; +} + +// c1c0 = c3c2c1c0 MOD p. This is a Barrett reduction. Reading at +// Intel paper or https://github.com/antonblanchard/crc32-vpmsum. +inline void +GF2NT_233_Reduce_POWER8(uint64x2_p& c3, uint64x2_p& c2, uint64x2_p& c1, uint64x2_p& c0) +{ + const uint64_t mod[] = {W64LIT(0xffffffffffffffff), W64LIT(0x01ffffffffff)}; + const uint64x2_p m0 = (uint64x2_p)VecLoad(mod); + + uint64x2_p b3, b2, b1, /*b0,*/ a1, a0; + const uint64x2_p z0={0}; + + b1 = c1; a1 = c1; + a0 = VecMergeHigh(c1, z0); + a1 = VecShiftLeft<23>(a1); + a1 = VecShiftRight<23>(a1); + c1 = VecOr(a1, a0); + b2 = VecShiftRight<64-23>(c2); + c3 = ShiftLeft128_POWER8<23>(c3); + a0 = VecMergeLow(b2, z0); + c3 = VecOr(c3, a0); + b1 = VecShiftRight<64-23>(b1); + c2 = ShiftLeft128_POWER8<23>(c2); + a0 = VecMergeLow(b1, z0); + c2 = VecOr(c2, a0); + b3 = c3; + b2 = VecShiftRight<64-10>(c2); + b3 = ShiftLeft128_POWER8<10>(b3); + a0 = VecMergeLow(b2, z0); + b3 = VecOr(b3, a0); + a0 = VecMergeLow(c3, z0); + b3 = VecXor(b3, a0); + b1 = VecShiftRight<64-23>(b3); + b3 = ShiftLeft128_POWER8<23>(b3); + b3 = VecMergeLow(b3, z0); + b3 = VecOr(b3, b1); + c2 = VecXor(c2, b3); + b3 = c3; + b2 = VecShiftRight<64-10>(c2); + b3 = ShiftLeft128_POWER8<10>(b3); + b2 = VecMergeLow(b2, z0); + b3 = VecOr(b3, b2); + b2 = c2; + b2 = ShiftLeft128_POWER8<10>(b2); + a0 = VecMergeHigh(z0, b2); + c2 = VecXor(c2, a0); + a0 = VecMergeHigh(z0, b3); + a1 = VecMergeLow(b2, z0); + a0 = VecOr(a0, a1); + c3 = VecXor(c3, a0); + c0 = VecXor(c0, c2); + c1 = VecXor(c1, c3); + c1 = VecAnd(c1, m0); +} + +#endif + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if (CRYPTOPP_CLMUL_AVAILABLE) + +void +GF2NT_233_Multiply_Reduce_CLMUL(const word* pA, const word* pB, word* pC) +{ + enum {S=sizeof(__m128i)/sizeof(word)}; + __m128i a0 = _mm_loadu_si128(reinterpret_cast(pA+0*S)); + __m128i a1 = _mm_loadu_si128(reinterpret_cast(pA+1*S)); + __m128i b0 = _mm_loadu_si128(reinterpret_cast(pB+0*S)); + __m128i b1 = _mm_loadu_si128(reinterpret_cast(pB+1*S)); + + __m128i c0, c1, c2, c3; + F2N_Multiply_256x256_CLMUL(c3, c2, c1, c0, a1, a0, b1, b0); + GF2NT_233_Reduce_CLMUL(c3, c2, c1, c0); + + _mm_storeu_si128(reinterpret_cast<__m128i*>(pC+0*S), c0); + _mm_storeu_si128(reinterpret_cast<__m128i*>(pC+1*S), c1); +} + +void +GF2NT_233_Square_Reduce_CLMUL(const word* pA, word* pC) +{ + enum {S=sizeof(__m128i)/sizeof(word)}; + __m128i a0 = _mm_loadu_si128(reinterpret_cast(pA+0*S)); + __m128i a1 = _mm_loadu_si128(reinterpret_cast(pA+1*S)); + + __m128i c0, c1, c2, c3; + F2N_Square_256_CLMUL(c3, c2, c1, c0, a1, a0); + GF2NT_233_Reduce_CLMUL(c3, c2, c1, c0); + + _mm_storeu_si128(reinterpret_cast<__m128i*>(pC+0*S), c0); + _mm_storeu_si128(reinterpret_cast<__m128i*>(pC+1*S), c1); +} + +#elif (CRYPTOPP_ARM_PMULL_AVAILABLE) + +void +GF2NT_233_Multiply_Reduce_ARMv8(const word* pA, const word* pB, word* pC) +{ + // word is either 32-bit or 64-bit, depending on the platform. + // Load using a 32-bit pointer to avoid possible alignment issues. + const uint32_t* pAA = reinterpret_cast(pA); + const uint32_t* pBB = reinterpret_cast(pB); + + uint64x2_t a0 = vreinterpretq_u64_u32(vld1q_u32(pAA+0)); + uint64x2_t a1 = vreinterpretq_u64_u32(vld1q_u32(pAA+4)); + uint64x2_t b0 = vreinterpretq_u64_u32(vld1q_u32(pBB+0)); + uint64x2_t b1 = vreinterpretq_u64_u32(vld1q_u32(pBB+4)); + + uint64x2_t c0, c1, c2, c3; + F2N_Multiply_256x256_ARMv8(c3, c2, c1, c0, a1, a0, b1, b0); + GF2NT_233_Reduce_ARMv8(c3, c2, c1, c0); + + uint32_t* pCC = reinterpret_cast(pC); + vst1q_u32(pCC+0, vreinterpretq_u32_u64(c0)); + vst1q_u32(pCC+4, vreinterpretq_u32_u64(c1)); +} + +void +GF2NT_233_Square_Reduce_ARMv8(const word* pA, word* pC) +{ + // word is either 32-bit or 64-bit, depending on the platform. + // Load using a 32-bit pointer to avoid possible alignment issues. + const uint32_t* pAA = reinterpret_cast(pA); + uint64x2_t a0 = vreinterpretq_u64_u32(vld1q_u32(pAA+0)); + uint64x2_t a1 = vreinterpretq_u64_u32(vld1q_u32(pAA+4)); + + uint64x2_t c0, c1, c2, c3; + F2N_Square_256_ARMv8(c3, c2, c1, c0, a1, a0); + GF2NT_233_Reduce_ARMv8(c3, c2, c1, c0); + + uint32_t* pCC = reinterpret_cast(pC); + vst1q_u32(pCC+0, vreinterpretq_u32_u64(c0)); + vst1q_u32(pCC+4, vreinterpretq_u32_u64(c1)); +} + +#elif (CRYPTOPP_POWER8_VMULL_AVAILABLE) && 0 + +void +GF2NT_233_Multiply_Reduce_POWER8(const word* pA, const word* pB, word* pC) +{ + // word is either 32-bit or 64-bit, depending on the platform. + // Load using a byte pointer to avoid possible alignment issues. + const byte* pAA = reinterpret_cast(pA); + const byte* pBB = reinterpret_cast(pB); + + uint64x2_p a0 = (uint64x2_p)VecLoad(pAA+0); + uint64x2_p a1 = (uint64x2_p)VecLoad(pAA+16); + uint64x2_p b0 = (uint64x2_p)VecLoad(pBB+0); + uint64x2_p b1 = (uint64x2_p)VecLoad(pBB+16); + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8_t mb[] = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11}; + const uint8x16_p m = (uint8x16_p)VecLoad(mb); + a0 = VecPermute(a0, m); + a1 = VecPermute(a1, m); + b0 = VecPermute(b0, m); + b1 = VecPermute(b1, m); +#endif + + uint64x2_p c0, c1, c2, c3; + F2N_Multiply_256x256_POWER8(c3, c2, c1, c0, a1, a0, b1, b0); + GF2NT_233_Reduce_POWER8(c3, c2, c1, c0); + +#if (CRYPTOPP_BIG_ENDIAN) + c0 = VecPermute(c0, m); + c1 = VecPermute(c1, m); +#endif + + byte* pCC = reinterpret_cast(pC); + VecStore(c0, pCC+0); + VecStore(c1, pCC+16); +} + +void +GF2NT_233_Square_Reduce_POWER8(const word* pA, word* pC) +{ + // word is either 32-bit or 64-bit, depending on the platform. + // Load using a byte pointer to avoid possible alignment issues. + const byte* pAA = reinterpret_cast(pA); + uint64x2_p a0 = (uint64x2_p)VecLoad(pAA+0); + uint64x2_p a1 = (uint64x2_p)VecLoad(pAA+16); + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8_t mb[] = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11}; + const uint8x16_p m = (uint8x16_p)VecLoad(mb); + a0 = VecPermute(a0, m); + a1 = VecPermute(a1, m); +#endif + + uint64x2_p c0, c1, c2, c3; + F2N_Square_256_POWER8(c3, c2, c1, c0, a1, a0); + GF2NT_233_Reduce_POWER8(c3, c2, c1, c0); + +#if (CRYPTOPP_BIG_ENDIAN) + c0 = VecPermute(c0, m); + c1 = VecPermute(c1, m); +#endif + + byte* pCC = reinterpret_cast(pC); + VecStore(c0, pCC+0); + VecStore(c1, pCC+16); +} + +#endif + +NAMESPACE_END + +#endif // CRYPTOPP_IMPORTS diff --git a/external/ours/library/crypto/src/shared/original/gfpcrypt.cpp b/external/ours/library/crypto/src/shared/original/gfpcrypt.cpp new file mode 100755 index 000000000..4c257cbdf --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gfpcrypt.cpp @@ -0,0 +1,334 @@ +// dsa.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +// TODO: fix the C4589 warnings +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4189 4589) +#endif + +#ifndef CRYPTOPP_IMPORTS + +#include "gfpcrypt.h" +#include "nbtheory.h" +#include "modarith.h" +#include "integer.h" +#include "asn.h" +#include "oids.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void TestInstantiations_gfpcrypt() +{ + GDSA::Signer test; + GDSA::Verifier test1; + DSA::Signer test5(NullRNG(), 100); + DSA::Signer test2(test5); + NR::Signer test3; + NR::Verifier test4; + DLIES<>::Encryptor test6; + DLIES<>::Decryptor test7; +} +#endif + +void DL_GroupParameters_DSA::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + Integer p, q, g; + + if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g)) + { + q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2); + Initialize(p, q, g); + } + else + { + int modulusSize = 2048, defaultSubgroupOrderSize; + alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize); + + switch (modulusSize) + { + case 1024: + defaultSubgroupOrderSize = 160; + break; + case 2048: + defaultSubgroupOrderSize = 224; + break; + case 3072: + defaultSubgroupOrderSize = 256; + break; + default: + throw InvalidArgument("DSA: not a valid prime length"); + } + + DL_GroupParameters_GFP::GenerateRandom(rng, CombinedNameValuePairs(alg, MakeParameters(Name::SubgroupOrderSize(), defaultSubgroupOrderSize, false))); + } +} + +bool DL_GroupParameters_DSA::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = DL_GroupParameters_GFP::ValidateGroup(rng, level); + CRYPTOPP_ASSERT(pass); + + const int pSize = GetModulus().BitCount(), qSize = GetSubgroupOrder().BitCount(); + pass = pass && ((pSize==1024 && qSize==160) || (pSize==2048 && qSize==224) || (pSize==2048 && qSize==256) || (pSize==3072 && qSize==256)); + CRYPTOPP_ASSERT(pass); + + return pass; +} + +void DL_SignatureMessageEncodingMethod_DSA::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); + CRYPTOPP_ASSERT(recoverableMessageLength == 0); + CRYPTOPP_ASSERT(hashIdentifier.second == 0); + + const size_t representativeByteLength = BitsToBytes(representativeBitLength); + const size_t digestSize = hash.DigestSize(); + const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize); + + memset(representative, 0, paddingLength); + hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize)); + + if (digestSize*8 > representativeBitLength) + { + Integer h(representative, representativeByteLength); + h >>= representativeByteLength*8 - representativeBitLength; + h.Encode(representative, representativeByteLength); + } +} + +void DL_SignatureMessageEncodingMethod_NR::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(hash); CRYPTOPP_UNUSED(hashIdentifier); CRYPTOPP_UNUSED(messageEmpty); + CRYPTOPP_UNUSED(representative); CRYPTOPP_UNUSED(representativeBitLength); + + CRYPTOPP_ASSERT(recoverableMessageLength == 0); + CRYPTOPP_ASSERT(hashIdentifier.second == 0); + const size_t representativeByteLength = BitsToBytes(representativeBitLength); + const size_t digestSize = hash.DigestSize(); + const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize); + + memset(representative, 0, paddingLength); + hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize)); + + if (digestSize*8 >= representativeBitLength) + { + Integer h(representative, representativeByteLength); + h >>= representativeByteLength*8 - representativeBitLength + 1; + h.Encode(representative, representativeByteLength); + } +} + +bool DL_GroupParameters_IntegerBased::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const +{ + const Integer &p = GetModulus(), &q = GetSubgroupOrder(); + bool pass = true; + + CRYPTOPP_ASSERT(p > Integer::One() && p.IsOdd()); + pass = pass && p > Integer::One() && p.IsOdd(); + + CRYPTOPP_ASSERT(q > Integer::One() && q.IsOdd()); + pass = pass && q > Integer::One() && q.IsOdd(); + + if (level >= 1) + { + CRYPTOPP_ASSERT(GetCofactor() > Integer::One()); + CRYPTOPP_ASSERT(GetGroupOrder() % q == Integer::Zero()); + + pass = pass && GetCofactor() > Integer::One() && GetGroupOrder() % q == Integer::Zero(); + } + if (level >= 2) + { + CRYPTOPP_ASSERT(VerifyPrime(rng, q, level-2)); + CRYPTOPP_ASSERT(VerifyPrime(rng, p, level-2)); + + pass = pass && VerifyPrime(rng, q, level-2) && VerifyPrime(rng, p, level-2); + } + + return pass; +} + +bool DL_GroupParameters_IntegerBased::ValidateElement(unsigned int level, const Integer &g, const DL_FixedBasePrecomputation *gpc) const +{ + const Integer &p = GetModulus(), &q = GetSubgroupOrder(); + bool pass = true; + + CRYPTOPP_ASSERT(GetFieldType() == 1 ? g.IsPositive() : g.NotNegative()); + pass = pass && GetFieldType() == 1 ? g.IsPositive() : g.NotNegative(); + + CRYPTOPP_ASSERT(g < p && !IsIdentity(g)); + pass = pass && g < p && !IsIdentity(g); + + if (level >= 1) + { + if (gpc) + { + CRYPTOPP_ASSERT(gpc->Exponentiate(GetGroupPrecomputation(), Integer::One()) == g); + pass = pass && gpc->Exponentiate(GetGroupPrecomputation(), Integer::One()) == g; + } + } + if (level >= 2) + { + if (GetFieldType() == 2) + { + CRYPTOPP_ASSERT(Jacobi(g*g-4, p)==-1); + pass = pass && Jacobi(g*g-4, p)==-1; + } + + // verifying that Lucas((p+1)/2, w, p)==2 is omitted because it's too costly + // and at most 1 bit is leaked if it's false + bool fullValidate = (GetFieldType() == 2 && level >= 3) || !FastSubgroupCheckAvailable(); + + if (fullValidate && pass) + { + Integer gp = gpc ? gpc->Exponentiate(GetGroupPrecomputation(), q) : ExponentiateElement(g, q); + CRYPTOPP_ASSERT(IsIdentity(gp)); + pass = pass && IsIdentity(gp); + } + else if (GetFieldType() == 1) + { + CRYPTOPP_ASSERT(Jacobi(g, p) == 1); + pass = pass && Jacobi(g, p) == 1; + } + } + + return pass; +} + +void DL_GroupParameters_IntegerBased::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + Integer p, q, g; + + if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g)) + { + q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2); + } + else + { + int modulusSize, subgroupOrderSize; + + if (!alg.GetIntValue("ModulusSize", modulusSize)) + modulusSize = alg.GetIntValueWithDefault("KeySize", 2048); + + if (!alg.GetIntValue("SubgroupOrderSize", subgroupOrderSize)) + subgroupOrderSize = GetDefaultSubgroupOrderSize(modulusSize); + + PrimeAndGenerator pg; + pg.Generate(GetFieldType() == 1 ? 1 : -1, rng, modulusSize, subgroupOrderSize); + p = pg.Prime(); + q = pg.SubPrime(); + g = pg.Generator(); + } + + Initialize(p, q, g); +} + +void DL_GroupParameters_IntegerBased::EncodeElement(bool reversible, const Element &element, byte *encoded) const +{ + CRYPTOPP_UNUSED(reversible); + element.Encode(encoded, GetModulus().ByteCount()); +} + +unsigned int DL_GroupParameters_IntegerBased::GetEncodedElementSize(bool reversible) const +{ + CRYPTOPP_UNUSED(reversible); + return GetModulus().ByteCount(); +} + +Integer DL_GroupParameters_IntegerBased::DecodeElement(const byte *encoded, bool checkForGroupMembership) const +{ + CRYPTOPP_UNUSED(checkForGroupMembership); + Integer g(encoded, GetModulus().ByteCount()); + if (!ValidateElement(1, g, NULLPTR)) + throw DL_BadElement(); + return g; +} + +void DL_GroupParameters_IntegerBased::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder parameters(bt); + Integer p(parameters); + Integer q(parameters); + Integer g; + if (parameters.EndReached()) + { + g = q; + q = ComputeGroupOrder(p) / 2; + } + else + g.BERDecode(parameters); + parameters.MessageEnd(); + + SetModulusAndSubgroupGenerator(p, g); + SetSubgroupOrder(q); +} + +void DL_GroupParameters_IntegerBased::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder parameters(bt); + GetModulus().DEREncode(parameters); + m_q.DEREncode(parameters); + GetSubgroupGenerator().DEREncode(parameters); + parameters.MessageEnd(); +} + +bool DL_GroupParameters_IntegerBased::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper >(this, name, valueType, pValue) + CRYPTOPP_GET_FUNCTION_ENTRY(Modulus); +} + +void DL_GroupParameters_IntegerBased::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY2(Modulus, SubgroupGenerator) + CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder) + ; +} + +OID DL_GroupParameters_IntegerBased::GetAlgorithmID() const +{ + return ASN1::id_dsa(); +} + +void DL_GroupParameters_GFP::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const +{ + ModularArithmetic ma(GetModulus()); + ma.SimultaneousExponentiate(results, base, exponents, exponentsCount); +} + +DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::MultiplyElements(const Element &a, const Element &b) const +{ + return a_times_b_mod_c(a, b, GetModulus()); +} + +DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const +{ + ModularArithmetic ma(GetModulus()); + return ma.CascadeExponentiate(element1, exponent1, element2, exponent2); +} + +Integer DL_GroupParameters_IntegerBased::GetMaxExponent() const +{ + return STDMIN(GetSubgroupOrder()-1, Integer::Power2(2*DiscreteLogWorkFactor(GetFieldType()*GetModulus().BitCount()))); +} + +unsigned int DL_GroupParameters_IntegerBased::GetDefaultSubgroupOrderSize(unsigned int modulusSize) const +{ + return 2*DiscreteLogWorkFactor(GetFieldType()*modulusSize); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/gfpcrypt.h b/external/ours/library/crypto/src/shared/original/gfpcrypt.h new file mode 100755 index 000000000..f8fc3c5ef --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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(); + 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=ture 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/external/ours/library/crypto/src/shared/original/gost.cpp b/external/ours/library/crypto/src/shared/original/gost.cpp new file mode 100755 index 000000000..dbeff9111 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gost.cpp @@ -0,0 +1,123 @@ +#include "pch.h" +#include "gost.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +// these are the S-boxes given in Applied Cryptography 2nd Ed., p. 333 +const byte GOST::Base::sBox[8][16]={ + {4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3}, + {14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9}, + {5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11}, + {7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3}, + {6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2}, + {4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14}, + {13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12}, + {1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12}}; + +/* // these are the S-boxes given in the GOST source code listing in Applied + // Cryptography 2nd Ed., p. 644. they appear to be from the DES S-boxes + {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }, + { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }, + {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }, + { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }, + { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }, + {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }, + {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }, + {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }}; +*/ + +volatile bool GOST::Base::sTableCalculated = false; +word32 GOST::Base::sTable[4][256]; + +void GOST::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + PrecalculateSTable(); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_key.begin(), 8, userKey, KEYLENGTH); +} + +void GOST::Base::PrecalculateSTable() +{ + if (!sTableCalculated) + { + for (unsigned i = 0; i < 4; i++) + for (unsigned j = 0; j < 256; j++) + { + word32 temp = sBox[2*i][j%16] | (sBox[2*i+1][j/16] << 4); + sTable[i][j] = rotlMod(temp, 11+8*i); + } + + sTableCalculated=true; + } +} + +#define f(x) ( t=x, \ + sTable[3][GETBYTE(t, 3)] ^ sTable[2][GETBYTE(t, 2)] \ + ^ sTable[1][GETBYTE(t, 1)] ^ sTable[0][GETBYTE(t, 0)] ) + +typedef BlockGetAndPut Block; + +void GOST::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 n1, n2, t; + + Block::Get(inBlock)(n1)(n2); + + for (unsigned int i=0; i<3; i++) + { + n2 ^= f(n1+m_key[0]); + n1 ^= f(n2+m_key[1]); + n2 ^= f(n1+m_key[2]); + n1 ^= f(n2+m_key[3]); + n2 ^= f(n1+m_key[4]); + n1 ^= f(n2+m_key[5]); + n2 ^= f(n1+m_key[6]); + n1 ^= f(n2+m_key[7]); + } + + n2 ^= f(n1+m_key[7]); + n1 ^= f(n2+m_key[6]); + n2 ^= f(n1+m_key[5]); + n1 ^= f(n2+m_key[4]); + n2 ^= f(n1+m_key[3]); + n1 ^= f(n2+m_key[2]); + n2 ^= f(n1+m_key[1]); + n1 ^= f(n2+m_key[0]); + + Block::Put(xorBlock, outBlock)(n2)(n1); +} + +void GOST::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 n1, n2, t; + + Block::Get(inBlock)(n1)(n2); + + n2 ^= f(n1+m_key[0]); + n1 ^= f(n2+m_key[1]); + n2 ^= f(n1+m_key[2]); + n1 ^= f(n2+m_key[3]); + n2 ^= f(n1+m_key[4]); + n1 ^= f(n2+m_key[5]); + n2 ^= f(n1+m_key[6]); + n1 ^= f(n2+m_key[7]); + + for (unsigned int i=0; i<3; i++) + { + n2 ^= f(n1+m_key[7]); + n1 ^= f(n2+m_key[6]); + n2 ^= f(n1+m_key[5]); + n1 ^= f(n2+m_key[4]); + n2 ^= f(n1+m_key[3]); + n1 ^= f(n2+m_key[2]); + n2 ^= f(n1+m_key[1]); + n1 ^= f(n2+m_key[0]); + } + + Block::Put(xorBlock, outBlock)(n2)(n1); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/gost.h b/external/ours/library/crypto/src/shared/original/gost.h new file mode 100755 index 000000000..fe6e1576a --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/gzip.cpp b/external/ours/library/crypto/src/shared/original/gzip.cpp new file mode 100755 index 000000000..ade1d422f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/gzip.cpp @@ -0,0 +1,208 @@ +// gzip.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "gzip.h" +#include "argnames.h" + +NAMESPACE_BEGIN(CryptoPP) + +// Checks whether the character is valid for ISO/IEC 8859-1 as required by RFC 1952 +static inline bool Is8859Character(char c) { + const unsigned char cc = static_cast(c); + return (cc >= 32 && cc <= 126) || (cc >= 160); +} + +void Gzip::IsolatedInitialize(const NameValuePairs ¶meters) +{ + Deflator::IsolatedInitialize(parameters); + + ConstByteArrayParameter v; + if (parameters.GetValue(Name::FileName(), v)) + m_filename.assign(reinterpret_cast(v.begin()), v.size()); + if (parameters.GetValue(Name::Comment(), v)) + m_comment.assign(reinterpret_cast(v.begin()), v.size()); + m_filetime = parameters.GetIntValueWithDefault(Name::FileTime(), 0); +} + +void Gzip::WritePrestreamHeader() +{ + m_totalLen = 0; + m_crc.Restart(); + + int flags = 0; + if(!m_filename.empty()) + flags |= FILENAME; + if(!m_comment.empty()) + flags |= COMMENTS; + + AttachedTransformation()->Put(MAGIC1); + AttachedTransformation()->Put(MAGIC2); + AttachedTransformation()->Put(DEFLATED); + AttachedTransformation()->Put((byte)flags); // general flag + AttachedTransformation()->PutWord32(m_filetime, LITTLE_ENDIAN_ORDER); // time stamp + byte extra = static_cast((GetDeflateLevel() == 1) ? + FAST : ((GetDeflateLevel() == 9) ? SLOW : 0)); + AttachedTransformation()->Put(extra); + AttachedTransformation()->Put(GZIP_OS_CODE); + + // Filename is NULL terminated, hence the +1 + if(!m_filename.empty()) + AttachedTransformation()->Put((const unsigned char*)m_filename.data(), m_filename.size() +1); + + // Comment is NULL terminated, hence the +1 + if(!m_comment.empty()) + AttachedTransformation()->Put((const unsigned char*)m_comment.data(), m_comment.size() +1); +} + +void Gzip::ProcessUncompressedData(const byte *inString, size_t length) +{ + m_crc.Update(inString, length); + m_totalLen += (word32)length; +} + +void Gzip::WritePoststreamTail() +{ + SecByteBlock crc(4); + m_crc.Final(crc); + AttachedTransformation()->Put(crc, 4); + AttachedTransformation()->PutWord32(m_totalLen, LITTLE_ENDIAN_ORDER); + + m_filetime = 0; + m_filename.clear(); + m_comment.clear(); +} + +void Gzip::SetComment(const std::string& comment, bool throwOnEncodingError) +{ + if(throwOnEncodingError) + { + for(size_t i = 0; i < comment.length(); i++) { + const char c = comment[i]; + if(!Is8859Character(c)) + throw InvalidDataFormat("The comment is not ISO/IEC 8859-1 encoded"); + } + } + + m_comment = comment; +} + +void Gzip::SetFilename(const std::string& filename, bool throwOnEncodingError) +{ + if(throwOnEncodingError) + { + for(size_t i = 0; i < filename.length(); i++) { + const char c = filename[i]; + if(!Is8859Character(c)) + throw InvalidDataFormat("The filename is not ISO/IEC 8859-1 encoded"); + } + } + + m_filename = filename; +} + +// ************************************************************* + +Gunzip::Gunzip(BufferedTransformation *attachment, bool repeat, int propagation) + : Inflator(attachment, repeat, propagation), m_length(0), m_filetime(0) +{ +} + +void Gunzip::ProcessPrestreamHeader() +{ + m_length = 0; + m_crc.Restart(); + + m_filetime = 0; + m_filename.clear(); + m_comment.clear(); + + byte buf[6]; + byte b, flags; + + if (m_inQueue.Get(buf, 2)!=2) throw HeaderErr(); + if (buf[0] != MAGIC1 || buf[1] != MAGIC2) throw HeaderErr(); + if (!m_inQueue.Get(b) || (b != DEFLATED)) throw HeaderErr(); // skip CM flag + if (!m_inQueue.Get(flags)) throw HeaderErr(); + if (flags & (ENCRYPTED | CONTINUED)) throw HeaderErr(); + if (m_inQueue.GetWord32(m_filetime, LITTLE_ENDIAN_ORDER) != 4) throw HeaderErr(); + if (m_inQueue.Skip(2)!=2) throw HeaderErr(); // Skip extra flags and OS type + + if (flags & EXTRA_FIELDS) // skip extra fields + { + word16 length; + if (m_inQueue.GetWord16(length, LITTLE_ENDIAN_ORDER) != 2) throw HeaderErr(); + if (m_inQueue.Skip(length)!=length) throw HeaderErr(); + } + + if (flags & FILENAME) // extract filename + { + do + { + if(!m_inQueue.Get(b)) throw HeaderErr(); + if(b) m_filename.append( 1, (char)b ); + } + while (b); + } + + if (flags & COMMENTS) // extract comments + { + do + { + if(!m_inQueue.Get(b)) throw HeaderErr(); + if(b) m_comment.append( 1, (char)b ); + } + while (b); + } +} + +void Gunzip::ProcessDecompressedData(const byte *inString, size_t length) +{ + AttachedTransformation()->Put(inString, length); + m_crc.Update(inString, length); + m_length += (word32)length; +} + +void Gunzip::ProcessPoststreamTail() +{ + SecByteBlock crc(4); + if (m_inQueue.Get(crc, 4) != 4) + throw TailErr(); + if (!m_crc.Verify(crc)) + throw CrcErr(); + + word32 lengthCheck; + if (m_inQueue.GetWord32(lengthCheck, LITTLE_ENDIAN_ORDER) != 4) + throw TailErr(); + if (lengthCheck != m_length) + throw LengthErr(); +} + +const std::string& Gunzip::GetComment(bool throwOnEncodingError) const +{ + if(throwOnEncodingError) + { + for(size_t i = 0; i < m_comment.length(); i++) { + const char c = m_comment[i]; + if(!Is8859Character(c)) + throw InvalidDataFormat("The comment is not ISO/IEC 8859-1 encoded"); + } + } + + return m_comment; +} + +const std::string& Gunzip::GetFilename(bool throwOnEncodingError) const +{ + if(throwOnEncodingError) + { + for(size_t i = 0; i < m_filename.length(); i++) { + const char c = m_filename[i]; + if(!Is8859Character(c)) + throw InvalidDataFormat("The filename is not ISO/IEC 8859-1 encoded"); + } + } + + return m_filename; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/gzip.h b/external/ours/library/crypto/src/shared/original/gzip.h new file mode 100755 index 000000000..b05feb4c4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/hashfwd.h b/external/ours/library/crypto/src/shared/original/hashfwd.h new file mode 100755 index 000000000..49c2b02a2 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/hc128.cpp b/external/ours/library/crypto/src/shared/original/hc128.cpp new file mode 100755 index 000000000..74f67c171 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/hc128.cpp @@ -0,0 +1,279 @@ +// hc128.cpp - 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. + +#include "pch.h" +#include "config.h" + +#include "hc128.h" +#include "secblock.h" +#include "misc.h" + +/*h1 function*/ +#define h1(x, y) { \ + byte a,c; \ + a = (byte) (x); \ + c = (byte) ((x) >> 16); \ + y = (m_T[512+a])+(m_T[512+256+c]); \ +} + +/*h2 function*/ +#define h2(x, y) { \ + byte a,c; \ + a = (byte) (x); \ + c = (byte) ((x) >> 16); \ + y = (m_T[a])+(m_T[256+c]); \ +} + +/*one step of HC-128, update P and generate 32 bits keystream*/ +#define step_P(u,v,a,b,c,d,n){ \ + word32 tem0,tem1,tem2,tem3; \ + h1(m_X[(d)],tem3); \ + tem0 = rotrConstant<23>(m_T[(v)]); \ + tem1 = rotrConstant<10>(m_X[(c)]); \ + tem2 = rotrConstant<8>(m_X[(b)]); \ + (m_T[(u)]) += tem2+(tem0 ^ tem1); \ + (m_X[(a)]) = (m_T[(u)]); \ + (n) = tem3 ^ (m_T[(u)]); \ +} + +/*one step of HC-128, update Q and generate 32 bits keystream*/ +#define step_Q(u,v,a,b,c,d,n){ \ + word32 tem0,tem1,tem2,tem3; \ + h2(m_Y[(d)],tem3); \ + tem0 = rotrConstant<(32-23)>(m_T[(v)]); \ + tem1 = rotrConstant<(32-10)>(m_Y[(c)]); \ + tem2 = rotrConstant<(32-8)>(m_Y[(b)]); \ + (m_T[(u)]) += tem2 + (tem0 ^ tem1); \ + (m_Y[(a)]) = (m_T[(u)]); \ + (n) = tem3 ^ (m_T[(u)]) ; \ +} + +/*update table P*/ +#define update_P(u,v,a,b,c,d){ \ + word32 tem0,tem1,tem2,tem3; \ + tem0 = rotrConstant<23>(m_T[(v)]); \ + tem1 = rotrConstant<10>(m_X[(c)]); \ + tem2 = rotrConstant<8>(m_X[(b)]); \ + h1(m_X[(d)],tem3); \ + (m_T[(u)]) = ((m_T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ + (m_X[(a)]) = (m_T[(u)]); \ +} + +/*update table Q*/ +#define update_Q(u,v,a,b,c,d){ \ + word32 tem0,tem1,tem2,tem3; \ + tem0 = rotrConstant<(32-23)>(m_T[(v)]); \ + tem1 = rotrConstant<(32-10)>(m_Y[(c)]); \ + tem2 = rotrConstant<(32-8)>(m_Y[(b)]); \ + h2(m_Y[(d)],tem3); \ + (m_T[(u)]) = ((m_T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ + (m_Y[(a)]) = (m_T[(u)]); \ +} + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; +using CryptoPP::rotrConstant; + +inline word32 f1(word32 x) +{ + return rotrConstant<7>(x) ^ rotrConstant<18>(x) ^ ((x) >> 3); +} + +inline word32 f2(word32 x) +{ + return rotrConstant<17>(x) ^ rotrConstant<19>(x) ^ ((x) >> 10); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +/*16 steps of HC-128, generate 512 bits keystream*/ +void HC128Policy::GenerateKeystream(word32 keystream[16]) +{ + unsigned int cc = m_ctr & 0x1ff; + unsigned int dd = (cc + 16) & 0x1ff; + + if (m_ctr < 512) + { + m_ctr = (m_ctr + 16) & 0x3ff; + step_P(cc + 0, cc + 1, 0, 6, 13, 4, keystream[0]); + step_P(cc + 1, cc + 2, 1, 7, 14, 5, keystream[1]); + step_P(cc + 2, cc + 3, 2, 8, 15, 6, keystream[2]); + step_P(cc + 3, cc + 4, 3, 9, 0, 7, keystream[3]); + step_P(cc + 4, cc + 5, 4, 10, 1, 8, keystream[4]); + step_P(cc + 5, cc + 6, 5, 11, 2, 9, keystream[5]); + step_P(cc + 6, cc + 7, 6, 12, 3, 10, keystream[6]); + step_P(cc + 7, cc + 8, 7, 13, 4, 11, keystream[7]); + step_P(cc + 8, cc + 9, 8, 14, 5, 12, keystream[8]); + step_P(cc + 9, cc + 10, 9, 15, 6, 13, keystream[9]); + step_P(cc + 10, cc + 11, 10, 0, 7, 14, keystream[10]); + step_P(cc + 11, cc + 12, 11, 1, 8, 15, keystream[11]); + step_P(cc + 12, cc + 13, 12, 2, 9, 0, keystream[12]); + step_P(cc + 13, cc + 14, 13, 3, 10, 1, keystream[13]); + step_P(cc + 14, cc + 15, 14, 4, 11, 2, keystream[14]); + step_P(cc + 15, dd + 0, 15, 5, 12, 3, keystream[15]); + } + else + { + m_ctr = (m_ctr + 16) & 0x3ff; + step_Q(512 + cc + 0, 512 + cc + 1, 0, 6, 13, 4, keystream[0]); + step_Q(512 + cc + 1, 512 + cc + 2, 1, 7, 14, 5, keystream[1]); + step_Q(512 + cc + 2, 512 + cc + 3, 2, 8, 15, 6, keystream[2]); + step_Q(512 + cc + 3, 512 + cc + 4, 3, 9, 0, 7, keystream[3]); + step_Q(512 + cc + 4, 512 + cc + 5, 4, 10, 1, 8, keystream[4]); + step_Q(512 + cc + 5, 512 + cc + 6, 5, 11, 2, 9, keystream[5]); + step_Q(512 + cc + 6, 512 + cc + 7, 6, 12, 3, 10, keystream[6]); + step_Q(512 + cc + 7, 512 + cc + 8, 7, 13, 4, 11, keystream[7]); + step_Q(512 + cc + 8, 512 + cc + 9, 8, 14, 5, 12, keystream[8]); + step_Q(512 + cc + 9, 512 + cc + 10, 9, 15, 6, 13, keystream[9]); + step_Q(512 + cc + 10, 512 + cc + 11, 10, 0, 7, 14, keystream[10]); + step_Q(512 + cc + 11, 512 + cc + 12, 11, 1, 8, 15, keystream[11]); + step_Q(512 + cc + 12, 512 + cc + 13, 12, 2, 9, 0, keystream[12]); + step_Q(512 + cc + 13, 512 + cc + 14, 13, 3, 10, 1, keystream[13]); + step_Q(512 + cc + 14, 512 + cc + 15, 14, 4, 11, 2, keystream[14]); + step_Q(512 + cc + 15, 512 + dd + 0, 15, 5, 12, 3, keystream[15]); + } +} + +/*16 steps of HC-128, without generating keystream, */ +/*but use the outputs to update P and Q*/ +void HC128Policy::SetupUpdate() /*each time 16 steps*/ +{ + unsigned int cc = m_ctr & 0x1ff; + unsigned int dd = (cc + 16) & 0x1ff; + + if (m_ctr < 512) + { + m_ctr = (m_ctr + 16) & 0x3ff; + update_P(cc + 0, cc + 1, 0, 6, 13, 4); + update_P(cc + 1, cc + 2, 1, 7, 14, 5); + update_P(cc + 2, cc + 3, 2, 8, 15, 6); + update_P(cc + 3, cc + 4, 3, 9, 0, 7); + update_P(cc + 4, cc + 5, 4, 10, 1, 8); + update_P(cc + 5, cc + 6, 5, 11, 2, 9); + update_P(cc + 6, cc + 7, 6, 12, 3, 10); + update_P(cc + 7, cc + 8, 7, 13, 4, 11); + update_P(cc + 8, cc + 9, 8, 14, 5, 12); + update_P(cc + 9, cc + 10, 9, 15, 6, 13); + update_P(cc + 10, cc + 11, 10, 0, 7, 14); + update_P(cc + 11, cc + 12, 11, 1, 8, 15); + update_P(cc + 12, cc + 13, 12, 2, 9, 0); + update_P(cc + 13, cc + 14, 13, 3, 10, 1); + update_P(cc + 14, cc + 15, 14, 4, 11, 2); + update_P(cc + 15, dd + 0, 15, 5, 12, 3); + } + else + { + m_ctr = (m_ctr + 16) & 0x3ff; + update_Q(512 + cc + 0, 512 + cc + 1, 0, 6, 13, 4); + update_Q(512 + cc + 1, 512 + cc + 2, 1, 7, 14, 5); + update_Q(512 + cc + 2, 512 + cc + 3, 2, 8, 15, 6); + update_Q(512 + cc + 3, 512 + cc + 4, 3, 9, 0, 7); + update_Q(512 + cc + 4, 512 + cc + 5, 4, 10, 1, 8); + update_Q(512 + cc + 5, 512 + cc + 6, 5, 11, 2, 9); + update_Q(512 + cc + 6, 512 + cc + 7, 6, 12, 3, 10); + update_Q(512 + cc + 7, 512 + cc + 8, 7, 13, 4, 11); + update_Q(512 + cc + 8, 512 + cc + 9, 8, 14, 5, 12); + update_Q(512 + cc + 9, 512 + cc + 10, 9, 15, 6, 13); + update_Q(512 + cc + 10, 512 + cc + 11, 10, 0, 7, 14); + update_Q(512 + cc + 11, 512 + cc + 12, 11, 1, 8, 15); + update_Q(512 + cc + 12, 512 + cc + 13, 12, 2, 9, 0); + update_Q(512 + cc + 13, 512 + cc + 14, 13, 3, 10, 1); + update_Q(512 + cc + 14, 512 + cc + 15, 14, 4, 11, 2); + update_Q(512 + cc + 15, 512 + dd + 0, 15, 5, 12, 3); + } +} + +void HC128Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *userKey, size_t keylen) +{ + CRYPTOPP_UNUSED(params); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_key.begin(), 4, userKey, keylen); + for (unsigned int i = 4; i < 8; i++) + m_key[i] = m_key[i - 4]; +} + +void HC128Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ + while (iterationCount--) + { + word32 keystream[16]; + GenerateKeystream(keystream); + + PutWord(false, LITTLE_ENDIAN_ORDER, output + 0, keystream[0]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 4, keystream[1]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 8, keystream[2]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 12, keystream[3]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 16, keystream[4]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 20, keystream[5]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 24, keystream[6]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 28, keystream[7]); + + PutWord(false, LITTLE_ENDIAN_ORDER, output + 32, keystream[8]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 36, keystream[9]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 40, keystream[10]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 44, keystream[11]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 48, keystream[12]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 52, keystream[13]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 56, keystream[14]); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 60, keystream[15]); + + // If AdditiveCipherTemplate does not have an accumulated keystream + // then it will ask OperateKeystream to generate one. Optionally it + // will ask for an XOR of the input with the keystream while + // writing the result to the output buffer. In all cases the + // keystream is written to the output buffer. The optional part is + // adding the input buffer and keystream. + if ((operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL)) + { + xorbuf(output, input, BYTES_PER_ITERATION); + input += BYTES_PER_ITERATION; + } + + output += BYTES_PER_ITERATION; + } +} + +void HC128Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_iv.begin(), 4, iv, length); + for (unsigned int i = 4; i < 8; i++) + m_iv[i] = m_iv[i - 4]; + + /* expand the key and IV into the table T */ + /* (expand the key and IV into the table P and Q) */ + + for (unsigned int i = 0; i < 8; i++) + m_T[i] = m_key[i]; + for (unsigned int i = 8; i < 16; i++) + m_T[i] = m_iv[i - 8]; + + for (unsigned int i = 16; i < (256 + 16); i++) + m_T[i] = f2(m_T[i - 2]) + m_T[i - 7] + f1(m_T[i - 15]) + m_T[i - 16] + i; + + for (unsigned int i = 0; i < 16; i++) + m_T[i] = m_T[256 + i]; + + for (unsigned int i = 16; i < 1024; i++) + m_T[i] = f2(m_T[i - 2]) + m_T[i - 7] + f1(m_T[i - 15]) + m_T[i - 16] + 256 + i; + + /* initialize counter1024, X and Y */ + m_ctr = 0; + for (unsigned int i = 0; i < 16; i++) + m_X[i] = m_T[512 - 16 + i]; + for (unsigned int i = 0; i < 16; i++) + m_Y[i] = m_T[512 + 512 - 16 + i]; + + /* run the cipher 1024 steps before generating the output */ + for (unsigned int i = 0; i < 64; i++) + SetupUpdate(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/hc128.h b/external/ours/library/crypto/src/shared/original/hc128.h new file mode 100755 index 000000000..a43eeeb38 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/hc256.cpp b/external/ours/library/crypto/src/shared/original/hc256.cpp new file mode 100755 index 000000000..9259b87a7 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/hc256.cpp @@ -0,0 +1,158 @@ +// hc256.cpp - 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. + +#include "pch.h" +#include "config.h" + +#include "hc256.h" +#include "secblock.h" +#include "misc.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; +using CryptoPP::rotrConstant; + +inline word32 f1(word32 x) +{ + return rotrConstant<7>(x) ^ rotrConstant<18>(x) ^ (x >> 3); +} + +inline word32 f2(word32 x) +{ + return rotrConstant<17>(x) ^ rotrConstant<19>(x) ^ (x >> 10); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +inline word32 HC256Policy::H1(word32 u) +{ + word32 tem; + byte a, b, c, d; + a = (byte)(u); + b = (byte)(u >> 8); + c = (byte)(u >> 16); + d = (byte)(u >> 24); + tem = m_Q[a] + m_Q[256 + b] + m_Q[512 + c] + m_Q[768 + d]; + return (tem); +} + +inline word32 HC256Policy::H2(word32 u) +{ + word32 tem; + byte a, b, c, d; + a = (byte)(u); + b = (byte)(u >> 8); + c = (byte)(u >> 16); + d = (byte)(u >> 24); + tem = m_P[a] + m_P[256 + b] + m_P[512 + c] + m_P[768 + d]; + return (tem); +} + +inline word32 HC256Policy::Generate() /*one step of the cipher*/ +{ + word32 i, i3, i10, i12, i1023; + word32 output; + + i = m_ctr & 0x3ff; + i3 = (i - 3) & 0x3ff; + i10 = (i - 10) & 0x3ff; + i12 = (i - 12) & 0x3ff; + i1023 = (i - 1023) & 0x3ff; + + if (m_ctr < 1024) { + m_P[i] = m_P[i] + m_P[i10] + (rotrConstant<10>(m_P[i3]) ^ rotrConstant<23>(m_P[i1023])) + m_Q[(m_P[i3] ^ m_P[i1023]) & 0x3ff]; + output = H1(m_P[i12]) ^ m_P[i]; + } + else { + m_Q[i] = m_Q[i] + m_Q[i10] + (rotrConstant<10>(m_Q[i3]) ^ rotrConstant<23>(m_Q[i1023])) + m_P[(m_Q[i3] ^ m_Q[i1023]) & 0x3ff]; + output = H2(m_Q[i12]) ^ m_Q[i]; + } + m_ctr = (m_ctr + 1) & 0x7ff; + return (output); +} + +void HC256Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *userKey, size_t keylen) +{ + CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(keylen); + CRYPTOPP_ASSERT(keylen == 32); + + for (unsigned int i = 0; i < 8; i++) + m_key[i] = 0; + + for (unsigned int i = 0; i < 32; i++) + { + m_key[i >> 2] = m_key[i >> 2] | userKey[i]; + m_key[i >> 2] = rotlConstant<8>(m_key[i >> 2]); + } +} + +void HC256Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ + while (iterationCount--) + { + PutWord(false, LITTLE_ENDIAN_ORDER, output + 0, Generate()); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 4, Generate()); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 8, Generate()); + PutWord(false, LITTLE_ENDIAN_ORDER, output + 12, Generate()); + + // If AdditiveCipherTemplate does not have an accumulated keystream + // then it will ask OperateKeystream to generate one. Optionally it + // will ask for an XOR of the input with the keystream while + // writing the result to the output buffer. In all cases the + // keystream is written to the output buffer. The optional part is + // adding the input buffer and keystream. + if ((operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL)) + { + xorbuf(output, input, BYTES_PER_ITERATION); + input += BYTES_PER_ITERATION; + } + + output += BYTES_PER_ITERATION; + } +} + +void HC256Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length == 32); + + /* initialize the iv */ + word32 W[2560]; + for (unsigned int i = 0; i < 8; i++) + m_iv[i] = 0; + + for (unsigned int i = 0; i < 32; i++) + { + m_iv[i >> 2] = m_iv[i >> 2] | iv[i]; + m_iv[i >> 2] = rotlConstant<8>(m_iv[i >> 2]); + } + + /* setup the table P and Q */ + + for (unsigned int i = 0; i < 8; i++) + W[i] = m_key[i]; + for (unsigned int i = 8; i < 16; i++) + W[i] = m_iv[i - 8]; + + for (unsigned int i = 16; i < 2560; i++) + W[i] = f2(W[i - 2]) + W[i - 7] + f1(W[i - 15]) + W[i - 16] + i; + + for (unsigned int i = 0; i < 1024; i++) + m_P[i] = W[i + 512]; + for (unsigned int i = 0; i < 1024; i++) + m_Q[i] = W[i + 1536]; + + m_ctr = 0; + + /* run the cipher 4096 steps before generating the output */ + for (unsigned int i = 0; i < 4096; i++) + Generate(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/hc256.h b/external/ours/library/crypto/src/shared/original/hc256.h new file mode 100755 index 000000000..ccd1ca050 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/hc256.h @@ -0,0 +1,67 @@ +// 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); + 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/external/ours/library/crypto/src/shared/original/hex.cpp b/external/ours/library/crypto/src/shared/original/hex.cpp new file mode 100755 index 000000000..d347241b5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/hex.cpp @@ -0,0 +1,58 @@ +// hex.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "hex.h" + +NAMESPACE_BEGIN(CryptoPP) +ANONYMOUS_NAMESPACE_BEGIN + +const byte s_vecUpper[] = "0123456789ABCDEF"; +const byte s_vecLower[] = "0123456789abcdef"; +const int s_array[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +ANONYMOUS_NAMESPACE_END + +void HexEncoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true); + m_filter->Initialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_vecUpper[0] : &s_vecLower[0], false)(Name::Log2Base(), 4, true))); +} + +void HexDecoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 4, true))); +} + +// Unrolled initialization, http://github.com/weidai11/cryptopp/issues/376 +const int *HexDecoder::GetDefaultDecodingLookupArray() +{ + return s_array; +} + +NAMESPACE_END + +#endif // CRYPTOPP_IMPORTS diff --git a/external/ours/library/crypto/src/shared/original/hex.h b/external/ours/library/crypto/src/shared/original/hex.h new file mode 100755 index 000000000..05f106871 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/hight.cpp b/external/ours/library/crypto/src/shared/original/hight.cpp new file mode 100755 index 000000000..8b6f28ed1 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/hight.cpp @@ -0,0 +1,271 @@ +// lea.cpp - written and placed in the public domain by Kim Sung Hee and Jeffrey Walton +// Based on "HIGHT: 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. +// +// This implementation is based on source files found in a zip file at the +// Korea Internet and Security Agency (https://www.kisa.or.kr/eng/main.jsp). +// The zip files was downloaded from the Korean language area of the site so we +// don't have a url or english zip filename to cite. The source filename from +// the zip is KISA_HIGHT_ECB.c. + +#include "pch.h" +#include "config.h" + +#include "hight.h" +#include "misc.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; + +const byte DELTA[128] = { + 0x5A,0x6D,0x36,0x1B,0x0D,0x06,0x03,0x41, + 0x60,0x30,0x18,0x4C,0x66,0x33,0x59,0x2C, + 0x56,0x2B,0x15,0x4A,0x65,0x72,0x39,0x1C, + 0x4E,0x67,0x73,0x79,0x3C,0x5E,0x6F,0x37, + 0x5B,0x2D,0x16,0x0B,0x05,0x42,0x21,0x50, + 0x28,0x54,0x2A,0x55,0x6A,0x75,0x7A,0x7D, + 0x3E,0x5F,0x2F,0x17,0x4B,0x25,0x52,0x29, + 0x14,0x0A,0x45,0x62,0x31,0x58,0x6C,0x76, + 0x3B,0x1D,0x0E,0x47,0x63,0x71,0x78,0x7C, + 0x7E,0x7F,0x3F,0x1F,0x0F,0x07,0x43,0x61, + 0x70,0x38,0x5C,0x6E,0x77,0x7B,0x3D,0x1E, + 0x4F,0x27,0x53,0x69,0x34,0x1A,0x4D,0x26, + 0x13,0x49,0x24,0x12,0x09,0x04,0x02,0x01, + 0x40,0x20,0x10,0x08,0x44,0x22,0x11,0x48, + 0x64,0x32,0x19,0x0C,0x46,0x23,0x51,0x68, + 0x74,0x3A,0x5D,0x2E,0x57,0x6B,0x35,0x5A +}; + +const byte HIGHT_F0[256] = { + 0x00,0x86,0x0D,0x8B,0x1A,0x9C,0x17,0x91, + 0x34,0xB2,0x39,0xBF,0x2E,0xA8,0x23,0xA5, + 0x68,0xEE,0x65,0xE3,0x72,0xF4,0x7F,0xF9, + 0x5C,0xDA,0x51,0xD7,0x46,0xC0,0x4B,0xCD, + 0xD0,0x56,0xDD,0x5B,0xCA,0x4C,0xC7,0x41, + 0xE4,0x62,0xE9,0x6F,0xFE,0x78,0xF3,0x75, + 0xB8,0x3E,0xB5,0x33,0xA2,0x24,0xAF,0x29, + 0x8C,0x0A,0x81,0x07,0x96,0x10,0x9B,0x1D, + 0xA1,0x27,0xAC,0x2A,0xBB,0x3D,0xB6,0x30, + 0x95,0x13,0x98,0x1E,0x8F,0x09,0x82,0x04, + 0xC9,0x4F,0xC4,0x42,0xD3,0x55,0xDE,0x58, + 0xFD,0x7B,0xF0,0x76,0xE7,0x61,0xEA,0x6C, + 0x71,0xF7,0x7C,0xFA,0x6B,0xED,0x66,0xE0, + 0x45,0xC3,0x48,0xCE,0x5F,0xD9,0x52,0xD4, + 0x19,0x9F,0x14,0x92,0x03,0x85,0x0E,0x88, + 0x2D,0xAB,0x20,0xA6,0x37,0xB1,0x3A,0xBC, + 0x43,0xC5,0x4E,0xC8,0x59,0xDF,0x54,0xD2, + 0x77,0xF1,0x7A,0xFC,0x6D,0xEB,0x60,0xE6, + 0x2B,0xAD,0x26,0xA0,0x31,0xB7,0x3C,0xBA, + 0x1F,0x99,0x12,0x94,0x05,0x83,0x08,0x8E, + 0x93,0x15,0x9E,0x18,0x89,0x0F,0x84,0x02, + 0xA7,0x21,0xAA,0x2C,0xBD,0x3B,0xB0,0x36, + 0xFB,0x7D,0xF6,0x70,0xE1,0x67,0xEC,0x6A, + 0xCF,0x49,0xC2,0x44,0xD5,0x53,0xD8,0x5E, + 0xE2,0x64,0xEF,0x69,0xF8,0x7E,0xF5,0x73, + 0xD6,0x50,0xDB,0x5D,0xCC,0x4A,0xC1,0x47, + 0x8A,0x0C,0x87,0x01,0x90,0x16,0x9D,0x1B, + 0xBE,0x38,0xB3,0x35,0xA4,0x22,0xA9,0x2F, + 0x32,0xB4,0x3F,0xB9,0x28,0xAE,0x25,0xA3, + 0x06,0x80,0x0B,0x8D,0x1C,0x9A,0x11,0x97, + 0x5A,0xDC,0x57,0xD1,0x40,0xC6,0x4D,0xCB, + 0x6E,0xE8,0x63,0xE5,0x74,0xF2,0x79,0xFF +}; + +const byte HIGHT_F1[256] = { + 0x00,0x58,0xB0,0xE8,0x61,0x39,0xD1,0x89, + 0xC2,0x9A,0x72,0x2A,0xA3,0xFB,0x13,0x4B, + 0x85,0xDD,0x35,0x6D,0xE4,0xBC,0x54,0x0C, + 0x47,0x1F,0xF7,0xAF,0x26,0x7E,0x96,0xCE, + 0x0B,0x53,0xBB,0xE3,0x6A,0x32,0xDA,0x82, + 0xC9,0x91,0x79,0x21,0xA8,0xF0,0x18,0x40, + 0x8E,0xD6,0x3E,0x66,0xEF,0xB7,0x5F,0x07, + 0x4C,0x14,0xFC,0xA4,0x2D,0x75,0x9D,0xC5, + 0x16,0x4E,0xA6,0xFE,0x77,0x2F,0xC7,0x9F, + 0xD4,0x8C,0x64,0x3C,0xB5,0xED,0x05,0x5D, + 0x93,0xCB,0x23,0x7B,0xF2,0xAA,0x42,0x1A, + 0x51,0x09,0xE1,0xB9,0x30,0x68,0x80,0xD8, + 0x1D,0x45,0xAD,0xF5,0x7C,0x24,0xCC,0x94, + 0xDF,0x87,0x6F,0x37,0xBE,0xE6,0x0E,0x56, + 0x98,0xC0,0x28,0x70,0xF9,0xA1,0x49,0x11, + 0x5A,0x02,0xEA,0xB2,0x3B,0x63,0x8B,0xD3, + 0x2C,0x74,0x9C,0xC4,0x4D,0x15,0xFD,0xA5, + 0xEE,0xB6,0x5E,0x06,0x8F,0xD7,0x3F,0x67, + 0xA9,0xF1,0x19,0x41,0xC8,0x90,0x78,0x20, + 0x6B,0x33,0xDB,0x83,0x0A,0x52,0xBA,0xE2, + 0x27,0x7F,0x97,0xCF,0x46,0x1E,0xF6,0xAE, + 0xE5,0xBD,0x55,0x0D,0x84,0xDC,0x34,0x6C, + 0xA2,0xFA,0x12,0x4A,0xC3,0x9B,0x73,0x2B, + 0x60,0x38,0xD0,0x88,0x01,0x59,0xB1,0xE9, + 0x3A,0x62,0x8A,0xD2,0x5B,0x03,0xEB,0xB3, + 0xF8,0xA0,0x48,0x10,0x99,0xC1,0x29,0x71, + 0xBF,0xE7,0x0F,0x57,0xDE,0x86,0x6E,0x36, + 0x7D,0x25,0xCD,0x95,0x1C,0x44,0xAC,0xF4, + 0x31,0x69,0x81,0xD9,0x50,0x08,0xE0,0xB8, + 0xF3,0xAB,0x43,0x1B,0x92,0xCA,0x22,0x7A, + 0xB4,0xEC,0x04,0x5C,0xD5,0x8D,0x65,0x3D, + 0x76,0x2E,0xC6,0x9E,0x17,0x4F,0xA7,0xFF +}; + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void HIGHT::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + CRYPTOPP_UNUSED(keyLength); + + for(unsigned int i=0; i<4; i++) { + m_rkey[i ] = userKey[i+12]; + m_rkey[i+4] = userKey[i ]; + } + + for(unsigned int i=0; i<8; i++) { + for(unsigned int j=0; j<8; j++) { + m_rkey[8+16*i+j] = static_cast(userKey[(j-i)&7] + DELTA[16*i+j]); + } + + for(unsigned int j=0; j<8; j++) { + m_rkey[8+16*i+j+8] = static_cast(userKey[((j-i)&7)+8] + DELTA[16*i+j+8]); + } + } +} + +void HIGHT::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // First Round + m_xx[1] = inBlock[1]; + m_xx[3] = inBlock[3]; + m_xx[5] = inBlock[5]; + m_xx[7] = inBlock[7]; + + m_xx[0] = (inBlock[0] + m_rkey[0]) & 0xFF; + m_xx[2] = (inBlock[2] ^ m_rkey[1]); + m_xx[4] = (inBlock[4] + m_rkey[2]) & 0xFF; + m_xx[6] = (inBlock[6] ^ m_rkey[3]); + + // Encryption Round + #define HIGHT_ENC(k, i0,i1,i2,i3,i4,i5,i6,i7) { \ + m_xx[i0] = (m_xx[i0] ^ (HIGHT_F0[m_xx[i1]] + m_rkey[4*k+3])) & 0xFF; \ + m_xx[i2] = (m_xx[i2] + (HIGHT_F1[m_xx[i3]] ^ m_rkey[4*k+2])) & 0xFF; \ + m_xx[i4] = (m_xx[i4] ^ (HIGHT_F0[m_xx[i5]] + m_rkey[4*k+1])) & 0xFF; \ + m_xx[i6] = (m_xx[i6] + (HIGHT_F1[m_xx[i7]] ^ m_rkey[4*k+0])) & 0xFF; \ + } + + HIGHT_ENC( 2, 7,6,5,4,3,2,1,0); + HIGHT_ENC( 3, 6,5,4,3,2,1,0,7); + HIGHT_ENC( 4, 5,4,3,2,1,0,7,6); + HIGHT_ENC( 5, 4,3,2,1,0,7,6,5); + HIGHT_ENC( 6, 3,2,1,0,7,6,5,4); + HIGHT_ENC( 7, 2,1,0,7,6,5,4,3); + HIGHT_ENC( 8, 1,0,7,6,5,4,3,2); + HIGHT_ENC( 9, 0,7,6,5,4,3,2,1); + HIGHT_ENC(10, 7,6,5,4,3,2,1,0); + HIGHT_ENC(11, 6,5,4,3,2,1,0,7); + HIGHT_ENC(12, 5,4,3,2,1,0,7,6); + HIGHT_ENC(13, 4,3,2,1,0,7,6,5); + HIGHT_ENC(14, 3,2,1,0,7,6,5,4); + HIGHT_ENC(15, 2,1,0,7,6,5,4,3); + HIGHT_ENC(16, 1,0,7,6,5,4,3,2); + HIGHT_ENC(17, 0,7,6,5,4,3,2,1); + HIGHT_ENC(18, 7,6,5,4,3,2,1,0); + HIGHT_ENC(19, 6,5,4,3,2,1,0,7); + HIGHT_ENC(20, 5,4,3,2,1,0,7,6); + HIGHT_ENC(21, 4,3,2,1,0,7,6,5); + HIGHT_ENC(22, 3,2,1,0,7,6,5,4); + HIGHT_ENC(23, 2,1,0,7,6,5,4,3); + HIGHT_ENC(24, 1,0,7,6,5,4,3,2); + HIGHT_ENC(25, 0,7,6,5,4,3,2,1); + HIGHT_ENC(26, 7,6,5,4,3,2,1,0); + HIGHT_ENC(27, 6,5,4,3,2,1,0,7); + HIGHT_ENC(28, 5,4,3,2,1,0,7,6); + HIGHT_ENC(29, 4,3,2,1,0,7,6,5); + HIGHT_ENC(30, 3,2,1,0,7,6,5,4); + HIGHT_ENC(31, 2,1,0,7,6,5,4,3); + HIGHT_ENC(32, 1,0,7,6,5,4,3,2); + HIGHT_ENC(33, 0,7,6,5,4,3,2,1); + + // Final Round + outBlock[1] = static_cast(m_xx[2]); + outBlock[3] = static_cast(m_xx[4]); + outBlock[5] = static_cast(m_xx[6]); + outBlock[7] = static_cast(m_xx[0]); + + outBlock[0] = static_cast(m_xx[1] + m_rkey[4]); + outBlock[2] = static_cast(m_xx[3] ^ m_rkey[5]); + outBlock[4] = static_cast(m_xx[5] + m_rkey[6]); + outBlock[6] = static_cast(m_xx[7] ^ m_rkey[7]); + + if (xorBlock) + xorbuf(outBlock, xorBlock, 8); +} + +void HIGHT::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + m_xx[2] = static_cast(inBlock[1]); + m_xx[4] = static_cast(inBlock[3]); + m_xx[6] = static_cast(inBlock[5]); + m_xx[0] = static_cast(inBlock[7]); + + m_xx[1] = static_cast(inBlock[0] - m_rkey[4]); + m_xx[3] = static_cast(inBlock[2] ^ m_rkey[5]); + m_xx[5] = static_cast(inBlock[4] - m_rkey[6]); + m_xx[7] = static_cast(inBlock[6] ^ m_rkey[7]); + + #define HIGHT_DEC(k, i0,i1,i2,i3,i4,i5,i6,i7) { \ + m_xx[i1] = (m_xx[i1] - (HIGHT_F1[m_xx[i2]] ^ m_rkey[4*k+2])) & 0xFF; \ + m_xx[i3] = (m_xx[i3] ^ (HIGHT_F0[m_xx[i4]] + m_rkey[4*k+1])) & 0xFF; \ + m_xx[i5] = (m_xx[i5] - (HIGHT_F1[m_xx[i6]] ^ m_rkey[4*k+0])) & 0xFF; \ + m_xx[i7] = (m_xx[i7] ^ (HIGHT_F0[m_xx[i0]] + m_rkey[4*k+3])) & 0xFF; \ + } + + HIGHT_DEC(33, 7,6,5,4,3,2,1,0); + HIGHT_DEC(32, 0,7,6,5,4,3,2,1); + HIGHT_DEC(31, 1,0,7,6,5,4,3,2); + HIGHT_DEC(30, 2,1,0,7,6,5,4,3); + HIGHT_DEC(29, 3,2,1,0,7,6,5,4); + HIGHT_DEC(28, 4,3,2,1,0,7,6,5); + HIGHT_DEC(27, 5,4,3,2,1,0,7,6); + HIGHT_DEC(26, 6,5,4,3,2,1,0,7); + HIGHT_DEC(25, 7,6,5,4,3,2,1,0); + HIGHT_DEC(24, 0,7,6,5,4,3,2,1); + HIGHT_DEC(23, 1,0,7,6,5,4,3,2); + HIGHT_DEC(22, 2,1,0,7,6,5,4,3); + HIGHT_DEC(21, 3,2,1,0,7,6,5,4); + HIGHT_DEC(20, 4,3,2,1,0,7,6,5); + HIGHT_DEC(19, 5,4,3,2,1,0,7,6); + HIGHT_DEC(18, 6,5,4,3,2,1,0,7); + HIGHT_DEC(17, 7,6,5,4,3,2,1,0); + HIGHT_DEC(16, 0,7,6,5,4,3,2,1); + HIGHT_DEC(15, 1,0,7,6,5,4,3,2); + HIGHT_DEC(14, 2,1,0,7,6,5,4,3); + HIGHT_DEC(13, 3,2,1,0,7,6,5,4); + HIGHT_DEC(12, 4,3,2,1,0,7,6,5); + HIGHT_DEC(11, 5,4,3,2,1,0,7,6); + HIGHT_DEC(10, 6,5,4,3,2,1,0,7); + HIGHT_DEC( 9, 7,6,5,4,3,2,1,0); + HIGHT_DEC( 8, 0,7,6,5,4,3,2,1); + HIGHT_DEC( 7, 1,0,7,6,5,4,3,2); + HIGHT_DEC( 6, 2,1,0,7,6,5,4,3); + HIGHT_DEC( 5, 3,2,1,0,7,6,5,4); + HIGHT_DEC( 4, 4,3,2,1,0,7,6,5); + HIGHT_DEC( 3, 5,4,3,2,1,0,7,6); + HIGHT_DEC( 2, 6,5,4,3,2,1,0,7); + + outBlock[1] = static_cast(m_xx[1]); + outBlock[3] = static_cast(m_xx[3]); + outBlock[5] = static_cast(m_xx[5]); + outBlock[7] = static_cast(m_xx[7]); + + outBlock[0] = static_cast(m_xx[0] - m_rkey[0]); + outBlock[2] = static_cast(m_xx[2] ^ m_rkey[1]); + outBlock[4] = static_cast(m_xx[4] - m_rkey[2]); + outBlock[6] = static_cast(m_xx[6] ^ m_rkey[3]); + + if (xorBlock) + xorbuf(outBlock, xorBlock, 8); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/hight.h b/external/ours/library/crypto/src/shared/original/hight.h new file mode 100755 index 000000000..0262382ba --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/hkdf.h b/external/ours/library/crypto/src/shared/original/hkdf.h new file mode 100755 index 000000000..c62560204 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/hmac.cpp b/external/ours/library/crypto/src/shared/original/hmac.cpp new file mode 100755 index 000000000..7648ea9ea --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/hmac.cpp @@ -0,0 +1,90 @@ +// hmac.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "hmac.h" + +NAMESPACE_BEGIN(CryptoPP) + +void HMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &) +{ + AssertValidKeyLength(keylength); + + Restart(); + + HashTransformation &hash = AccessHash(); + unsigned int blockSize = hash.BlockSize(); + + if (!blockSize) + throw InvalidArgument("HMAC: can only be used with a block-based hash function"); + + m_buf.resize(2*AccessHash().BlockSize() + AccessHash().DigestSize()); + + if (keylength <= blockSize) + { + // hmac.cpp:26:9: runtime error: null pointer passed as argument 2 + if (AccessIpad() && userKey && keylength) + memcpy(AccessIpad(), userKey, keylength); + } + else + { + AccessHash().CalculateDigest(AccessIpad(), userKey, keylength); + keylength = hash.DigestSize(); + } + + CRYPTOPP_ASSERT(keylength <= blockSize); + memset(AccessIpad()+keylength, 0, blockSize-keylength); + + for (unsigned int i=0; i, 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/external/ours/library/crypto/src/shared/original/hmqv.h b/external/ours/library/crypto/src/shared/original/hmqv.h new file mode 100755 index 000000000..fb11b3107 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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); + 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/external/ours/library/crypto/src/shared/original/hrtimer.cpp b/external/ours/library/crypto/src/shared/original/hrtimer.cpp new file mode 100755 index 000000000..f9b8a7cdc --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/hrtimer.cpp @@ -0,0 +1,174 @@ +// hrtimer.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "hrtimer.h" +#include "misc.h" + +#include // for NULL +#include + +#if defined(CRYPTOPP_WIN32_AVAILABLE) +#define WIN32_LEAN_AND_MEAN +#include +# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)) +# include +# if defined(WINAPI_FAMILY) +# if (WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_PHONE_APP)) +# include +# endif +# endif +#endif +#endif + +#if defined(CRYPTOPP_UNIX_AVAILABLE) +#include +#include +#include +#endif + +#include "trap.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_WIN32_AVAILABLE) +static TimerWord InitializePerformanceCounterFrequency() +{ + LARGE_INTEGER freq = {0,0}; + if (!QueryPerformanceFrequency(&freq)) + throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError())); + return freq.QuadPart; +} + +inline TimerWord PerformanceCounterFrequency() +{ + static const word64 freq = InitializePerformanceCounterFrequency(); + return freq; +} +#endif + +#ifndef CRYPTOPP_IMPORTS + +double TimerBase::ConvertTo(TimerWord t, Unit unit) +{ + static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000}; + + // When 'unit' is an enum 'Unit', a Clang warning is generated. + CRYPTOPP_ASSERT(static_cast(unit) < COUNTOF(unitsPerSecondTable)); + return static_cast(t) * unitsPerSecondTable[unit] / TicksPerSecond(); +} + +void TimerBase::StartTimer() +{ + m_last = m_start = GetCurrentTimerValue(); + m_started = true; +} + +double TimerBase::ElapsedTimeAsDouble() +{ + if (m_stuckAtZero) + return 0; + + if (m_started) + { + TimerWord now = GetCurrentTimerValue(); + if (m_last < now) // protect against OS bugs where time goes backwards + m_last = now; + return ConvertTo(m_last - m_start, m_timerUnit); + } + + StartTimer(); + return 0; +} + +unsigned long TimerBase::ElapsedTime() +{ + double elapsed = ElapsedTimeAsDouble(); + CRYPTOPP_ASSERT(elapsed <= (double)ULONG_MAX); + return (unsigned long)elapsed; +} + +TimerWord Timer::GetCurrentTimerValue() +{ +#if defined(CRYPTOPP_WIN32_AVAILABLE) + // Use the first union member to avoid an uninitialized warning + LARGE_INTEGER now = {0,0}; + if (!QueryPerformanceCounter(&now)) + throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError())); + return now.QuadPart; +#elif defined(CRYPTOPP_UNIX_AVAILABLE) + timeval now; + gettimeofday(&now, NULLPTR); + return (TimerWord)now.tv_sec * 1000000 + now.tv_usec; +#else + // clock_t now; + return clock(); +#endif +} + +TimerWord Timer::TicksPerSecond() +{ +#if defined(CRYPTOPP_WIN32_AVAILABLE) + return PerformanceCounterFrequency(); +#elif defined(CRYPTOPP_UNIX_AVAILABLE) + return 1000000; +#else + return CLOCKS_PER_SEC; +#endif +} + +#endif // #ifndef CRYPTOPP_IMPORTS + +TimerWord ThreadUserTimer::GetCurrentTimerValue() +{ +#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(THREAD_TIMER_AVAILABLE) + static bool getCurrentThreadImplemented = true; + if (getCurrentThreadImplemented) + { + FILETIME now, ignored; + if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now)) + { + const DWORD lastError = GetLastError(); + if (lastError == ERROR_CALL_NOT_IMPLEMENTED) + { + getCurrentThreadImplemented = false; + goto GetCurrentThreadNotImplemented; + } + throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError)); + } + return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32); + } +GetCurrentThreadNotImplemented: + return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC); +#elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE) + LARGE_INTEGER now; + if (!QueryPerformanceCounter(&now)) + { + const DWORD lastError = GetLastError(); + throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: QueryPerformanceCounter failed with error " + IntToString(lastError)); + } + return now.QuadPart; +#elif defined(CRYPTOPP_UNIX_AVAILABLE) + tms now; + times(&now); + return now.tms_utime; +#else + return clock(); +#endif +} + +TimerWord ThreadUserTimer::TicksPerSecond() +{ +#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(THREAD_TIMER_AVAILABLE) + return 10*1000*1000; +#elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE) + static const TimerWord ticksPerSecond = PerformanceCounterFrequency(); + return ticksPerSecond; +#elif defined(CRYPTOPP_UNIX_AVAILABLE) + static const long ticksPerSecond = sysconf(_SC_CLK_TCK); + return ticksPerSecond; +#else + return CLOCKS_PER_SEC; +#endif +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/hrtimer.h b/external/ours/library/crypto/src/shared/original/hrtimer.h new file mode 100755 index 000000000..a7e7d9778 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/ida.cpp b/external/ours/library/crypto/src/shared/original/ida.cpp new file mode 100755 index 000000000..1c8b3ab29 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ida.cpp @@ -0,0 +1,418 @@ +// ida.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +#include "ida.h" +#include "stdcpp.h" +#include "algebra.h" +#include "polynomi.h" +#include "polynomi.cpp" + +NAMESPACE_BEGIN(CryptoPP) + +#if (defined(_MSC_VER) && (_MSC_VER < 1400)) && !defined(__MWERKS__) + // VC60 and VC7 workaround: built-in reverse_iterator has two template parameters, Dinkumware only has one + typedef std::reverse_bidirectional_iterator RevIt; +#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) + typedef std::reverse_iterator RevIt; +#else + typedef std::reverse_iterator RevIt; +#endif + +void RawIDA::IsolatedInitialize(const NameValuePairs ¶meters) +{ + if (!parameters.GetIntValue("RecoveryThreshold", m_threshold)) + throw InvalidArgument("RawIDA: missing RecoveryThreshold argument"); + + CRYPTOPP_ASSERT(m_threshold > 0); + if (m_threshold <= 0) + throw InvalidArgument("RawIDA: RecoveryThreshold must be greater than 0"); + + m_lastMapPosition = m_inputChannelMap.end(); + m_channelsReady = 0; + m_channelsFinished = 0; + m_w.New(m_threshold); + m_y.New(m_threshold); + m_inputQueues.reserve(m_threshold); + + m_outputChannelIds.clear(); + m_outputChannelIdStrings.clear(); + m_outputQueues.clear(); + + word32 outputChannelID; + if (parameters.GetValue("OutputChannelID", outputChannelID)) + AddOutputChannel(outputChannelID); + else + { + int nShares = parameters.GetIntValueWithDefault("NumberOfShares", m_threshold); + CRYPTOPP_ASSERT(nShares > 0); + if (nShares <= 0) {nShares = m_threshold;} + for (unsigned int i=0; i< (unsigned int)(nShares); i++) + AddOutputChannel(i); + } +} + +unsigned int RawIDA::InsertInputChannel(word32 channelId) +{ + if (m_lastMapPosition != m_inputChannelMap.end()) + { + if (m_lastMapPosition->first == channelId) + goto skipFind; + ++m_lastMapPosition; + if (m_lastMapPosition != m_inputChannelMap.end() && m_lastMapPosition->first == channelId) + goto skipFind; + } + m_lastMapPosition = m_inputChannelMap.find(channelId); + +skipFind: + if (m_lastMapPosition == m_inputChannelMap.end()) + { + if (m_inputChannelIds.size() == size_t(m_threshold)) + return m_threshold; + + m_lastMapPosition = m_inputChannelMap.insert(InputChannelMap::value_type(channelId, (unsigned int)m_inputChannelIds.size())).first; + m_inputQueues.push_back(MessageQueue()); + m_inputChannelIds.push_back(channelId); + + if (m_inputChannelIds.size() == size_t(m_threshold)) + PrepareInterpolation(); + } + return m_lastMapPosition->second; +} + +unsigned int RawIDA::LookupInputChannel(word32 channelId) const +{ + std::map::const_iterator it = m_inputChannelMap.find(channelId); + if (it == m_inputChannelMap.end()) + return m_threshold; + else + return it->second; +} + +void RawIDA::ChannelData(word32 channelId, const byte *inString, size_t length, bool messageEnd) +{ + int i = InsertInputChannel(channelId); + if (i < m_threshold) + { + lword size = m_inputQueues[i].MaxRetrievable(); + m_inputQueues[i].Put(inString, length); + if (size < 4 && size + length >= 4) + { + m_channelsReady++; + if (m_channelsReady == size_t(m_threshold)) + ProcessInputQueues(); + } + + if (messageEnd) + { + m_inputQueues[i].MessageEnd(); + if (m_inputQueues[i].NumberOfMessages() == 1) + { + m_channelsFinished++; + if (m_channelsFinished == size_t(m_threshold)) + { + m_channelsReady = 0; + for (i=0; i= m_v.size()) + { + m_v.resize(i+1); + m_outputToInput.resize(i+1); + } + + m_outputToInput[i] = LookupInputChannel(m_outputChannelIds[i]); + if (m_outputToInput[i] == size_t(m_threshold) && i * size_t(m_threshold) <= 1000*1000) + { + m_v[i].resize(m_threshold); + PrepareBulkPolynomialInterpolationAt(m_gf32, m_v[i].begin(), m_outputChannelIds[i], &(m_inputChannelIds[0]), m_w.begin(), m_threshold); + } +} + +void RawIDA::AddOutputChannel(word32 channelId) +{ + m_outputChannelIds.push_back(channelId); + m_outputChannelIdStrings.push_back(WordToString(channelId)); + m_outputQueues.push_back(ByteQueue()); + if (m_inputChannelIds.size() == size_t(m_threshold)) + ComputeV((unsigned int)m_outputChannelIds.size() - 1); +} + +void RawIDA::PrepareInterpolation() +{ + CRYPTOPP_ASSERT(m_inputChannelIds.size() == size_t(m_threshold)); + PrepareBulkPolynomialInterpolation(m_gf32, m_w.begin(), &(m_inputChannelIds[0]), (unsigned int)(m_threshold)); + for (unsigned int i=0; i 0 : m_channelsReady == size_t(m_threshold)) + { + m_channelsReady = 0; + for (i=0; i 0 || queue.MaxRetrievable() >= 4; + } + + for (i=0; (unsigned int)i 0 && m_outputQueues[0].AnyRetrievable()) + FlushOutputQueues(); + + if (finished) + { + OutputMessageEnds(); + + m_channelsReady = 0; + m_channelsFinished = 0; + m_v.clear(); + + std::vector inputQueues; + std::vector inputChannelIds; + + inputQueues.swap(m_inputQueues); + inputChannelIds.swap(m_inputChannelIds); + m_inputChannelMap.clear(); + m_lastMapPosition = m_inputChannelMap.end(); + + for (i=0; iChannelMessageEnd(m_outputChannelIdStrings[i], GetAutoSignalPropagation()-1); + } +} + +// **************************************************************** + +void SecretSharing::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_pad = parameters.GetValueWithDefault("AddPadding", true); + m_ida.IsolatedInitialize(parameters); +} + +size_t SecretSharing::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (!blocking) + throw BlockingInputOnly("SecretSharing"); + + SecByteBlock buf(UnsignedMin(256, length)); + unsigned int threshold = m_ida.GetThreshold(); + while (length > 0) + { + size_t len = STDMIN(length, buf.size()); + m_ida.ChannelData(0xffffffff, begin, len, false); + for (unsigned int i=0; i 0) + SecretSharing::Put(0); + } + m_ida.ChannelData(0xffffffff, NULLPTR, 0, true); + for (unsigned int i=0; iMessageEnd(GetAutoSignalPropagation()-1); +} + +// **************************************************************** + +void InformationDispersal::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_nextChannel = 0; + m_pad = parameters.GetValueWithDefault("AddPadding", true); + m_ida.IsolatedInitialize(parameters); +} + +size_t InformationDispersal::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (!blocking) + throw BlockingInputOnly("InformationDispersal"); + + while (length--) + { + m_ida.ChannelData(m_nextChannel, begin, 1, false); + begin++; + m_nextChannel++; + if (m_nextChannel == m_ida.GetThreshold()) + m_nextChannel = 0; + } + + if (messageEnd) + { + m_ida.SetAutoSignalPropagation(messageEnd-1); + if (m_pad) + InformationDispersal::Put(1); + for (word32 i=0; iMessageEnd(GetAutoSignalPropagation()-1); +} + +size_t PaddingRemover::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (!blocking) + throw BlockingInputOnly("PaddingRemover"); + + const byte *const end = begin + length; + + if (m_possiblePadding) + { + size_t len = FindIfNot(begin, end, byte(0)) - begin; + m_zeroCount += len; + begin += len; + if (begin == end) + return 0; + + AttachedTransformation()->Put(1); + while (m_zeroCount--) + AttachedTransformation()->Put(0); + AttachedTransformation()->Put(*begin++); + m_possiblePadding = false; + } + + const byte *x = FindIfNot(RevIt(end), RevIt(begin), byte(0)).base(); + if (x != begin && *(x-1) == 1) + { + AttachedTransformation()->Put(begin, x-begin-1); + m_possiblePadding = true; + m_zeroCount = end - x; + } + else + AttachedTransformation()->Put(begin, end-begin); + + if (messageEnd) + { + m_possiblePadding = false; + Output(0, begin, length, messageEnd, blocking); + } + return 0; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/ida.h b/external/ours/library/crypto/src/shared/original/ida.h new file mode 100755 index 000000000..82b48df11 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/idea.cpp b/external/ours/library/crypto/src/shared/original/idea.cpp new file mode 100755 index 000000000..dde2fdb45 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/idea.cpp @@ -0,0 +1,191 @@ +// idea.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "idea.h" +#include "misc.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +static const int IDEA_KEYLEN=(6*IDEA::ROUNDS+4); // key schedule length in # of word16s + +#define low16(x) ((x)&0xffff) // compiler should be able to optimize this away if word is 16 bits +#define high16(x) ((x)>>16) + +CRYPTOPP_COMPILE_ASSERT(sizeof(IDEA::Word) >= 2); + +// should use an inline function but macros are still faster in MSVC 4.0 +#define DirectMUL(a,b) \ +{ \ + word32 p=(word32)low16(a)*b; \ + \ + if (p) \ + { \ + p = low16(p) - high16(p); \ + a = (IDEA::Word)p - (IDEA::Word)high16(p); \ + } \ + else \ + a = 1-a-b; \ +} + +#ifdef IDEA_LARGECACHE +volatile bool IDEA::Base::tablesBuilt = false; +word16 IDEA::Base::log[0x10000]; +word16 IDEA::Base::antilog[0x10000]; + +void IDEA::Base::BuildLogTables() +{ + if (tablesBuilt) + return; + else + { + tablesBuilt = true; + + IDEA::Word x=1; + word32 i; + + for (i=0; i<0x10000; i++) + { + antilog[i] = (word16)x; + DirectMUL(x, 3); + } + + for (i=0; i<0x10000; i++) + log[antilog[i]] = (word16)i; + } +} + +void IDEA::Base::LookupKeyLogs() +{ + IDEA::Word* Z=key; + int r=ROUNDS; + do + { + Z[0] = log[Z[0]]; + Z[3] = log[Z[3]]; + Z[4] = log[Z[4]]; + Z[5] = log[Z[5]]; + Z+=6; + } while (--r); + Z[0] = log[Z[0]]; + Z[3] = log[Z[3]]; +} + +inline void IDEA::Base::LookupMUL(IDEA::Word &a, IDEA::Word b) +{ + a = antilog[low16(log[low16(a)]+b)]; +} +#endif // IDEA_LARGECACHE + +void IDEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + +#ifdef IDEA_LARGECACHE + BuildLogTables(); +#endif + + EnKey(userKey); + + if (!IsForwardTransformation()) + DeKey(); + +#ifdef IDEA_LARGECACHE + LookupKeyLogs(); +#endif +} + +void IDEA::Base::EnKey (const byte *userKey) +{ + unsigned int i; + + for (i=0; i<8; i++) + m_key[i] = ((IDEA::Word)userKey[2*i]<<8) | userKey[2*i+1]; + + for (; i> 7)); + } +} + +static IDEA::Word MulInv(IDEA::Word x) +{ + IDEA::Word y=x; + for (unsigned i=0; i<15; i++) + { + DirectMUL(y,low16(y)); + DirectMUL(y,x); + } + return low16(y); +} + +static inline IDEA::Word AddInv(IDEA::Word x) +{ + return low16(0-x); +} + +void IDEA::Base::DeKey() +{ + FixedSizeSecBlock tempkey; + size_t i; + + for (i=0; i0)]); + tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2-(i>0)]); + tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]); + tempkey[i*6+4] = m_key[(ROUNDS-1-i)*6+4]; + tempkey[i*6+5] = m_key[(ROUNDS-1-i)*6+5]; + } + + tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]); + tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1]); + tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2]); + tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]); + + m_key = tempkey; +} + +#ifdef IDEA_LARGECACHE +#define MUL(a,b) LookupMUL(a,b) +#else +#define MUL(a,b) DirectMUL(a,b) +#endif + +void IDEA::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + typedef BlockGetAndPut Block; + + const IDEA::Word *key = m_key; + IDEA::Word x0,x1,x2,x3,t0,t1; + Block::Get(inBlock)(x0)(x1)(x2)(x3); + + for (unsigned int i=0; i, 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/external/ours/library/crypto/src/shared/original/integer.cpp b/external/ours/library/crypto/src/shared/original/integer.cpp new file mode 100755 index 000000000..dac3ef7c6 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/integer.cpp @@ -0,0 +1,4910 @@ +// integer.cpp - originally written and placed in the public domain by Wei Dai +// contains public domain code contributed by Alister Lee and Leonard Janke + +// Notes by JW: The Integer class needs to do two things. First, it needs +// to set function pointers on some platforms, like X86 and X64. The +// function pointers select a fast multiply and addition based on the cpu. +// Second, it wants to create Integer::Zero(), Integer::One() and +// Integer::Two(). +// The function pointers are initialized in the InitializeInteger class by +// calling SetFunctionPointers(). The call to SetFunctionPointers() is +// guarded to run once using a double-checked pattern. We don't use C++ +// std::call_once due to bad interactions between libstdc++, glibc and +// pthreads. The bad interactions were causing crashes for us on platforms +// like Sparc and PowerPC. Since we are only setting function pointers we +// don't have to worry about leaking memory. The worst case seems to be the +// pointers gets written twice until the init flag is set and visible to +// all threads. +// For Integer::Zero(), Integer::One() and Integer::Two(), we use one of three +// strategies. First, if initialization priorities are available then we use +// them. Initialization priorities are init_priority() on Linux and init_seg() +// on Windows. OS X and several other platforms lack them. Initialization +// priorities are platform specific but they are also the most trouble free +// with determisitic destruction. +// Second, if C++11 dynamic initialization is available, then we use it. After +// the std::call_once fiasco we moved to dynamic initialization to avoid +// unknown troubles platforms that are tested less frequently. In addition +// Microsoft platforms mostly do not provide dynamic initialization. +// The MSDN docs claim they do but they don't in practice because we need +// Visual Studio 2017 and Windows 10 or above. +// Third, we fall back to Wei's original code of a Singleton. Wei's original +// code was much simpler. It simply used the Singleton pattern, but it always +// produced memory findings on some platforms. The Singleton generates memory +// findings because it uses a Create On First Use pattern (a dumb Nifty +// Counter) and the compiler had to be smart enough to fold them to return +// the same object. Unix and Linux compilers do a good job of folding objects, +// but Microsoft compilers do a rather poor job for some versions of the +// compiler. +// Another problem with the Singleton is resource destruction requires running +// resource acquisition in reverse. For resources provided through the +// Singletons, there is no way to express the dependency order to safely +// destroy resources. (That's one of the problems C++11 dynamic +// intitialization with concurrent execution is supposed to solve). +// The final problem with Singletons is resource/memory exhaustion in languages +// like Java and .Net. Java and .Net load and unload a native DLL hundreds or +// thousands of times during the life of a program. Each load produces a +// memory leak and they can add up quickly. If they library is being used in +// Java or .Net then Singleton must be avoided at all costs. +// +// The code below has a path cut-in for BMI2 using mulx and adcx instructions. +// There was a modest speedup of approximately 0.03 ms in public key Integer +// operations. We had to disable BMI2 for the moment because some OS X machines +// were advertising BMI/BMI2 support but caused SIGILL's at runtime. Also see +// https://github.com/weidai11/cryptopp/issues/850. + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "integer.h" +#include "secblock.h" +#include "modarith.h" +#include "nbtheory.h" +#include "smartptr.h" +#include "algparam.h" +#include "filters.h" +#include "stdcpp.h" +#include "asn.h" +#include "oids.h" +#include "words.h" +#include "pubkey.h" // for P1363_KDF2 +#include "sha.h" +#include "cpu.h" +#include "misc.h" + +#include + +#if (_MSC_VER >= 1400) && !defined(_M_ARM) + #include +#endif + +#ifdef __DECCXX + #include +#endif + +// "Error: The operand ___LKDB cannot be assigned to", +// http://github.com/weidai11/cryptopp/issues/188 +#if (__SUNPRO_CC >= 0x5130) +# define MAYBE_CONST +# define MAYBE_UNCONST_CAST(x) const_cast(x) +#else +# define MAYBE_CONST const +# define MAYBE_UNCONST_CAST(x) x +#endif + +// "Inline assembly operands don't work with .intel_syntax", +// http://llvm.org/bugs/show_bug.cgi?id=24232 +#if CRYPTOPP_BOOL_X32 || defined(CRYPTOPP_DISABLE_MIXED_ASM) +# undef CRYPTOPP_X86_ASM_AVAILABLE +# undef CRYPTOPP_X32_ASM_AVAILABLE +# undef CRYPTOPP_X64_ASM_AVAILABLE +# undef CRYPTOPP_SSE2_ASM_AVAILABLE +# undef CRYPTOPP_SSSE3_ASM_AVAILABLE +#else +# define CRYPTOPP_INTEGER_SSE2 (CRYPTOPP_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86)) +#endif + +// ***************** C++ Static Initialization ******************** + +NAMESPACE_BEGIN(CryptoPP) + +// Function body near the middle of the file +static void SetFunctionPointers(); + +// Use a double-checked pattern. We are not leaking anything so it +// does not matter if a pointer is written twice during a race. +// Avoid std::call_once due to too many problems on platforms like +// Solaris and Sparc. Also see +// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 and +// http://github.com/weidai11/cryptopp/issues/707. +InitializeInteger::InitializeInteger() +{ + static bool s_flag; + MEMORY_BARRIER(); + if (s_flag == false) + { + SetFunctionPointers(); + s_flag = true; + MEMORY_BARRIER(); + } +} + +template +struct NewInteger +{ + Integer * operator()() const + { + return new Integer(i); + } +}; + +// ***************** Library code ******************** + +inline static int Compare(const word *A, const word *B, size_t N) +{ + while (N--) + if (A[N] > B[N]) + return 1; + else if (A[N] < B[N]) + return -1; + + return 0; +} + +inline static int Increment(word *A, size_t N, word B=1) +{ + CRYPTOPP_ASSERT(N); + word t = A[0]; + A[0] = t+B; + if (A[0] >= t) + return 0; + for (unsigned i=1; i>(WORD_BITS-1)); d##0 = 2*d##0 + (c>>(WORD_BITS-1)); c *= 2; + #endif + #ifndef Acc2WordsBy2 + #define Acc2WordsBy2(a, b) a##0 += b##0; a##1 += a##0 < b##0; a##1 += b##1; + #endif + #define AddWithCarry(u, a, b) {word t = a+b; u##0 = t + u##1; u##1 = (ta) + (u##0>t);} + #define GetCarry(u) u##1 + #define GetBorrow(u) u##1 +#else + #define Declare2Words(x) dword x; + #if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) && (defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64)) + #define MultiplyWords(p, a, b) p = __emulu(a, b); + #else + #define MultiplyWords(p, a, b) p = (dword)a*b; + #endif + #define AssignWord(a, b) a = b; + #define Add2WordsBy1(a, b, c) a = b + c; + #define Acc2WordsBy2(a, b) a += b; + #define LowWord(a) word(a) + #define HighWord(a) word(a>>WORD_BITS) + #define Double3Words(c, d) d = 2*d + (c>>(WORD_BITS-1)); c *= 2; + #define AddWithCarry(u, a, b) u = dword(a) + b + GetCarry(u); + #define SubtractWithBorrow(u, a, b) u = dword(a) - b - GetBorrow(u); + #define GetCarry(u) HighWord(u) + #define GetBorrow(u) word(u>>(WORD_BITS*2-1)) +#endif +#ifndef MulAcc + #define MulAcc(c, d, a, b) MultiplyWords(p, a, b); Acc2WordsBy1(p, c); c = LowWord(p); Acc2WordsBy1(d, HighWord(p)); +#endif +#ifndef Acc2WordsBy1 + #define Acc2WordsBy1(a, b) Add2WordsBy1(a, a, b) +#endif +#ifndef Acc3WordsBy2 + #define Acc3WordsBy2(c, d, e) Acc2WordsBy1(e, c); c = LowWord(e); Add2WordsBy1(e, d, HighWord(e)); +#endif + +class DWord +{ +public: +#if defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE) + DWord() {std::memset(&m_whole, 0x00, sizeof(m_whole));} +#else + DWord() {std::memset(&m_halfs, 0x00, sizeof(m_halfs));} +#endif + +#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + explicit DWord(word low) : m_whole(low) { } +#else + explicit DWord(word low) + { + m_halfs.high = 0; + m_halfs.low = low; + } +#endif + +#if defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE) + DWord(word low, word high) : m_whole() +#else + DWord(word low, word high) : m_halfs() +#endif + { +#if defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE) +# if (CRYPTOPP_LITTLE_ENDIAN) + const word t[2] = {low,high}; + memcpy(&m_whole, t, sizeof(m_whole)); +# else + const word t[2] = {high,low}; + memcpy(&m_whole, t, sizeof(m_whole)); +# endif +#else + m_halfs.low = low; + m_halfs.high = high; +#endif + } + + static DWord Multiply(word a, word b) + { + DWord r; + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + r.m_whole = (dword)a * b; + #elif defined(MultiplyWordsLoHi) + MultiplyWordsLoHi(r.m_halfs.low, r.m_halfs.high, a, b); + #else + CRYPTOPP_ASSERT(0); + #endif + return r; + } + + static DWord MultiplyAndAdd(word a, word b, word c) + { + DWord r = Multiply(a, b); + return r += c; + } + + DWord & operator+=(word a) + { + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + m_whole = m_whole + a; + #else + m_halfs.low += a; + m_halfs.high += (m_halfs.low < a); + #endif + return *this; + } + + DWord operator+(word a) + { + DWord r; + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + r.m_whole = m_whole + a; + #else + r.m_halfs.low = m_halfs.low + a; + r.m_halfs.high = m_halfs.high + (r.m_halfs.low < a); + #endif + return r; + } + + DWord operator-(DWord a) + { + DWord r; + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + r.m_whole = m_whole - a.m_whole; + #else + r.m_halfs.low = m_halfs.low - a.m_halfs.low; + r.m_halfs.high = m_halfs.high - a.m_halfs.high - (r.m_halfs.low > m_halfs.low); + #endif + return r; + } + + DWord operator-(word a) + { + DWord r; + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + r.m_whole = m_whole - a; + #else + r.m_halfs.low = m_halfs.low - a; + r.m_halfs.high = m_halfs.high - (r.m_halfs.low > m_halfs.low); + #endif + return r; + } + + // returns quotient, which must fit in a word + word operator/(word divisor); + + word operator%(word a); + + bool operator!() const + { + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + return !m_whole; + #else + return !m_halfs.high && !m_halfs.low; + #endif + } + + // TODO: When NATIVE_DWORD is in effect, we access high and low, which are inactive + // union members, and that's UB. Also see http://stackoverflow.com/q/11373203. + word GetLowHalf() const {return m_halfs.low;} + word GetHighHalf() const {return m_halfs.high;} + word GetHighHalfAsBorrow() const {return 0-m_halfs.high;} + +private: + // Issue 274, "Types cannot be declared in anonymous union", + // http://github.com/weidai11/cryptopp/issues/274 + // Thanks to Martin Bonner at http://stackoverflow.com/a/39507183 + struct half_words + { + #if (CRYPTOPP_LITTLE_ENDIAN) + word low; + word high; + #else + word high; + word low; + #endif + }; + union + { + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + dword m_whole; + #endif + half_words m_halfs; + }; +}; + +class Word +{ +public: + Word() : m_whole(0) {} + Word(word value) : m_whole(value) {} + Word(hword low, hword high) : m_whole(low | (word(high) << (WORD_BITS/2))) {} + + static Word Multiply(hword a, hword b) + { + Word r; + r.m_whole = (word)a * b; + return r; + } + + Word operator-(Word a) + { + Word r; + r.m_whole = m_whole - a.m_whole; + return r; + } + + Word operator-(hword a) + { + Word r; + r.m_whole = m_whole - a; + return r; + } + + // returns quotient, which must fit in a word + hword operator/(hword divisor) + { + return hword(m_whole / divisor); + } + + bool operator!() const + { + return !m_whole; + } + + word GetWhole() const {return m_whole;} + hword GetLowHalf() const {return hword(m_whole);} + hword GetHighHalf() const {return hword(m_whole>>(WORD_BITS/2));} + hword GetHighHalfAsBorrow() const {return 0-hword(m_whole>>(WORD_BITS/2));} + +private: + word m_whole; +}; + +// do a 3 word by 2 word divide, returns quotient and leaves remainder in A +template +S DivideThreeWordsByTwo(S *A, S B0, S B1, D *dummy=NULLPTR) +{ + CRYPTOPP_UNUSED(dummy); + + // Assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S + CRYPTOPP_ASSERT(A[2] < B1 || (A[2]==B1 && A[1] < B0)); + + // Profiling guided the flow below. + + // estimate the quotient: do a 2 S by 1 S divide. + S Q; bool pre = (S(B1+1) == 0); + if (B1 > 0 && !pre) + Q = D(A[1], A[2]) / S(B1+1); + else if (pre) + Q = A[2]; + else + Q = D(A[0], A[1]) / B0; + + // now subtract Q*B from A + D p = D::Multiply(B0, Q); + D u = (D) A[0] - p.GetLowHalf(); + A[0] = u.GetLowHalf(); + u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - D::Multiply(B1, Q); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + + // Q <= actual quotient, so fix it + while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) + { + u = (D) A[0] - B0; + A[0] = u.GetLowHalf(); + u = (D) A[1] - B1 - u.GetHighHalfAsBorrow(); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + Q++; + CRYPTOPP_ASSERT(Q); // shouldn't overflow + } + + return Q; +} + +// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1 +template +inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B) +{ + // Profiling guided the flow below. + + if (!!B) + { + S Q[2]; + T[0] = Al.GetLowHalf(); + T[1] = Al.GetHighHalf(); + T[2] = Ah.GetLowHalf(); + T[3] = Ah.GetHighHalf(); + Q[1] = DivideThreeWordsByTwo(T+1, B.GetLowHalf(), B.GetHighHalf()); + Q[0] = DivideThreeWordsByTwo(T, B.GetLowHalf(), B.GetHighHalf()); + return D(Q[0], Q[1]); + } + else // if divisor is 0, we assume divisor==2**(2*WORD_BITS) + { + return D(Ah.GetLowHalf(), Ah.GetHighHalf()); + } +} + +// returns quotient, which must fit in a word +inline word DWord::operator/(word a) +{ + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + return word(m_whole / a); + #else + hword r[4]; + return DivideFourWordsByTwo(r, m_halfs.low, m_halfs.high, a).GetWhole(); + #endif +} + +inline word DWord::operator%(word a) +{ + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + return word(m_whole % a); + #else + if (a < (word(1) << (WORD_BITS/2))) + { + hword h = hword(a); + word r = m_halfs.high % h; + r = ((m_halfs.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h; + return hword((hword(m_halfs.low) + (r << (WORD_BITS/2))) % h); + } + else + { + hword r[4]; + DivideFourWordsByTwo(r, m_halfs.low, m_halfs.high, a); + return Word(r[0], r[1]).GetWhole(); + } + #endif +} + +// ******************************************************** + +// Use some tricks to share assembly code between MSVC, GCC, Clang and Sun CC. +#if defined(__GNUC__) + #define AddPrologue \ + int result; \ + __asm__ __volatile__ \ + ( \ + INTEL_NOPREFIX + #define AddEpilogue \ + ATT_PREFIX \ + : "=a" (result)\ + : "d" (C), "a" (A), "D" (B), "c" (N) \ + : "%esi", "memory", "cc" \ + );\ + return result; + #define MulPrologue \ + __asm__ __volatile__ \ + ( \ + INTEL_NOPREFIX \ + AS1( push ebx) \ + AS2( mov ebx, edx) + #define MulEpilogue \ + AS1( pop ebx) \ + ATT_PREFIX \ + : \ + : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B) \ + : "%esi", "memory", "cc" \ + ); + #define SquPrologue MulPrologue + #define SquEpilogue \ + AS1( pop ebx) \ + ATT_PREFIX \ + : \ + : "d" (s_maskLow16), "c" (C), "a" (A) \ + : "%esi", "%edi", "memory", "cc" \ + ); + #define TopPrologue MulPrologue + #define TopEpilogue \ + AS1( pop ebx) \ + ATT_PREFIX \ + : \ + : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B), "S" (L) \ + : "memory", "cc" \ + ); +#else + #define AddPrologue \ + __asm push edi \ + __asm push esi \ + __asm mov eax, [esp+12] \ + __asm mov edi, [esp+16] + #define AddEpilogue \ + __asm pop esi \ + __asm pop edi \ + __asm ret 8 + #define SaveEBX + #define RestoreEBX + #define SquPrologue \ + AS2( mov eax, A) \ + AS2( mov ecx, C) \ + SaveEBX \ + AS2( lea ebx, s_maskLow16) + #define MulPrologue \ + AS2( mov eax, A) \ + AS2( mov edi, B) \ + AS2( mov ecx, C) \ + SaveEBX \ + AS2( lea ebx, s_maskLow16) + #define TopPrologue \ + AS2( mov eax, A) \ + AS2( mov edi, B) \ + AS2( mov ecx, C) \ + AS2( mov esi, L) \ + SaveEBX \ + AS2( lea ebx, s_maskLow16) + #define SquEpilogue RestoreEBX + #define MulEpilogue RestoreEBX + #define TopEpilogue RestoreEBX +#endif + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +int Baseline_Add(size_t N, word *C, const word *A, const word *B); +int Baseline_Sub(size_t N, word *C, const word *A, const word *B); +} +#elif defined(CRYPTOPP_X64_ASM_AVAILABLE) && defined(__GNUC__) && defined(CRYPTOPP_WORD128_AVAILABLE) +int Baseline_Add(size_t N, word *C, const word *A, const word *B) +{ + word result; + __asm__ __volatile__ + ( + INTEL_NOPREFIX + AS1( neg %1) + ASJ( jz, 1, f) + AS2( mov %0,[%3+8*%1]) + AS2( add %0,[%4+8*%1]) + AS2( mov [%2+8*%1],%0) + ASL(0) + AS2( mov %0,[%3+8*%1+8]) + AS2( adc %0,[%4+8*%1+8]) + AS2( mov [%2+8*%1+8],%0) + AS2( lea %1,[%1+2]) + ASJ( jrcxz, 1, f) + AS2( mov %0,[%3+8*%1]) + AS2( adc %0,[%4+8*%1]) + AS2( mov [%2+8*%1],%0) + ASJ( jmp, 0, b) + ASL(1) + AS2( mov %0, 0) + AS2( adc %0, %0) + ATT_NOPREFIX + : "=&r" (result), "+c" (N) + : "r" (C+N), "r" (A+N), "r" (B+N) + : "memory", "cc" + ); + return (int)result; +} + +int Baseline_Sub(size_t N, word *C, const word *A, const word *B) +{ + word result; + __asm__ __volatile__ + ( + INTEL_NOPREFIX + AS1( neg %1) + ASJ( jz, 1, f) + AS2( mov %0,[%3+8*%1]) + AS2( sub %0,[%4+8*%1]) + AS2( mov [%2+8*%1],%0) + ASL(0) + AS2( mov %0,[%3+8*%1+8]) + AS2( sbb %0,[%4+8*%1+8]) + AS2( mov [%2+8*%1+8],%0) + AS2( lea %1,[%1+2]) + ASJ( jrcxz, 1, f) + AS2( mov %0,[%3+8*%1]) + AS2( sbb %0,[%4+8*%1]) + AS2( mov [%2+8*%1],%0) + ASJ( jmp, 0, b) + ASL(1) + AS2( mov %0, 0) + AS2( adc %0, %0) + ATT_NOPREFIX + : "=&r" (result), "+c" (N) + : "r" (C+N), "r" (A+N), "r" (B+N) + : "memory", "cc" + ); + return (int)result; +} +#elif defined(CRYPTOPP_X86_ASM_AVAILABLE) && CRYPTOPP_BOOL_X86 +CRYPTOPP_NAKED int CRYPTOPP_FASTCALL Baseline_Add(size_t N, word *C, const word *A, const word *B) +{ + AddPrologue + + // now: eax = A, edi = B, edx = C, ecx = N + AS2( lea eax, [eax+4*ecx]) + AS2( lea edi, [edi+4*ecx]) + AS2( lea edx, [edx+4*ecx]) + + AS1( neg ecx) // ecx is negative index + AS2( test ecx, 2) // this clears carry flag + ASJ( jz, 0, f) + AS2( sub ecx, 2) + ASJ( jmp, 1, f) + + ASL(0) + ASJ( jecxz, 2, f) // loop until ecx overflows and becomes zero + AS2( mov esi,[eax+4*ecx]) + AS2( adc esi,[edi+4*ecx]) + AS2( mov [edx+4*ecx],esi) + AS2( mov esi,[eax+4*ecx+4]) + AS2( adc esi,[edi+4*ecx+4]) + AS2( mov [edx+4*ecx+4],esi) + ASL(1) + AS2( mov esi,[eax+4*ecx+8]) + AS2( adc esi,[edi+4*ecx+8]) + AS2( mov [edx+4*ecx+8],esi) + AS2( mov esi,[eax+4*ecx+12]) + AS2( adc esi,[edi+4*ecx+12]) + AS2( mov [edx+4*ecx+12],esi) + + AS2( lea ecx,[ecx+4]) // advance index, avoid inc which causes slowdown on Intel Core 2 + ASJ( jmp, 0, b) + + ASL(2) + AS2( mov eax, 0) + AS1( setc al) // store carry into eax (return result register) + + AddEpilogue + + // http://github.com/weidai11/cryptopp/issues/340 + CRYPTOPP_UNUSED(A); CRYPTOPP_UNUSED(B); + CRYPTOPP_UNUSED(C); CRYPTOPP_UNUSED(N); +} + +CRYPTOPP_NAKED int CRYPTOPP_FASTCALL Baseline_Sub(size_t N, word *C, const word *A, const word *B) +{ + AddPrologue + + // now: eax = A, edi = B, edx = C, ecx = N + AS2( lea eax, [eax+4*ecx]) + AS2( lea edi, [edi+4*ecx]) + AS2( lea edx, [edx+4*ecx]) + + AS1( neg ecx) // ecx is negative index + AS2( test ecx, 2) // this clears carry flag + ASJ( jz, 0, f) + AS2( sub ecx, 2) + ASJ( jmp, 1, f) + + ASL(0) + ASJ( jecxz, 2, f) // loop until ecx overflows and becomes zero + AS2( mov esi,[eax+4*ecx]) + AS2( sbb esi,[edi+4*ecx]) + AS2( mov [edx+4*ecx],esi) + AS2( mov esi,[eax+4*ecx+4]) + AS2( sbb esi,[edi+4*ecx+4]) + AS2( mov [edx+4*ecx+4],esi) + ASL(1) + AS2( mov esi,[eax+4*ecx+8]) + AS2( sbb esi,[edi+4*ecx+8]) + AS2( mov [edx+4*ecx+8],esi) + AS2( mov esi,[eax+4*ecx+12]) + AS2( sbb esi,[edi+4*ecx+12]) + AS2( mov [edx+4*ecx+12],esi) + + AS2( lea ecx,[ecx+4]) // advance index, avoid inc which causes slowdown on Intel Core 2 + ASJ( jmp, 0, b) + + ASL(2) + AS2( mov eax, 0) + AS1( setc al) // store carry into eax (return result register) + + AddEpilogue + + // http://github.com/weidai11/cryptopp/issues/340 + CRYPTOPP_UNUSED(A); CRYPTOPP_UNUSED(B); + CRYPTOPP_UNUSED(C); CRYPTOPP_UNUSED(N); +} + +#if CRYPTOPP_INTEGER_SSE2 +CRYPTOPP_NAKED int CRYPTOPP_FASTCALL SSE2_Add(size_t N, word *C, const word *A, const word *B) +{ + AddPrologue + + // now: eax = A, edi = B, edx = C, ecx = N + AS2( lea eax, [eax+4*ecx]) + AS2( lea edi, [edi+4*ecx]) + AS2( lea edx, [edx+4*ecx]) + + AS1( neg ecx) // ecx is negative index + AS2( pxor mm2, mm2) + ASJ( jz, 2, f) + AS2( test ecx, 2) // this clears carry flag + ASJ( jz, 0, f) + AS2( sub ecx, 2) + ASJ( jmp, 1, f) + + ASL(0) + AS2( movd mm0, DWORD PTR [eax+4*ecx]) + AS2( movd mm1, DWORD PTR [edi+4*ecx]) + AS2( paddq mm0, mm1) + AS2( paddq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx], mm2) + AS2( psrlq mm2, 32) + + AS2( movd mm0, DWORD PTR [eax+4*ecx+4]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+4]) + AS2( paddq mm0, mm1) + AS2( paddq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+4], mm2) + AS2( psrlq mm2, 32) + + ASL(1) + AS2( movd mm0, DWORD PTR [eax+4*ecx+8]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+8]) + AS2( paddq mm0, mm1) + AS2( paddq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+8], mm2) + AS2( psrlq mm2, 32) + + AS2( movd mm0, DWORD PTR [eax+4*ecx+12]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+12]) + AS2( paddq mm0, mm1) + AS2( paddq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+12], mm2) + AS2( psrlq mm2, 32) + + AS2( add ecx, 4) + ASJ( jnz, 0, b) + + ASL(2) + AS2( movd eax, mm2) + AS1( emms) + + AddEpilogue + + // http://github.com/weidai11/cryptopp/issues/340 + CRYPTOPP_UNUSED(A); CRYPTOPP_UNUSED(B); + CRYPTOPP_UNUSED(C); CRYPTOPP_UNUSED(N); +} +CRYPTOPP_NAKED int CRYPTOPP_FASTCALL SSE2_Sub(size_t N, word *C, const word *A, const word *B) +{ + AddPrologue + + // now: eax = A, edi = B, edx = C, ecx = N + AS2( lea eax, [eax+4*ecx]) + AS2( lea edi, [edi+4*ecx]) + AS2( lea edx, [edx+4*ecx]) + + AS1( neg ecx) // ecx is negative index + AS2( pxor mm2, mm2) + ASJ( jz, 2, f) + AS2( test ecx, 2) // this clears carry flag + ASJ( jz, 0, f) + AS2( sub ecx, 2) + ASJ( jmp, 1, f) + + ASL(0) + AS2( movd mm0, DWORD PTR [eax+4*ecx]) + AS2( movd mm1, DWORD PTR [edi+4*ecx]) + AS2( psubq mm0, mm1) + AS2( psubq mm0, mm2) + AS2( movd DWORD PTR [edx+4*ecx], mm0) + AS2( psrlq mm0, 63) + + AS2( movd mm2, DWORD PTR [eax+4*ecx+4]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+4]) + AS2( psubq mm2, mm1) + AS2( psubq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+4], mm2) + AS2( psrlq mm2, 63) + + ASL(1) + AS2( movd mm0, DWORD PTR [eax+4*ecx+8]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+8]) + AS2( psubq mm0, mm1) + AS2( psubq mm0, mm2) + AS2( movd DWORD PTR [edx+4*ecx+8], mm0) + AS2( psrlq mm0, 63) + + AS2( movd mm2, DWORD PTR [eax+4*ecx+12]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+12]) + AS2( psubq mm2, mm1) + AS2( psubq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+12], mm2) + AS2( psrlq mm2, 63) + + AS2( add ecx, 4) + ASJ( jnz, 0, b) + + ASL(2) + AS2( movd eax, mm2) + AS1( emms) + + AddEpilogue + + // http://github.com/weidai11/cryptopp/issues/340 + CRYPTOPP_UNUSED(A); CRYPTOPP_UNUSED(B); + CRYPTOPP_UNUSED(C); CRYPTOPP_UNUSED(N); +} +#endif // CRYPTOPP_INTEGER_SSE2 +#else // CRYPTOPP_SSE2_ASM_AVAILABLE +int CRYPTOPP_FASTCALL Baseline_Add(size_t N, word *C, const word *A, const word *B) +{ + CRYPTOPP_ASSERT (N%2 == 0); + + Declare2Words(u); + AssignWord(u, 0); + for (size_t i=0; i=2 && N%2==0); + + if (N <= s_recursionLimit) + s_pMul[N/4](R, A, B); + else + { + const size_t N2 = N/2; + + size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2; + Subtract(R0, A + AN2, A + (N2 ^ AN2), N2); + + size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2; + Subtract(R1, B + BN2, B + (N2 ^ BN2), N2); + + RecursiveMultiply(R2, T2, A1, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + RecursiveMultiply(R0, T2, A0, B0, N2); + + // now T[01] holds (A1-A0)*(B0-B1), R[01] holds A0*B0, R[23] holds A1*B1 + + int c2 = Add(R2, R2, R1, N2); + int c3 = c2; + c2 += Add(R1, R2, R0, N2); + c3 += Add(R2, R2, R3, N2); + + if (AN2 == BN2) + c3 -= Subtract(R1, R1, T0, N); + else + c3 += Add(R1, R1, T0, N); + + c3 += Increment(R2, N2, c2); + CRYPTOPP_ASSERT (c3 >= 0 && c3 <= 2); + Increment(R3, N2, c3); + } +} + +// R[2*N] - result = A*A +// T[2*N] - temporary work space +// A[N] --- number to be squared + +void RecursiveSquare(word *R, word *T, const word *A, size_t N) +{ + CRYPTOPP_ASSERT(N && N%2==0); + + if (N <= s_recursionLimit) + s_pSqu[N/4](R, A); + else + { + const size_t N2 = N/2; + + RecursiveSquare(R0, T2, A0, N2); + RecursiveSquare(R2, T2, A1, N2); + RecursiveMultiply(T0, T2, A0, A1, N2); + + int carry = Add(R1, R1, T0, N); + carry += Add(R1, R1, T0, N); + Increment(R3, N2, carry); + } +} + +// R[N] - bottom half of A*B +// T[3*N/2] - temporary work space +// A[N] - multiplier +// B[N] - multiplicant + +void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B, size_t N) +{ + CRYPTOPP_ASSERT(N>=2 && N%2==0); + + if (N <= s_recursionLimit) + s_pBot[N/4](R, A, B); + else + { + const size_t N2 = N/2; + + RecursiveMultiply(R, T, A0, B0, N2); + RecursiveMultiplyBottom(T0, T1, A1, B0, N2); + Add(R1, R1, T0, N2); + RecursiveMultiplyBottom(T0, T1, A0, B1, N2); + Add(R1, R1, T0, N2); + } +} + +// R[N] --- upper half of A*B +// T[2*N] - temporary work space +// L[N] --- lower half of A*B +// A[N] --- multiplier +// B[N] --- multiplicant + +void MultiplyTop(word *R, word *T, const word *L, const word *A, const word *B, size_t N) +{ + CRYPTOPP_ASSERT(N>=2 && N%2==0); + + if (N <= s_recursionLimit) + s_pTop[N/4](R, A, B, L[N-1]); + else + { + const size_t N2 = N/2; + + size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2; + Subtract(R0, A + AN2, A + (N2 ^ AN2), N2); + + size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2; + Subtract(R1, B + BN2, B + (N2 ^ BN2), N2); + + RecursiveMultiply(T0, T2, R0, R1, N2); + RecursiveMultiply(R0, T2, A1, B1, N2); + + // now T[01] holds (A1-A0)*(B0-B1) = A1*B0+A0*B1-A1*B1-A0*B0, R[01] holds A1*B1 + + int t, c3; + int c2 = Subtract(T2, L+N2, L, N2); + + if (AN2 == BN2) + { + c2 -= Add(T2, T2, T0, N2); + t = (Compare(T2, R0, N2) == -1); + c3 = t - Subtract(T2, T2, T1, N2); + } + else + { + c2 += Subtract(T2, T2, T0, N2); + t = (Compare(T2, R0, N2) == -1); + c3 = t + Add(T2, T2, T1, N2); + } + + c2 += t; + if (c2 >= 0) + c3 += Increment(T2, N2, c2); + else + c3 -= Decrement(T2, N2, -c2); + c3 += Add(R0, T2, R1, N2); + + CRYPTOPP_ASSERT (c3 >= 0 && c3 <= 2); + Increment(R1, N2, c3); + } +} + +inline void Multiply(word *R, word *T, const word *A, const word *B, size_t N) +{ + RecursiveMultiply(R, T, A, B, N); +} + +inline void Square(word *R, word *T, const word *A, size_t N) +{ + RecursiveSquare(R, T, A, N); +} + +inline void MultiplyBottom(word *R, word *T, const word *A, const word *B, size_t N) +{ + RecursiveMultiplyBottom(R, T, A, B, N); +} + +// R[NA+NB] - result = A*B +// T[NA+NB] - temporary work space +// A[NA] ---- multiplier +// B[NB] ---- multiplicant + +void AsymmetricMultiply(word *R, word *T, const word *A, size_t NA, const word *B, size_t NB) +{ + if (NA == NB) + { + // Profiling guided the flow below. + if (A != B) + Multiply(R, T, A, B, NA); + else + Square(R, T, A, NA); + + return; + } + + if (NA > NB) + { + std::swap(A, B); + std::swap(NA, NB); + } + + CRYPTOPP_ASSERT(NB % NA == 0); + + if (NA==2 && !A[1]) + { + // Profiling guided the flow below. + switch (A[0]) + { + default: + R[NB] = LinearMultiply(R, B, A[0], NB); + R[NB+1] = 0; + return; + case 0: + SetWords(R, 0, NB+2); + return; + case 1: + CopyWords(R, B, NB); + R[NB] = R[NB+1] = 0; + return; + } + } + + size_t i; + if ((NB/NA)%2 == 0) + { + Multiply(R, T, A, B, NA); + CopyWords(T+2*NA, R+NA, NA); + + for (i=2*NA; i=4); + +#define M0 M +#define M1 (M+N2) +#define V0 V +#define V1 (V+N2) + +#define X0 X +#define X1 (X+N2) +#define X2 (X+N) +#define X3 (X+N+N2) + + const size_t N2 = N/2; + Multiply(T0, T2, V0, X3, N2); + int c2 = Add(T0, T0, X0, N); + MultiplyBottom(T3, T2, T0, U, N2); + MultiplyTop(T2, R, T0, T3, M0, N2); + c2 -= Subtract(T2, T1, T2, N2); + Multiply(T0, R, T3, M1, N2); + c2 -= Subtract(T0, T2, T0, N2); + int c3 = -(int)Subtract(T1, X2, T1, N2); + Multiply(R0, T2, V1, X3, N2); + c3 += Add(R, R, T, N); + + if (c2>0) + c3 += Increment(R1, N2); + else if (c2<0) + c3 -= Decrement(R1, N2, -c2); + + CRYPTOPP_ASSERT(c3>=-1 && c3<=1); + if (c3>0) + Subtract(R, R, M, N); + else if (c3<0) + Add(R, R, M, N); + +#undef M0 +#undef M1 +#undef V0 +#undef V1 + +#undef X0 +#undef X1 +#undef X2 +#undef X3 +} + +#undef A0 +#undef A1 +#undef B0 +#undef B1 + +#undef T0 +#undef T1 +#undef T2 +#undef T3 + +#undef R0 +#undef R1 +#undef R2 +#undef R3 + +/* +// do a 3 word by 2 word divide, returns quotient and leaves remainder in A +static word SubatomicDivide(word *A, word B0, word B1) +{ + // Assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a word + CRYPTOPP_ASSERT(A[2] < B1 || (A[2]==B1 && A[1] < B0)); + + // estimate the quotient: do a 2 word by 1 word divide + word Q; + if (B1+1 == 0) + Q = A[2]; + else + Q = DWord(A[1], A[2]).DividedBy(B1+1); + + // now subtract Q*B from A + DWord p = DWord::Multiply(B0, Q); + DWord u = (DWord) A[0] - p.GetLowHalf(); + A[0] = u.GetLowHalf(); + u = (DWord) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - DWord::Multiply(B1, Q); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + + // Q <= actual quotient, so fix it + while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) + { + u = (DWord) A[0] - B0; + A[0] = u.GetLowHalf(); + u = (DWord) A[1] - B1 - u.GetHighHalfAsBorrow(); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + Q++; + CRYPTOPP_ASSERT(Q); // shouldn't overflow + } + + return Q; +} + +// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1 +static inline void AtomicDivide(word *Q, const word *A, const word *B) +{ + if (!B[0] && !B[1]) // if divisor is 0, we assume divisor==2**(2*WORD_BITS) + { + Q[0] = A[2]; + Q[1] = A[3]; + } + else + { + word T[4]; + T[0] = A[0]; T[1] = A[1]; T[2] = A[2]; T[3] = A[3]; + Q[1] = SubatomicDivide(T+1, B[0], B[1]); + Q[0] = SubatomicDivide(T, B[0], B[1]); + +#if defined(CRYPTOPP_DEBUG) + // multiply quotient and divisor and add remainder, make sure it equals dividend + CRYPTOPP_ASSERT(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0](T, DWord(A[0], A[1]), DWord(A[2], A[3]), DWord(B[0], B[1])); + Q[0] = q.GetLowHalf(); + Q[1] = q.GetHighHalf(); + +#if defined(CRYPTOPP_DEBUG) + if (B[0] || B[1]) + { + // multiply quotient and divisor and add remainder, make sure it equals dividend + CRYPTOPP_ASSERT(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]= 0) + { + R[N] -= Subtract(R, R, B, N); + Q[1] += (++Q[0]==0); + CRYPTOPP_ASSERT(Q[0] || Q[1]); // no overflow + } +} + +// R[NB] -------- remainder = A%B +// Q[NA-NB+2] --- quotient = A/B +// T[NA+3*(NB+2)] - temp work space +// A[NA] -------- dividend +// B[NB] -------- divisor + +void Divide(word *R, word *Q, word *T, const word *A, size_t NA, const word *B, size_t NB) +{ + CRYPTOPP_ASSERT(NA && NB && NA%2==0 && NB%2==0); + CRYPTOPP_ASSERT(B[NB-1] || B[NB-2]); + CRYPTOPP_ASSERT(NB <= NA); + + // set up temporary work space + word *const TA=T; + word *const TB=T+NA+2; + word *const TP=T+NA+2+NB; + + // copy B into TB and normalize it so that TB has highest bit set to 1 + unsigned shiftWords = (B[NB-1]==0); + TB[0] = TB[NB-1] = 0; + CopyWords(TB+shiftWords, B, NB-shiftWords); + unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]); + CRYPTOPP_ASSERT(shiftBits < WORD_BITS); + ShiftWordsLeftByBits(TB, NB, shiftBits); + + // copy A into TA and normalize it + TA[0] = TA[NA] = TA[NA+1] = 0; + CopyWords(TA+shiftWords, A, NA); + ShiftWordsLeftByBits(TA, NA+2, shiftBits); + + if (TA[NA+1]==0 && TA[NA] <= 1) + { + Q[NA-NB+1] = Q[NA-NB] = 0; + while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0) + { + TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB); + ++Q[NA-NB]; + } + } + else + { + NA+=2; + CRYPTOPP_ASSERT(Compare(TA+NA-NB, TB, NB) < 0); + } + + word BT[2]; + BT[0] = TB[NB-2] + 1; + BT[1] = TB[NB-1] + (BT[0]==0); + + // start reducing TA mod TB, 2 words at a time + for (size_t i=NA-2; i>=NB; i-=2) + { + AtomicDivide(Q+i-NB, TA+i-2, BT); + CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB); + } + + // copy TA into R, and denormalize it + CopyWords(R, TA+shiftWords, NB); + ShiftWordsRightByBits(R, NB, shiftBits); +} + +static inline size_t EvenWordCount(const word *X, size_t N) +{ + while (N && X[N-2]==0 && X[N-1]==0) + N-=2; + return N; +} + +// return k +// R[N] --- result = A^(-1) * 2^k mod M +// T[4*N] - temporary work space +// A[NA] -- number to take inverse of +// M[N] --- modulus + +unsigned int AlmostInverse(word *R, word *T, const word *A, size_t NA, const word *M, size_t N) +{ + CRYPTOPP_ASSERT(NA<=N && N && N%2==0); + + word *b = T; + word *c = T+N; + word *f = T+2*N; + word *g = T+3*N; + size_t bcLen=2, fgLen=EvenWordCount(M, N); + unsigned int k=0; + bool s=false; + + SetWords(T, 0, 3*N); + b[0]=1; + CopyWords(f, A, NA); + CopyWords(g, M, N); + + while (1) + { + word t=f[0]; + while (!t) + { + if (EvenWordCount(f, fgLen)==0) + { + SetWords(R, 0, N); + return 0; + } + + ShiftWordsRightByWords(f, fgLen, 1); + bcLen += 2 * (c[bcLen-1] != 0); + CRYPTOPP_ASSERT(bcLen <= N); + ShiftWordsLeftByWords(c, bcLen, 1); + k+=WORD_BITS; + t=f[0]; + } + + // t must be non-0; otherwise undefined. + unsigned int i = TrailingZeros(t); + t >>= i; + k += i; + + if (t==1 && f[1]==0 && EvenWordCount(f+2, fgLen-2)==0) + { + if (s) + Subtract(R, M, b, N); + else + CopyWords(R, b, N); + return k; + } + + ShiftWordsRightByBits(f, fgLen, i); + t = ShiftWordsLeftByBits(c, bcLen, i); + c[bcLen] += t; + bcLen += 2 * (t!=0); + CRYPTOPP_ASSERT(bcLen <= N); + + bool swap = Compare(f, g, fgLen)==-1; + ConditionalSwapPointers(swap, f, g); + ConditionalSwapPointers(swap, b, c); + s ^= swap; + + fgLen -= 2 * !(f[fgLen-2] | f[fgLen-1]); + + Subtract(f, f, g, fgLen); + t = Add(b, b, c, bcLen); + b[bcLen] += t; + bcLen += 2*t; + CRYPTOPP_ASSERT(bcLen <= N); + } +} + +// R[N] - result = A/(2^k) mod M +// A[N] - input +// M[N] - modulus + +void DivideByPower2Mod(word *R, const word *A, size_t k, const word *M, size_t N) +{ + CopyWords(R, A, N); + + while (k--) + { + if (R[0]%2==0) + ShiftWordsRightByBits(R, N, 1); + else + { + word carry = Add(R, R, M, N); + ShiftWordsRightByBits(R, N, 1); + R[N-1] += carry<<(WORD_BITS-1); + } + } +} + +// R[N] - result = A*(2^k) mod M +// A[N] - input +// M[N] - modulus + +void MultiplyByPower2Mod(word *R, const word *A, size_t k, const word *M, size_t N) +{ + CopyWords(R, A, N); + + while (k--) + if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0) + Subtract(R, R, M, N); +} + +// ****************************************************************** + +static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8}; + +static inline size_t RoundupSize(size_t n) +{ + if (n<=8) + return RoundupSizeTable[n]; + else if (n<=16) + return 16; + else if (n<=32) + return 32; + else if (n<=64) + return 64; + else + return size_t(1) << BitPrecision(n-1); +} + +Integer::Integer() + : reg(2), sign(POSITIVE) +{ + reg[0] = reg[1] = 0; +} + +Integer::Integer(const Integer& t) + : reg(RoundupSize(t.WordCount())), sign(t.sign) +{ + CopyWords(reg, t.reg, reg.size()); +} + +Integer::Integer(Sign s, lword value) + : reg(2), sign(s) +{ + reg[0] = word(value); + reg[1] = word(SafeRightShift(value)); +} + +Integer::Integer(signed long value) + : reg(2) +{ + if (value >= 0) + sign = POSITIVE; + else + { + sign = NEGATIVE; + value = -value; + } + reg[0] = word(value); + reg[1] = word(SafeRightShift((unsigned long)value)); +} + +Integer::Integer(Sign s, word high, word low) + : reg(2), sign(s) +{ + reg[0] = low; + reg[1] = high; +} + +bool Integer::IsConvertableToLong() const +{ + if (ByteCount() > sizeof(long)) + return false; + + unsigned long value = (unsigned long)reg[0]; + value += SafeLeftShift((unsigned long)reg[1]); + + if (sign==POSITIVE) + return (signed long)value >= 0; + else + return -(signed long)value < 0; +} + +signed long Integer::ConvertToLong() const +{ + CRYPTOPP_ASSERT(IsConvertableToLong()); + + unsigned long value = (unsigned long)reg[0]; + value += SafeLeftShift((unsigned long)reg[1]); + return sign==POSITIVE ? value : -(signed long)value; +} + +Integer::Integer(BufferedTransformation &encodedInteger, size_t byteCount, Signedness s, ByteOrder o) +{ + CRYPTOPP_ASSERT(o == BIG_ENDIAN_ORDER || o == LITTLE_ENDIAN_ORDER); + + if (o != LITTLE_ENDIAN_ORDER) + { + Decode(encodedInteger, byteCount, s); + } + else + { + SecByteBlock block(byteCount); + encodedInteger.Get(block, block.size()); + std::reverse(block.begin(), block.begin()+block.size()); + + Decode(block.begin(), block.size(), s); + } +} + +Integer::Integer(const byte *encodedInteger, size_t byteCount, Signedness s, ByteOrder o) +{ + CRYPTOPP_ASSERT(encodedInteger && byteCount); // NULL buffer + CRYPTOPP_ASSERT(o == BIG_ENDIAN_ORDER || o == LITTLE_ENDIAN_ORDER); + + if (o != LITTLE_ENDIAN_ORDER) + { + Decode(encodedInteger, byteCount, s); + } + else + { + SecByteBlock block(byteCount); +#if (_MSC_VER >= 1500) + std::reverse_copy(encodedInteger, encodedInteger+byteCount, + stdext::make_checked_array_iterator(block.begin(), block.size())); +#else + std::reverse_copy(encodedInteger, encodedInteger+byteCount, block.begin()); +#endif + Decode(block.begin(), block.size(), s); + return; + } +} + +Integer::Integer(BufferedTransformation &bt) +{ + // Make explicit call to avoid virtual-dispatch findings in ctor + Integer::BERDecode(bt); +} + +Integer::Integer(RandomNumberGenerator &rng, size_t bitcount) +{ + Randomize(rng, bitcount); +} + +Integer::Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod) +{ + if (!Randomize(rng, min, max, rnType, equiv, mod)) + throw Integer::RandomNumberNotFound(); +} + +Integer Integer::Power2(size_t e) +{ + Integer r((word)0, BitsToWords(e+1)); + r.SetBit(e); + return r; +} + +bool Integer::operator!() const +{ + return IsNegative() ? false : (reg[0]==0 && WordCount()==0); +} + +Integer& Integer::operator=(const Integer& t) +{ + if (this != &t) + { + if (reg.size() != t.reg.size() || t.reg[t.reg.size()/2] == 0) + reg.New(RoundupSize(t.WordCount())); + CopyWords(reg, t.reg, reg.size()); + sign = t.sign; + } + return *this; +} + +bool Integer::GetBit(size_t n) const +{ + // Profiling guided the flow below. + if (n/WORD_BITS < reg.size()) + return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1); + else + return 0; +} + +void Integer::SetBit(size_t n, bool value) +{ + if (value) + { + reg.CleanGrow(RoundupSize(BitsToWords(n+1))); + reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS)); + } + else + { + if (n/WORD_BITS < reg.size()) + reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS)); + } +} + +byte Integer::GetByte(size_t n) const +{ + // Profiling guided the flow below. + if (n/WORD_SIZE < reg.size()) + return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); + else + return 0; +} + +void Integer::SetByte(size_t n, byte value) +{ + reg.CleanGrow(RoundupSize(BytesToWords(n+1))); + reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE)); + reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE)); +} + +lword Integer::GetBits(size_t i, size_t n) const +{ + lword v = 0; + CRYPTOPP_ASSERT(n <= sizeof(v)*8); + for (unsigned int j=0; j +static Integer StringToInteger(const T *str, ByteOrder order) +{ + CRYPTOPP_ASSERT( order == BIG_ENDIAN_ORDER || order == LITTLE_ENDIAN_ORDER ); + + int radix, sign = 1; + // GCC workaround + // std::char_traits::length() not defined in GCC 3.2 and STLport 4.5.3 + unsigned int length; + for (length = 0; str[length] != 0; length++) {} + + Integer v; + + if (length == 0) + return Integer::Zero(); + + // 'str' is of length 1 or more + switch (str[length-1]) + { + case 'h': + case 'H': + radix=16; + break; + case 'o': + case 'O': + radix=8; + break; + case 'b': + case 'B': + radix=2; + break; + default: + radix=10; + } + + // 'str' is of length 1 or more + if (str[0] == '-') + { + sign = -1; + str += 1, length -= 1; + } + + // Recognize common prefixes for hexadecimal, octal and decimal. + // Microsoft's MASM also recognizes 0t for octal, but not here. + if (length > 2 && str[0] == '0') + { + if (str[1] == 'x' || str[1] == 'X') + { + radix = 16; + str += 2, length -= 2; + } + else if (str[1] == 'n' || str[1] == 'N') + { + radix = 10; + str += 2, length -= 2; + } + else if (str[1] == 'o' || str[1] == 'O') + { + radix = 8; + str += 2, length -= 2; + } + } + + if (order == BIG_ENDIAN_ORDER) + { + for (unsigned int i=0; i(str[i]); + + // Profiling guided the flow below. + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else + digit = radix; + + if (digit < radix) + { + v *= radix; + v += digit; + } + } + } + else if (radix == 16 && order == LITTLE_ENDIAN_ORDER) + { + // Nibble high, low and count + unsigned int nh = 0, nl = 0, nc = 0; + Integer position(Integer::One()); + + for (unsigned int i=0; i(str[i]); + + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else + digit = radix; + + if (digit < radix) + { + if (nc++ == 0) + nh = digit; + else + nl = digit; + + if (nc == 2) + { + v += position * (nh << 4 | nl); + nc = 0, position <<= 8; + } + } + } + + if (nc == 1) + v += nh * position; + } + else // LITTLE_ENDIAN_ORDER && radix != 16 + { + for (int i=static_cast(length)-1; i>=0; i--) + { + int digit, ch = static_cast(str[i]); + + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else + digit = radix; + + if (digit < radix) + { + v *= radix; + v += digit; + } + } + } + + if (sign == -1) + v.Negate(); + + return v; +} + +Integer::Integer(const char *str, ByteOrder order) + : reg(2), sign(POSITIVE) +{ + *this = StringToInteger(str,order); +} + +Integer::Integer(const wchar_t *str, ByteOrder order) + : reg(2), sign(POSITIVE) +{ + *this = StringToInteger(str,order); +} + +unsigned int Integer::WordCount() const +{ + return (unsigned int)CountWords(reg, reg.size()); +} + +unsigned int Integer::ByteCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]); + else + return 0; +} + +unsigned int Integer::BitCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]); + else + return 0; +} + +void Integer::Decode(const byte *input, size_t inputLen, Signedness s) +{ + CRYPTOPP_ASSERT(input && inputLen); // NULL buffer + StringStore store(input, inputLen); + Decode(store, inputLen, s); +} + +void Integer::Decode(BufferedTransformation &bt, size_t inputLen, Signedness s) +{ + CRYPTOPP_ASSERT(bt.MaxRetrievable() >= inputLen); + if (bt.MaxRetrievable() < inputLen) + throw InvalidArgument("Integer: input length is too small"); + + byte b; + bt.Peek(b); + sign = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE; + + while (inputLen>0 && (sign==POSITIVE ? b==0 : b==0xff)) + { + bt.Skip(1); + inputLen--; + bt.Peek(b); + } + + reg.CleanNew(RoundupSize(BytesToWords(inputLen))); + for (size_t i=inputLen; i > 0; i--) + { + (void)bt.Get(b); + reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8; + } + + if (sign == NEGATIVE) + { + for (size_t i=inputLen; i 0; i--) + bt.Put(GetByte(i-1)); + } + else + { + // take two's complement of *this + Integer temp = Integer::Power2(8*STDMAX((size_t)ByteCount(), outputLen)) + *this; + temp.Encode(bt, outputLen, UNSIGNED); + } +} + +void Integer::DEREncode(BufferedTransformation &bt) const +{ + DERGeneralEncoder enc(bt, INTEGER); + Encode(enc, MinEncodedSize(SIGNED), SIGNED); + enc.MessageEnd(); +} + +void Integer::BERDecode(const byte *input, size_t len) +{ + CRYPTOPP_ASSERT(input && len); // NULL buffer + StringStore store(input, len); + BERDecode(store); +} + +void Integer::BERDecode(BufferedTransformation &bt) +{ + BERGeneralDecoder dec(bt, INTEGER); + if (!dec.IsDefiniteLength() || dec.MaxRetrievable() < dec.RemainingLength()) + BERDecodeError(); + Decode(dec, (size_t)dec.RemainingLength(), SIGNED); + dec.MessageEnd(); +} + +void Integer::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const +{ + DERGeneralEncoder enc(bt, OCTET_STRING); + Encode(enc, length); + enc.MessageEnd(); +} + +void Integer::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length) +{ + BERGeneralDecoder dec(bt, OCTET_STRING); + if (!dec.IsDefiniteLength() || dec.RemainingLength() != length) + BERDecodeError(); + Decode(dec, length); + dec.MessageEnd(); +} + +size_t Integer::OpenPGPEncode(byte *output, size_t bufferSize) const +{ + CRYPTOPP_ASSERT(output && bufferSize); // NULL buffer + CRYPTOPP_ASSERT(bufferSize >= 2+ByteCount()); // Undersized buffer + ArraySink sink(output, bufferSize); + return OpenPGPEncode(sink); +} + +size_t Integer::OpenPGPEncode(BufferedTransformation &bt) const +{ + word16 bitCount = word16(BitCount()); + bt.PutWord16(bitCount); + size_t byteCount = BitsToBytes(bitCount); + Encode(bt, byteCount); + return 2 + byteCount; +} + +void Integer::OpenPGPDecode(const byte *input, size_t len) +{ + CRYPTOPP_ASSERT(input && len); // NULL buffer + StringStore store(input, len); + OpenPGPDecode(store); +} + +void Integer::OpenPGPDecode(BufferedTransformation &bt) +{ + word16 bitCount; + if (bt.GetWord16(bitCount) != 2 || bt.MaxRetrievable() < BitsToBytes(bitCount)) + throw OpenPGPDecodeErr(); + Decode(bt, BitsToBytes(bitCount)); +} + +void Integer::Randomize(RandomNumberGenerator &rng, size_t nbits) +{ + const size_t nbytes = nbits/8 + 1; + SecByteBlock buf(nbytes); + rng.GenerateBlock(buf, nbytes); + if (nbytes) + buf[0] = (byte)Crop(buf[0], nbits % 8); + Decode(buf, nbytes, UNSIGNED); +} + +void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max) +{ + if (min > max) + throw InvalidArgument("Integer: Min must be no greater than Max"); + + Integer range = max - min; + const unsigned int nbits = range.BitCount(); + + do + { + Randomize(rng, nbits); + } + while (*this > range); + + *this += min; +} + +bool Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod) +{ + return GenerateRandomNoThrow(rng, MakeParameters("Min", min)("Max", max) + ("RandomNumberType", rnType)("EquivalentTo", equiv)("Mod", mod)); +} + +class KDF2_RNG : public RandomNumberGenerator +{ +public: + KDF2_RNG(const byte *seed, size_t seedSize) + : m_counter(0), m_counterAndSeed(ClampSize(seedSize) + 4) + { + memcpy(m_counterAndSeed + 4, seed, ClampSize(seedSize)); + } + + void GenerateBlock(byte *output, size_t size) + { + CRYPTOPP_ASSERT(output && size); // NULL buffer + PutWord(false, BIG_ENDIAN_ORDER, m_counterAndSeed, m_counter); + ++m_counter; + P1363_KDF2::DeriveKey(output, size, m_counterAndSeed, m_counterAndSeed.size(), NULLPTR, 0); + } + + // UBsan finding, -Wstringop-overflow + inline size_t ClampSize(size_t req) const + { + // Clamp at 16 MB + if (req > 16U*1024*1024) + return 16U*1024*1024; + return req; + } + +private: + word32 m_counter; + SecByteBlock m_counterAndSeed; +}; + +bool Integer::GenerateRandomNoThrow(RandomNumberGenerator &i_rng, const NameValuePairs ¶ms) +{ + Integer min = params.GetValueWithDefault("Min", Integer::Zero()); + Integer max; + if (!params.GetValue("Max", max)) + { + int bitLength; + if (params.GetIntValue("BitLength", bitLength)) + max = Integer::Power2(bitLength); + else + throw InvalidArgument("Integer: missing Max argument"); + } + if (min > max) + throw InvalidArgument("Integer: Min must be no greater than Max"); + + Integer equiv = params.GetValueWithDefault("EquivalentTo", Integer::Zero()); + Integer mod = params.GetValueWithDefault("Mod", Integer::One()); + + if (equiv.IsNegative() || equiv >= mod) + throw InvalidArgument("Integer: invalid EquivalentTo and/or Mod argument"); + + Integer::RandomNumberType rnType = params.GetValueWithDefault("RandomNumberType", Integer::ANY); + + member_ptr kdf2Rng; + ConstByteArrayParameter seed; + if (params.GetValue(Name::Seed(), seed)) + { + ByteQueue bq; + DERSequenceEncoder seq(bq); + min.DEREncode(seq); + max.DEREncode(seq); + equiv.DEREncode(seq); + mod.DEREncode(seq); + DEREncodeUnsigned(seq, rnType); + DEREncodeOctetString(seq, seed.begin(), seed.size()); + seq.MessageEnd(); + + SecByteBlock finalSeed((size_t)bq.MaxRetrievable()); + bq.Get(finalSeed, finalSeed.size()); + kdf2Rng.reset(new KDF2_RNG(finalSeed.begin(), finalSeed.size())); + } + RandomNumberGenerator &rng = kdf2Rng.get() ? (RandomNumberGenerator &)*kdf2Rng : i_rng; + + switch (rnType) + { + case ANY: + if (mod == One()) + Randomize(rng, min, max); + else + { + Integer min1 = min + (equiv-min)%mod; + if (max < min1) + return false; + Randomize(rng, Zero(), (max - min1) / mod); + *this *= mod; + *this += min1; + } + return true; + + case PRIME: + { + const PrimeSelector *pSelector = params.GetValueWithDefault(Name::PointerToPrimeSelector(), (const PrimeSelector *)NULLPTR); + + int i; + i = 0; + while (1) + { + if (++i==16) + { + // check if there are any suitable primes in [min, max] + Integer first = min; + if (FirstPrime(first, max, equiv, mod, pSelector)) + { + // if there is only one suitable prime, we're done + *this = first; + if (!FirstPrime(first, max, equiv, mod, pSelector)) + return true; + } + else + return false; + } + + Randomize(rng, min, max); + if (FirstPrime(*this, STDMIN(*this+mod*PrimeSearchInterval(max), max), equiv, mod, pSelector)) + return true; + } + } + + default: + throw InvalidArgument("Integer: invalid RandomNumberType argument"); + } +} + +std::istream& operator>>(std::istream& in, Integer &a) +{ + char c; + unsigned int length = 0; + SecBlock str(length + 16); + + std::ws(in); + + do + { + in.read(&c, 1); + str[length++] = c; + if (length >= str.size()) + str.Grow(length + 16); + } + while (in && (c=='-' || c=='x' || (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F') || c=='h' || c=='H' || c=='o' || c=='O' || c==',' || c=='.')); + + if (in.gcount()) + in.putback(c); + str[length-1] = '\0'; + a = Integer(str); + + return in; +} + +// Ensure base 10 is default +inline int FlagToBase(long f) { + return f == std::ios::hex ? 16 : (f == std::ios::oct ? 8 : 10); +} + +inline char FlagToSuffix(long f) { + return f == std::ios::hex ? 'h' : (f == std::ios::oct ? 'o' : '.'); +} + +// Ensure base 10 is default +std::ostream& operator<<(std::ostream& out, const Integer &a) +{ + // Get relevant conversion specifications from ostream. + const long f = out.flags() & std::ios::basefield; + const int base = FlagToBase(f); + const char suffix = FlagToSuffix(f); + + Integer temp1=a, temp2; + if (a.IsNegative()) + { + out << '-'; + temp1.Negate(); + } + + if (!a) + out << '0'; + + static const char upper[]="0123456789ABCDEF"; + static const char lower[]="0123456789abcdef"; + + const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower; + unsigned int i=0; + SecBlock s(a.BitCount() / (SaturatingSubtract1(BitPrecision(base),1U)) + 1); + + while (!!temp1) + { + word digit; + Integer::Divide(digit, temp2, temp1, base); + s[i++]=vec[digit]; + temp1.swap(temp2); + } + + while (i--) + { + out << s[i]; + } + +#ifdef CRYPTOPP_USE_STD_SHOWBASE + if (out.flags() & std::ios_base::showbase) + out << suffix; + + return out; +#else + return out << suffix; +#endif +} + +Integer& Integer::operator++() +{ + if (NotNegative()) + { + if (Increment(reg, reg.size())) + { + reg.CleanGrow(2*reg.size()); + reg[reg.size()/2]=1; + } + } + else + { + word borrow = Decrement(reg, reg.size()); + CRYPTOPP_ASSERT(!borrow); CRYPTOPP_UNUSED(borrow); + + if (WordCount()==0) + *this = Zero(); + } + return *this; +} + +Integer& Integer::operator--() +{ + if (IsNegative()) + { + if (Increment(reg, reg.size())) + { + reg.CleanGrow(2*reg.size()); + reg[reg.size()/2]=1; + } + } + else + { + if (Decrement(reg, reg.size())) + *this = -One(); + } + return *this; +} + +// This is a bit operation. We set sign to POSITIVE, so there's no need to +// worry about negative zero. Also see http://stackoverflow.com/q/11644362. +Integer Integer::And(const Integer& t) const +{ + if (this == &t) + { + return AbsoluteValue(); + } + else if (reg.size() >= t.reg.size()) + { + Integer result(t); + AndWords(result.reg, reg, t.reg.size()); + + result.sign = POSITIVE; + return result; + } + else // reg.size() < t.reg.size() + { + Integer result(*this); + AndWords(result.reg, t.reg, reg.size()); + + result.sign = POSITIVE; + return result; + } +} + +// This is a bit operation. We set sign to POSITIVE, so there's no need to +// worry about negative zero. Also see http://stackoverflow.com/q/11644362. +Integer Integer::Or(const Integer& t) const +{ + if (this == &t) + { + return AbsoluteValue(); + } + else if (reg.size() >= t.reg.size()) + { + Integer result(*this); + OrWords(result.reg, t.reg, t.reg.size()); + + result.sign = POSITIVE; + return result; + } + else // reg.size() < t.reg.size() + { + Integer result(t); + OrWords(result.reg, reg, reg.size()); + + result.sign = POSITIVE; + return result; + } +} + +// This is a bit operation. We set sign to POSITIVE, so there's no need to +// worry about negative zero. Also see http://stackoverflow.com/q/11644362. +Integer Integer::Xor(const Integer& t) const +{ + if (this == &t) + { + return Integer::Zero(); + } + else if (reg.size() >= t.reg.size()) + { + Integer result(*this); + XorWords(result.reg, t.reg, t.reg.size()); + + result.sign = POSITIVE; + return result; + } + else // reg.size() < t.reg.size() + { + Integer result(t); + XorWords(result.reg, reg, reg.size()); + + result.sign = POSITIVE; + return result; + } +} + +void PositiveAdd(Integer &sum, const Integer &a, const Integer& b) +{ + // Profiling guided the flow below. + int carry; const bool pre = (a.reg.size() == b.reg.size()); + if (!pre && a.reg.size() > b.reg.size()) + { + carry = Add(sum.reg, a.reg, b.reg, b.reg.size()); + CopyWords(sum.reg+b.reg.size(), a.reg+b.reg.size(), a.reg.size()-b.reg.size()); + carry = Increment(sum.reg+b.reg.size(), a.reg.size()-b.reg.size(), carry); + } + else if (pre) + { + carry = Add(sum.reg, a.reg, b.reg, a.reg.size()); + } + else + { + carry = Add(sum.reg, a.reg, b.reg, a.reg.size()); + CopyWords(sum.reg+a.reg.size(), b.reg+a.reg.size(), b.reg.size()-a.reg.size()); + carry = Increment(sum.reg+a.reg.size(), b.reg.size()-a.reg.size(), carry); + } + + if (carry) + { + sum.reg.CleanGrow(2*sum.reg.size()); + sum.reg[sum.reg.size()/2] = 1; + } + sum.sign = Integer::POSITIVE; +} + +void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b) +{ + unsigned aSize = a.WordCount(); + aSize += aSize%2; + unsigned bSize = b.WordCount(); + bSize += bSize%2; + + // Profiling guided the flow below. + if (aSize > bSize) + { + word borrow = Subtract(diff.reg, a.reg, b.reg, bSize); + CopyWords(diff.reg+bSize, a.reg+bSize, aSize-bSize); + borrow = Decrement(diff.reg+bSize, aSize-bSize, borrow); + CRYPTOPP_ASSERT(!borrow); CRYPTOPP_UNUSED(borrow); + diff.sign = Integer::POSITIVE; + } + else if (aSize == bSize) + { + if (Compare(a.reg, b.reg, aSize) >= 0) + { + Subtract(diff.reg, a.reg, b.reg, aSize); + diff.sign = Integer::POSITIVE; + } + else + { + Subtract(diff.reg, b.reg, a.reg, aSize); + diff.sign = Integer::NEGATIVE; + } + } + else + { + word borrow = Subtract(diff.reg, b.reg, a.reg, aSize); + CopyWords(diff.reg+aSize, b.reg+aSize, bSize-aSize); + borrow = Decrement(diff.reg+aSize, bSize-aSize, borrow); + CRYPTOPP_ASSERT(!borrow); CRYPTOPP_UNUSED(borrow); + diff.sign = Integer::NEGATIVE; + } +} + +// MSVC .NET 2003 workaround +template inline const T& STDMAX2(const T& a, const T& b) +{ + return a < b ? b : a; +} + +Integer Integer::Plus(const Integer& b) const +{ + Integer sum((word)0, STDMAX2(reg.size(), b.reg.size())); + if (NotNegative()) + { + if (b.NotNegative()) + PositiveAdd(sum, *this, b); + else + PositiveSubtract(sum, *this, b); + } + else + { + if (b.NotNegative()) + PositiveSubtract(sum, b, *this); + else + { + PositiveAdd(sum, *this, b); + sum.sign = Integer::NEGATIVE; + } + } + return sum; +} + +Integer& Integer::operator+=(const Integer& t) +{ + reg.CleanGrow(t.reg.size()); + if (NotNegative()) + { + if (t.NotNegative()) + PositiveAdd(*this, *this, t); + else + PositiveSubtract(*this, *this, t); + } + else + { + if (t.NotNegative()) + PositiveSubtract(*this, t, *this); + else + { + PositiveAdd(*this, *this, t); + sign = Integer::NEGATIVE; + } + } + return *this; +} + +Integer Integer::Minus(const Integer& b) const +{ + Integer diff((word)0, STDMAX2(reg.size(), b.reg.size())); + if (NotNegative()) + { + if (b.NotNegative()) + PositiveSubtract(diff, *this, b); + else + PositiveAdd(diff, *this, b); + } + else + { + if (b.NotNegative()) + { + PositiveAdd(diff, *this, b); + diff.sign = Integer::NEGATIVE; + } + else + PositiveSubtract(diff, b, *this); + } + return diff; +} + +Integer& Integer::operator-=(const Integer& t) +{ + reg.CleanGrow(t.reg.size()); + if (NotNegative()) + { + if (t.NotNegative()) + PositiveSubtract(*this, *this, t); + else + PositiveAdd(*this, *this, t); + } + else + { + if (t.NotNegative()) + { + PositiveAdd(*this, *this, t); + sign = Integer::NEGATIVE; + } + else + PositiveSubtract(*this, t, *this); + } + return *this; +} + +Integer& Integer::operator<<=(size_t n) +{ + const size_t wordCount = WordCount(); + const size_t shiftWords = n / WORD_BITS; + const unsigned int shiftBits = (unsigned int)(n % WORD_BITS); + + reg.CleanGrow(RoundupSize(wordCount+BitsToWords(n))); + ShiftWordsLeftByWords(reg, wordCount + shiftWords, shiftWords); + ShiftWordsLeftByBits(reg+shiftWords, wordCount+BitsToWords(shiftBits), shiftBits); + return *this; +} + +Integer& Integer::operator>>=(size_t n) +{ + const size_t wordCount = WordCount(); + const size_t shiftWords = n / WORD_BITS; + const unsigned int shiftBits = (unsigned int)(n % WORD_BITS); + + ShiftWordsRightByWords(reg, wordCount, shiftWords); + if (wordCount > shiftWords) + ShiftWordsRightByBits(reg, wordCount-shiftWords, shiftBits); + if (IsNegative() && WordCount()==0) // avoid -0 + *this = Zero(); + return *this; +} + +Integer& Integer::operator&=(const Integer& t) +{ + if (this != &t) + { + const size_t size = STDMIN(reg.size(), t.reg.size()); + reg.resize(size); + AndWords(reg, t.reg, size); + } + sign = POSITIVE; + return *this; +} + +Integer& Integer::operator|=(const Integer& t) +{ + if (this != &t) + { + if (reg.size() >= t.reg.size()) + { + OrWords(reg, t.reg, t.reg.size()); + } + else // reg.size() < t.reg.size() + { + const size_t head = reg.size(); + const size_t tail = t.reg.size() - reg.size(); + reg.resize(head+tail); + OrWords(reg, t.reg, head); + CopyWords(reg+head,t.reg+head,tail); + } + } + sign = POSITIVE; + return *this; +} + +Integer& Integer::operator^=(const Integer& t) +{ + if (this == &t) + { + *this = Zero(); + } + else + { + if (reg.size() >= t.reg.size()) + { + XorWords(reg, t.reg, t.reg.size()); + } + else // reg.size() < t.reg.size() + { + const size_t head = reg.size(); + const size_t tail = t.reg.size() - reg.size(); + reg.resize(head+tail); + XorWords(reg, t.reg, head); + CopyWords(reg+head,t.reg+head,tail); + } + } + sign = POSITIVE; + return *this; +} + +void PositiveMultiply(Integer &product, const Integer &a, const Integer &b) +{ + size_t aSize = RoundupSize(a.WordCount()); + size_t bSize = RoundupSize(b.WordCount()); + + product.reg.CleanNew(RoundupSize(aSize+bSize)); + product.sign = Integer::POSITIVE; + + IntegerSecBlock workspace(aSize + bSize); + AsymmetricMultiply(product.reg, workspace, a.reg, aSize, b.reg, bSize); +} + +void Multiply(Integer &product, const Integer &a, const Integer &b) +{ + PositiveMultiply(product, a, b); + + if (a.NotNegative() != b.NotNegative()) + product.Negate(); +} + +Integer Integer::Times(const Integer &b) const +{ + Integer product; + Multiply(product, *this, b); + return product; +} + +/* +void PositiveDivide(Integer &remainder, Integer "ient, + const Integer ÷nd, const Integer &divisor) +{ + remainder.reg.CleanNew(divisor.reg.size()); + remainder.sign = Integer::POSITIVE; + quotient.reg.New(0); + quotient.sign = Integer::POSITIVE; + unsigned i=dividend.BitCount(); + while (i--) + { + word overflow = ShiftWordsLeftByBits(remainder.reg, remainder.reg.size(), 1); + remainder.reg[0] |= dividend[i]; + if (overflow || remainder >= divisor) + { + Subtract(remainder.reg, remainder.reg, divisor.reg, remainder.reg.size()); + quotient.SetBit(i); + } + } +} +*/ + +void PositiveDivide(Integer &remainder, Integer "ient, + const Integer &a, const Integer &b) +{ + unsigned aSize = a.WordCount(); + unsigned bSize = b.WordCount(); + + if (!bSize) + throw Integer::DivideByZero(); + + if (aSize < bSize) + { + remainder = a; + remainder.sign = Integer::POSITIVE; + quotient = Integer::Zero(); + return; + } + + aSize += aSize%2; // round up to next even number + bSize += bSize%2; + + remainder.reg.CleanNew(RoundupSize(bSize)); + remainder.sign = Integer::POSITIVE; + quotient.reg.CleanNew(RoundupSize(aSize-bSize+2)); + quotient.sign = Integer::POSITIVE; + + IntegerSecBlock T(aSize+3*(bSize+2)); + Divide(remainder.reg, quotient.reg, T, a.reg, aSize, b.reg, bSize); +} + +void Integer::Divide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor) +{ + PositiveDivide(remainder, quotient, dividend, divisor); + + if (dividend.IsNegative()) + { + quotient.Negate(); + if (remainder.NotZero()) + { + --quotient; + remainder = divisor.AbsoluteValue() - remainder; + } + } + + if (divisor.IsNegative()) + quotient.Negate(); +} + +void Integer::DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n) +{ + q = a; + q >>= n; + + const size_t wordCount = BitsToWords(n); + if (wordCount <= a.WordCount()) + { + r.reg.resize(RoundupSize(wordCount)); + CopyWords(r.reg, a.reg, wordCount); + SetWords(r.reg+wordCount, 0, r.reg.size()-wordCount); + if (n % WORD_BITS != 0) + r.reg[wordCount-1] %= (word(1) << (n % WORD_BITS)); + } + else + { + r.reg.resize(RoundupSize(a.WordCount())); + CopyWords(r.reg, a.reg, r.reg.size()); + } + r.sign = POSITIVE; + + if (a.IsNegative() && r.NotZero()) + { + --q; + r = Power2(n) - r; + } +} + +Integer Integer::DividedBy(const Integer &b) const +{ + Integer remainder, quotient; + Integer::Divide(remainder, quotient, *this, b); + return quotient; +} + +Integer Integer::Modulo(const Integer &b) const +{ + Integer remainder, quotient; + Integer::Divide(remainder, quotient, *this, b); + return remainder; +} + +void Integer::Divide(word &remainder, Integer "ient, const Integer ÷nd, word divisor) +{ + if (!divisor) + throw Integer::DivideByZero(); + + // IsPowerOf2 uses BMI on x86 if available. There is a small + // but measurable improvement during decryption and signing. + if (IsPowerOf2(divisor)) + { + quotient = dividend >> (BitPrecision(divisor)-1); + remainder = dividend.reg[0] & (divisor-1); + return; + } + + unsigned int i = dividend.WordCount(); + quotient.reg.CleanNew(RoundupSize(i)); + remainder = 0; + while (i--) + { + quotient.reg[i] = DWord(dividend.reg[i], remainder) / divisor; + remainder = DWord(dividend.reg[i], remainder) % divisor; + } + + if (dividend.NotNegative()) + quotient.sign = POSITIVE; + else + { + quotient.sign = NEGATIVE; + if (remainder) + { + --quotient; + remainder = divisor - remainder; + } + } +} + +Integer Integer::DividedBy(word b) const +{ + word remainder; + Integer quotient; + Integer::Divide(remainder, quotient, *this, b); + return quotient; +} + +word Integer::Modulo(word divisor) const +{ + if (!divisor) + throw Integer::DivideByZero(); + + word remainder; + + // Profiling guided the flow below. + if ((divisor & (divisor-1)) != 0) // divisor is not a power of 2 + { + // Profiling guided the flow below. + unsigned int i = WordCount(); + if (divisor > 5) + { + remainder = 0; + while (i--) + remainder = DWord(reg[i], remainder) % divisor; + } + else + { + DWord sum(0, 0); + while (i--) + sum += reg[i]; + remainder = sum % divisor; + } + } + else // divisor is a power of 2 + { + remainder = reg[0] & (divisor-1); + } + + if (IsNegative() && remainder) + remainder = divisor - remainder; + + return remainder; +} + +void Integer::Negate() +{ + if (!!(*this)) // don't flip sign if *this==0 + sign = Sign(1-sign); +} + +int Integer::PositiveCompare(const Integer& t) const +{ + // Profiling guided the flow below. + const unsigned size = WordCount(), tSize = t.WordCount(); + if (size != tSize) + return size > tSize ? 1 : -1; + else + return CryptoPP::Compare(reg, t.reg, size); +} + +int Integer::Compare(const Integer& t) const +{ + if (NotNegative()) + { + if (t.NotNegative()) + return PositiveCompare(t); + else + return 1; + } + else + { + if (t.NotNegative()) + return -1; + else + return -PositiveCompare(t); + } +} + +Integer Integer::SquareRoot() const +{ + if (!IsPositive()) + return Zero(); + + // overestimate square root + Integer x, y = Power2((BitCount()+1)/2); + CRYPTOPP_ASSERT(y*y >= *this); + + do + { + x = y; + y = (x + *this/x) >> 1; + } while (y().Gcd(a, b); +} + +Integer Integer::InverseMod(const Integer &m) const +{ + CRYPTOPP_ASSERT(m.NotNegative()); + CRYPTOPP_ASSERT(m.NotZero()); + + if (IsNegative()) + return Modulo(m).InverseModNext(m); + + // http://github.com/weidai11/cryptopp/issues/602 + if (*this >= m) + return Modulo(m).InverseModNext(m); + + return InverseModNext(m); +} + +Integer Integer::InverseModNext(const Integer &m) const +{ + CRYPTOPP_ASSERT(m.NotNegative()); + CRYPTOPP_ASSERT(m.NotZero()); + + if (m.IsEven()) + { + if (!m || IsEven()) + return Zero(); // no inverse + if (*this == One()) + return One(); + + Integer u = m.Modulo(*this).InverseModNext(*this); + return !u ? Zero() : (m*(*this-u)+1)/(*this); + } + + // AlmostInverse requires a 4x workspace + IntegerSecBlock T(m.reg.size() * 4); + Integer r((word)0, m.reg.size()); + unsigned k = AlmostInverse(r.reg, T, reg, reg.size(), m.reg, m.reg.size()); + DivideByPower2Mod(r.reg, r.reg, k, m.reg, m.reg.size()); + return r; +} + +word Integer::InverseMod(word mod) const +{ + CRYPTOPP_ASSERT(mod != 0); + + word g0 = mod, g1 = *this % mod; + word v0 = 0, v1 = 1; + word y; + + while (g1) + { + if (g1 == 1) + return v1; + y = g0 / g1; + g0 = g0 % g1; + v0 += y * v1; + + if (!g0) + break; + if (g0 == 1) + return mod-v0; + y = g1 / g0; + g1 = g1 % g0; + v1 += y * v0; + } + return 0; +} + +// ******************************************************** + +ModularArithmetic::ModularArithmetic(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + OID oid(seq); + if (oid != ASN1::prime_field()) + BERDecodeError(); + m_modulus.BERDecode(seq); + seq.MessageEnd(); + m_result.reg.resize(m_modulus.reg.size()); +} + +void ModularArithmetic::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + ASN1::prime_field().DEREncode(seq); + m_modulus.DEREncode(seq); + seq.MessageEnd(); +} + +void ModularArithmetic::DEREncodeElement(BufferedTransformation &out, const Element &a) const +{ + a.DEREncodeAsOctetString(out, MaxElementByteLength()); +} + +void ModularArithmetic::BERDecodeElement(BufferedTransformation &in, Element &a) const +{ + a.BERDecodeAsOctetString(in, MaxElementByteLength()); +} + +const Integer& ModularArithmetic::Half(const Integer &a) const +{ + if (a.reg.size()==m_modulus.reg.size()) + { + CryptoPP::DivideByPower2Mod(m_result.reg.begin(), a.reg, 1, m_modulus.reg, a.reg.size()); + return m_result; + } + else + return m_result1 = (a.IsEven() ? (a >> 1) : ((a+m_modulus) >> 1)); +} + +const Integer& ModularArithmetic::Add(const Integer &a, const Integer &b) const +{ + if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) + { + if (CryptoPP::Add(m_result.reg.begin(), a.reg, b.reg, a.reg.size()) + || Compare(m_result.reg, m_modulus.reg, a.reg.size()) >= 0) + { + CryptoPP::Subtract(m_result.reg.begin(), m_result.reg, m_modulus.reg, a.reg.size()); + } + return m_result; + } + else + { + m_result1 = a+b; + if (m_result1 >= m_modulus) + m_result1 -= m_modulus; + return m_result1; + } +} + +Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const +{ + if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) + { + if (CryptoPP::Add(a.reg, a.reg, b.reg, a.reg.size()) + || Compare(a.reg, m_modulus.reg, a.reg.size()) >= 0) + { + CryptoPP::Subtract(a.reg, a.reg, m_modulus.reg, a.reg.size()); + } + } + else + { + a+=b; + if (a>=m_modulus) + a-=m_modulus; + } + + return a; +} + +const Integer& ModularArithmetic::Subtract(const Integer &a, const Integer &b) const +{ + if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) + { + if (CryptoPP::Subtract(m_result.reg.begin(), a.reg, b.reg, a.reg.size())) + CryptoPP::Add(m_result.reg.begin(), m_result.reg, m_modulus.reg, a.reg.size()); + return m_result; + } + else + { + m_result1 = a-b; + if (m_result1.IsNegative()) + m_result1 += m_modulus; + return m_result1; + } +} + +Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const +{ + if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) + { + if (CryptoPP::Subtract(a.reg, a.reg, b.reg, a.reg.size())) + CryptoPP::Add(a.reg, a.reg, m_modulus.reg, a.reg.size()); + } + else + { + a-=b; + if (a.IsNegative()) + a+=m_modulus; + } + + return a; +} + +const Integer& ModularArithmetic::Inverse(const Integer &a) const +{ + if (!a) + return a; + + CopyWords(m_result.reg.begin(), m_modulus.reg, m_modulus.reg.size()); + if (CryptoPP::Subtract(m_result.reg.begin(), m_result.reg, a.reg, a.reg.size())) + Decrement(m_result.reg.begin()+a.reg.size(), m_modulus.reg.size()-a.reg.size()); + + return m_result; +} + +Integer ModularArithmetic::CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const +{ + if (m_modulus.IsOdd()) + { + MontgomeryRepresentation dr(m_modulus); + return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1, dr.ConvertIn(y), e2)); + } + else + return AbstractRing::CascadeExponentiate(x, e1, y, e2); +} + +void ModularArithmetic::SimultaneousExponentiate(Integer *results, const Integer &base, const Integer *exponents, unsigned int exponentsCount) const +{ + if (m_modulus.IsOdd()) + { + MontgomeryRepresentation dr(m_modulus); + dr.SimultaneousExponentiate(results, dr.ConvertIn(base), exponents, exponentsCount); + for (unsigned int i=0; i::SimultaneousExponentiate(results, base, exponents, exponentsCount); +} + +MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m) // modulus must be odd + : ModularArithmetic(m), + m_u((word)0, m_modulus.reg.size()), + m_workspace(5*m_modulus.reg.size()) +{ + if (!m_modulus.IsOdd()) + throw InvalidArgument("MontgomeryRepresentation: Montgomery representation requires an odd modulus"); + + RecursiveInverseModPower2(m_u.reg, m_workspace, m_modulus.reg, m_modulus.reg.size()); +} + +const Integer& MontgomeryRepresentation::Multiply(const Integer &a, const Integer &b) const +{ + word *const T = m_workspace.begin(); + word *const R = m_result.reg.begin(); + const size_t N = m_modulus.reg.size(); + CRYPTOPP_ASSERT(a.reg.size()<=N && b.reg.size()<=N); + + AsymmetricMultiply(T, T+2*N, a.reg, a.reg.size(), b.reg, b.reg.size()); + SetWords(T+a.reg.size()+b.reg.size(), 0, 2*N-a.reg.size()-b.reg.size()); + MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); + return m_result; +} + +const Integer& MontgomeryRepresentation::Square(const Integer &a) const +{ + word *const T = m_workspace.begin(); + word *const R = m_result.reg.begin(); + const size_t N = m_modulus.reg.size(); + CRYPTOPP_ASSERT(a.reg.size()<=N); + + CryptoPP::Square(T, T+2*N, a.reg, a.reg.size()); + SetWords(T+2*a.reg.size(), 0, 2*N-2*a.reg.size()); + MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); + return m_result; +} + +Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const +{ + word *const T = m_workspace.begin(); + word *const R = m_result.reg.begin(); + const size_t N = m_modulus.reg.size(); + CRYPTOPP_ASSERT(a.reg.size()<=N); + + CopyWords(T, a.reg, a.reg.size()); + SetWords(T+a.reg.size(), 0, 2*N-a.reg.size()); + MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); + return m_result; +} + +const Integer& MontgomeryRepresentation::MultiplicativeInverse(const Integer &a) const +{ +// return (EuclideanMultiplicativeInverse(a, modulus)<<(2*WORD_BITS*modulus.reg.size()))%modulus; + word *const T = m_workspace.begin(); + word *const R = m_result.reg.begin(); + const size_t N = m_modulus.reg.size(); + CRYPTOPP_ASSERT(a.reg.size()<=N); + + CopyWords(T, a.reg, a.reg.size()); + SetWords(T+a.reg.size(), 0, 2*N-a.reg.size()); + MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); + unsigned k = AlmostInverse(R, T, R, N, m_modulus.reg, N); + +// cout << "k=" << k << " N*32=" << 32*N << endl; + + if (k>N*WORD_BITS) + DivideByPower2Mod(R, R, k-N*WORD_BITS, m_modulus.reg, N); + else + MultiplyByPower2Mod(R, R, N*WORD_BITS-k, m_modulus.reg, N); + + return m_result; +} + +// Specialization declared in misc.h to allow us to print integers +// with additional control options, like arbirary bases and uppercase. +template <> CRYPTOPP_DLL +std::string IntToString(Integer value, unsigned int base) +{ + // Hack... set the high bit for uppercase. Set the next bit fo a suffix. + static const unsigned int BIT_32 = (1U << 31); + const bool UPPER = !!(base & BIT_32); + static const unsigned int BIT_31 = (1U << 30); + const bool BASE = !!(base & BIT_31); + + const char CH = UPPER ? 'A' : 'a'; + base &= ~(BIT_32|BIT_31); + CRYPTOPP_ASSERT(base >= 2 && base <= 32); + + if (value == 0) + return "0"; + + bool negative = false, zero = false; + if (value.IsNegative()) + { + negative = true; + value.Negate(); + } + + if (!value) + zero = true; + + SecBlock s(value.BitCount() / (SaturatingSubtract1(BitPrecision(base),1U)) + 1); + Integer temp; + + unsigned int i=0; + while (!!value) + { + word digit; + Integer::Divide(digit, temp, value, word(base)); + s[i++]=char((digit < 10 ? '0' : (CH - 10)) + digit); + value.swap(temp); + } + + std::string result; + result.reserve(i+2); + + if (negative) + result += '-'; + + if (zero) + result += '0'; + + while (i--) + result += s[i]; + + if (BASE) + { + if (base == 10) + result += '.'; + else if (base == 16) + result += 'h'; + else if (base == 8) + result += 'o'; + else if (base == 2) + result += 'b'; + } + + return result; +} + +// Specialization declared in misc.h to avoid Coverity findings. +template <> CRYPTOPP_DLL +std::string IntToString(word64 value, unsigned int base) +{ + // Hack... set the high bit for uppercase. + static 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"; + + std::string result; + while (value > 0) + { + word64 digit = value % base; + result = char((digit < 10 ? '0' : (CH - 10)) + digit) + result; + value /= base; + } + return result; +} + +#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. +bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt) +{ + if (valueType != typeid(Integer)) + return false; + *reinterpret_cast(pInteger) = *reinterpret_cast(pInt); + return true; +} +#endif // CRYPTOPP_NO_ASSIGN_TO_INTEGER + +// *************************** C++ Static Initialization *************************** + +class InitInteger +{ +public: + InitInteger() + { + SetFunctionPointers(); + } +}; + +// This is not really needed because each Integer can dynamically initialize +// itself, but we take a peephole optimization and initialize the class once +// if init priorities are available. Dynamic initialization will be used if +// init priorities are not available. + +#if defined(HAVE_GCC_INIT_PRIORITY) + const InitInteger s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 10))) = InitInteger(); + const Integer g_zero __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 11))) = Integer(0L); + const Integer g_one __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 12))) = Integer(1L); + const Integer g_two __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 13))) = Integer(2L); +#elif defined(HAVE_MSC_INIT_PRIORITY) + #pragma warning(disable: 4075) + #pragma init_seg(".CRT$XCU") + const InitInteger s_init; + const Integer g_zero(0L); + const Integer g_one(1L); + const Integer g_two(2L); + #pragma warning(default: 4075) +#elif HAVE_XLC_INIT_PRIORITY + // XLC needs constant, not a define + #pragma priority(280) + const InitInteger s_init; + const Integer g_zero(0L); + const Integer g_one(1L); + const Integer g_two(2L); +#else + const InitInteger s_init; +#endif + +// ***************** Library code ******************** + +const Integer &Integer::Zero() +{ +#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY) || defined(HAVE_XLC_INIT_PRIORITY) + return g_zero; +#elif defined(CRYPTOPP_CXX11_STATIC_INIT) + static const Integer s_zero(0L); + return s_zero; +#else // Potential memory leak. Avoid if possible. + return Singleton >().Ref(); +#endif +} + +const Integer &Integer::One() +{ +#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY) || defined(HAVE_XLC_INIT_PRIORITY) + return g_one; +#elif defined(CRYPTOPP_CXX11_STATIC_INIT) + static const Integer s_one(1L); + return s_one; +#else // Potential memory leak. Avoid if possible. + return Singleton >().Ref(); +#endif +} + +const Integer &Integer::Two() +{ +#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY) || defined(HAVE_XLC_INIT_PRIORITY) + return g_two; +#elif defined(CRYPTOPP_CXX11_STATIC_INIT) + static const Integer s_two(2L); + return s_two; +#else // Potential memory leak. Avoid if possible. + return Singleton >().Ref(); +#endif +} + +NAMESPACE_END + +#endif // CRYPTOPP_IMPORTS diff --git a/external/ours/library/crypto/src/shared/original/integer.h b/external/ours/library/crypto/src/shared/original/integer.h new file mode 100755 index 000000000..d727bdf78 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/integer.h @@ -0,0 +1,837 @@ +// 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 2, 8, 10, or 16. Base is determined by a case + /// insensitive suffix of 'h', 'o', or 'b'. 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 2, 8, 10, or 16. Base is determined by a case + /// insensitive suffix of 'h', 'o', or 'b'. 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]. + 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 comapre + /// \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 a reference to the dividend + /// \param d a reference to the divisor + /// \details Divide calculates r and q such that (a == d*q + r) && (0 <= r < abs(d)). + static void CRYPTOPP_API Divide(Integer &r, Integer &q, const Integer &a, const Integer &d); + + /// \brief Extended Division + /// \param r a reference for the remainder + /// \param q a reference for the quotient + /// \param a a reference to the dividend + /// \param d a reference to the divisor + /// \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 a reference to the dividend + /// \param n a 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 a reference to the first number + /// \param n a 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 a 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 a reference to a std::istream + /// \param a a reference to an Integer + /// \return a reference to a std::istream reference + friend CRYPTOPP_DLL std::istream& CRYPTOPP_API operator>>(std::istream& in, Integer &a); + + /// \brief Insertion operator + /// \param out a reference to a std::ostream + /// \param a a constant reference to an Integer + /// \return a reference to a std::ostream reference + /// \details The output integer responds to std::hex, std::oct, std::hex, std::upper and + /// std::lower. The output includes the suffix \a 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 a reference to the first term + /// \param y a reference to the second term + /// \param m a 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 a reference to the base + /// \param e a reference to the exponent + /// \param m a 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/external/ours/library/crypto/src/shared/original/iterhash.cpp b/external/ours/library/crypto/src/shared/original/iterhash.cpp index 1730ce941..938a0faca 100755 --- a/external/ours/library/crypto/src/shared/original/iterhash.cpp +++ b/external/ours/library/crypto/src/shared/original/iterhash.cpp @@ -1,14 +1,200 @@ -// iterhash.cpp - written and placed in the public domain by Wei Dai - -#include "FirstCrypto.h" -#include "iterhash.h" - -NAMESPACE_BEGIN(CryptoPP) - -#ifdef WORD64_AVAILABLE -template class IteratedHashBase; -#endif - -template class IteratedHashBase; - -NAMESPACE_END +// iterhash.cpp - originally written and placed in the public domain by Wei Dai + +#ifndef __GNUC__ +#define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#endif + +#include "iterhash.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +template void IteratedHashBase::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT(!(input == NULLPTR && length != 0)); + if (length == 0) { return; } + + HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi; + if ((m_countLo = oldCountLo + HashWordType(length)) < oldCountLo) + m_countHi++; // carry from low to high + m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(length); + if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(length) != 0) + throw HashInputTooLong(this->AlgorithmName()); + + const unsigned int blockSize = this->BlockSize(); + unsigned int num = ModPowerOf2(oldCountLo, blockSize); + + T* dataBuf = this->DataBuf(); + byte* data = (byte *)dataBuf; + + if (num != 0) // process left over data + { + if (num+length >= blockSize) + { + if (input) + {std::memcpy(data+num, input, blockSize-num);} + + HashBlock(dataBuf); + input += (blockSize-num); + length -= (blockSize-num); + num = 0; + // drop through and do the rest + } + else + { + if (input && length) + {std::memcpy(data+num, input, length);} + return; + } + } + + // now process the input data in blocks of blockSize bytes and save the leftovers to m_data + if (length >= blockSize) + { + if (input == data) + { + CRYPTOPP_ASSERT(length == blockSize); + HashBlock(dataBuf); + return; + } + else if (IsAligned(input)) + { + size_t leftOver = HashMultipleBlocks((T *)(void*)input, length); + input += (length - leftOver); + length = leftOver; + } + else + { + do + { // copy input first if it's not aligned correctly + if (input) + { std::memcpy(data, input, blockSize); } + + HashBlock(dataBuf); + input+=blockSize; + length-=blockSize; + } while (length >= blockSize); + } + } + + if (input && data != input) + std::memcpy(data, input, length); +} + +template byte * IteratedHashBase::CreateUpdateSpace(size_t &size) +{ + unsigned int blockSize = this->BlockSize(); + unsigned int num = ModPowerOf2(m_countLo, blockSize); + size = blockSize - num; + return (byte *)DataBuf() + num; +} + +template size_t IteratedHashBase::HashMultipleBlocks(const T *input, size_t length) +{ + const unsigned int blockSize = this->BlockSize(); + bool noReverse = NativeByteOrderIs(this->GetByteOrder()); + T* dataBuf = this->DataBuf(); + + // Alignment checks due to http://github.com/weidai11/cryptopp/issues/690. + // Sparc requires 8-byte aligned buffer when HashWordType is word64. + // We also had to provide a GetAlignmentOf specialization for word64 on Sparc. + + do + { + if (noReverse) + { + if (IsAligned(input)) + { + // Sparc bus error with non-aligned input. + this->HashEndianCorrectedBlock(input); + } + else + { + std::memcpy(dataBuf, input, blockSize); + this->HashEndianCorrectedBlock(dataBuf); + } + } + else + { + if (IsAligned(input)) + { + // Sparc bus error with non-aligned input. + ByteReverse(dataBuf, input, blockSize); + this->HashEndianCorrectedBlock(dataBuf); + } + else + { + std::memcpy(dataBuf, input, blockSize); + ByteReverse(dataBuf, dataBuf, blockSize); + this->HashEndianCorrectedBlock(dataBuf); + } + } + + input += blockSize/sizeof(T); + length -= blockSize; + } + while (length >= blockSize); + return length; +} + +template void IteratedHashBase::PadLastBlock(unsigned int lastBlockSize, byte padFirst) +{ + unsigned int blockSize = this->BlockSize(); + unsigned int num = ModPowerOf2(m_countLo, blockSize); + T* dataBuf = this->DataBuf(); + byte* data = (byte *)dataBuf; + + data[num++] = padFirst; + if (num <= lastBlockSize) + memset(data+num, 0, lastBlockSize-num); + else + { + memset(data+num, 0, blockSize-num); + HashBlock(dataBuf); + memset(data, 0, lastBlockSize); + } +} + +template void IteratedHashBase::Restart() +{ + m_countLo = m_countHi = 0; + Init(); +} + +template void IteratedHashBase::TruncatedFinal(byte *digest, size_t size) +{ + CRYPTOPP_ASSERT(digest != NULLPTR); + this->ThrowIfInvalidTruncatedSize(size); + + T* dataBuf = this->DataBuf(); + T* stateBuf = this->StateBuf(); + unsigned int blockSize = this->BlockSize(); + ByteOrder order = this->GetByteOrder(); + + PadLastBlock(blockSize - 2*sizeof(HashWordType)); + dataBuf[blockSize/sizeof(T)-2+order] = ConditionalByteReverse(order, this->GetBitCountLo()); + dataBuf[blockSize/sizeof(T)-1-order] = ConditionalByteReverse(order, this->GetBitCountHi()); + + HashBlock(dataBuf); + + if (IsAligned(digest) && size%sizeof(HashWordType)==0) + ConditionalByteReverse(order, (HashWordType *)(void*)digest, stateBuf, size); + else + { + ConditionalByteReverse(order, stateBuf, stateBuf, this->DigestSize()); + std::memcpy(digest, stateBuf, size); + } + + this->Restart(); // reinit for next use +} + +#if defined(__GNUC__) || defined(__clang__) + template class IteratedHashBase; + template class IteratedHashBase; + + template class IteratedHashBase; + template class IteratedHashBase; +#endif + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/iterhash.h b/external/ours/library/crypto/src/shared/original/iterhash.h index a0abd0e73..49d325857 100755 --- a/external/ours/library/crypto/src/shared/original/iterhash.h +++ b/external/ours/library/crypto/src/shared/original/iterhash.h @@ -1,187 +1,218 @@ -#ifndef CRYPTOPP_ITERHASH_H -#define CRYPTOPP_ITERHASH_H - -#include "cryptlib.h" -#include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -/*! The following classes are explicitly instantiated in iterhash.cpp - - IteratedHashBase - IteratedHashBase // #ifdef WORD64_AVAILABLE -*/ -template -class IteratedHashBase : public virtual HashModule -{ -public: - typedef T HashWordType; - - IteratedHashBase(unsigned int blockSize, unsigned int digestSize); - unsigned int DigestSize() const {return digest.size * sizeof(T);}; - void Update(const byte *input, unsigned int length); - -protected: - virtual unsigned int HashMultipleBlocks(const T *input, unsigned int length); - void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80); - void Reinit(); - virtual void Init() =0; - virtual void HashBlock(const T *input) =0; - - unsigned int blockSize; - word32 countLo, countHi; // 64-bit bit count - SecBlock data; // Data buffer - SecBlock digest; // Message digest -}; - -template -IteratedHashBase::IteratedHashBase(unsigned int blockSize, unsigned int digestSize) - : blockSize(blockSize), countLo(0), countHi(0) - , data(blockSize/sizeof(T)), digest(digestSize/sizeof(T)) -{ -} - -template void IteratedHashBase::Update(const byte *input, unsigned int len) -{ - HashWordType tmp = countLo; - if ((countLo = tmp + ((word32)len << 3)) < tmp) - countHi++; // Carry from low to high - - int rshift = (8*sizeof(HashWordType)-3); - if (rshift<32) - { - countHi += len >> rshift; - } - - assert((blockSize & (blockSize-1)) == 0); // blockSize is a power of 2 - unsigned int num = (unsigned int)(tmp >> 3) & (blockSize-1); - - if (num != 0) - { - if ((num+len) >= blockSize) - { - memcpy((byte *)data.ptr+num, input, blockSize-num); - HashBlock(data); - input += (blockSize-num); - len-=(blockSize - num); - num=0; - // drop through and do the rest - } - else - { - memcpy((byte *)data.ptr+num, input, len); - return; - } - } - - // we now can process the input data in blocks of blockSize - // chars and save the leftovers to this->data. - if (len >= blockSize) - { - if (IsAligned(input)) - { - unsigned int leftOver = HashMultipleBlocks((T *)input, len); - input += (len - leftOver); - len = leftOver; - } - else - do - { // copy input first if it's not aligned correctly - memcpy(data, input, blockSize); - HashBlock(data); - input+=blockSize; - len-=blockSize; - } while (len >= blockSize); - } - - memcpy(data, input, len); -} - -template unsigned int IteratedHashBase::HashMultipleBlocks(const T *input, unsigned int length) -{ - do - { - HashBlock(input); - input += blockSize/sizeof(T); - length -= blockSize; - } - while (length >= blockSize); - return length; -} - -template void IteratedHashBase::PadLastBlock(unsigned int lastBlockSize, byte padFirst) -{ - unsigned int num = (unsigned int)(countLo >> 3) & (blockSize-1); - assert(num < blockSize); - ((byte *)data.ptr)[num++]=padFirst; - if (num <= lastBlockSize) - memset((byte *)data.ptr+num, 0, lastBlockSize-num); - else - { - memset((byte *)data.ptr+num, 0, blockSize-num); - HashBlock(data); - memset(data, 0, lastBlockSize); - } -} - -template void IteratedHashBase::Reinit() -{ - countLo = countHi = 0; - Init(); -} - -// provide empty definitions to avoid instantiation warnings -template void IteratedHashBase::Init() {} -template void IteratedHashBase::HashBlock(const T *input) {} - -//! . -template -class IteratedHash : public IteratedHashBase -{ -public: - typedef T HashWordType; - enum {HIGHFIRST = H, BLOCKSIZE = S}; - - IteratedHash(unsigned int digestSize) : IteratedHashBase(BLOCKSIZE, digestSize) {} - - inline static void CorrectEndianess(HashWordType *out, const HashWordType *in, unsigned int byteCount) - { - if (!CheckEndianess(HIGHFIRST)) - byteReverse(out, in, byteCount); - else if (in!=out) - memcpy(out, in, byteCount); - } - - void Final(byte *hash) - { - this->PadLastBlock(BLOCKSIZE - 2*sizeof(HashWordType)); - CorrectEndianess(this->data, this->data, BLOCKSIZE - 2*sizeof(HashWordType)); - - this->data[this->data.size-2] = HIGHFIRST ? this->countHi : this->countLo; - this->data[this->data.size-1] = HIGHFIRST ? this->countLo : this->countHi; - - vTransform(this->data); - CorrectEndianess(this->digest, this->digest, this->DigestSize()); - memcpy(hash, this->digest, this->DigestSize()); - - this->Reinit(); // reinit for next use - } - -protected: - void HashBlock(const HashWordType *input) - { - if (CheckEndianess(HIGHFIRST)) - vTransform(input); - else - { - byteReverse(this->data.ptr, input, (unsigned int)BLOCKSIZE); - vTransform(this->data); - } - } - - virtual void vTransform(const HashWordType *data) =0; -}; - -NAMESPACE_END - -#endif +// 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/external/ours/library/crypto/src/shared/original/kalyna.cpp b/external/ours/library/crypto/src/shared/original/kalyna.cpp new file mode 100755 index 000000000..14d411e13 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/kalyna.cpp @@ -0,0 +1,1362 @@ +// kalyna.cpp - written and placed in the public domain by Jeffrey Walton +// This code 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 and most utilized resource +// was Keru Kuro's public domain 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. The only downside +// was the missing big endian port. + +#include "pch.h" +#include "config.h" + +#include "kalyna.h" +#include "argnames.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(KalynaTab) + +// T can be shared between Kupyna and Kalyna; IT, S and IS are Kalyna specific +extern const word64 T[8][256]; // Columns +extern const word64 IT[8][256]; // Inverse +extern const byte S[4][256]; // Substitution +extern const byte IS[4][256]; // Inverse + +NAMESPACE_END +NAMESPACE_END + +ANONYMOUS_NAMESPACE_BEGIN + +// The typedef here is to sidestep problems with byte in the global namespace +typedef unsigned char byte; + +using CryptoPP::word64; +using CryptoPP::KalynaTab::T; +using CryptoPP::KalynaTab::S; +using CryptoPP::KalynaTab::IT; +using CryptoPP::KalynaTab::IS; + +template +inline void MakeOddKey(const word64 evenkey[NB], word64 oddkey[NB]) +{ +#if (CRYPTOPP_BIG_ENDIAN) + if (NB == 2) + { + oddkey[0] = (evenkey[1] << 8) | (evenkey[0] >> 56); + oddkey[1] = (evenkey[0] << 8) | (evenkey[1] >> 56); + } + else if (NB == 4) + { + oddkey[0] = (evenkey[2] << 40) | (evenkey[1] >> 24); + oddkey[1] = (evenkey[3] << 40) | (evenkey[2] >> 24); + oddkey[2] = (evenkey[0] << 40) | (evenkey[3] >> 24); + oddkey[3] = (evenkey[1] << 40) | (evenkey[0] >> 24); + } + else if (NB == 8) + { + oddkey[0] = (evenkey[3] << 40) | (evenkey[2] >> 24); + oddkey[1] = (evenkey[4] << 40) | (evenkey[3] >> 24); + oddkey[2] = (evenkey[5] << 40) | (evenkey[4] >> 24); + oddkey[3] = (evenkey[6] << 40) | (evenkey[5] >> 24); + + oddkey[4] = (evenkey[7] << 40) | (evenkey[6] >> 24); + oddkey[5] = (evenkey[0] << 40) | (evenkey[7] >> 24); + oddkey[6] = (evenkey[1] << 40) | (evenkey[0] >> 24); + oddkey[7] = (evenkey[2] << 40) | (evenkey[1] >> 24); + } + else + { + CRYPTOPP_ASSERT(0); + } +#else + static const unsigned int U = (NB == 2) ? 16 : (NB == 4) ? 32 : (NB == 8) ? 64 : -1; + static const unsigned int V = (NB == 2) ? 7 : (NB == 4) ? 11 : (NB == 8) ? 19 : -1; + + const byte* even = reinterpret_cast(evenkey); + byte* odd = reinterpret_cast(oddkey); + + memcpy(odd, even + V, U - V); + memcpy(odd + U - V, even, V); +#endif +} + +template +inline void SwapBlocks(word64 k[NB]) +{ + const word64 t = k[0]; + k[0] = k[1]; + + if (NB > 2) + { + k[1] = k[2]; + k[2] = k[3]; + } + + if (NB > 4) + { + k[3] = k[4]; + k[4] = k[5]; + k[5] = k[6]; + k[6] = k[7]; + } + + k[NB - 1] = t; +} + +template +inline void AddKey(const word64 x[NB], word64 y[NB], const word64 k[NB]) +{ + y[0] = x[0] + k[0]; + y[1] = x[1] + k[1]; + + if (NB > 2) + { + y[2] = x[2] + k[2]; + y[3] = x[3] + k[3]; + } + + if (NB > 4) + { + y[4] = x[4] + k[4]; + y[5] = x[5] + k[5]; + y[6] = x[6] + k[6]; + y[7] = x[7] + k[7]; + } +} + +template +inline void SubKey(const word64 x[NB], word64 y[NB], const word64 k[NB]) +{ + y[0] = x[0] - k[0]; + y[1] = x[1] - k[1]; + + if (NB > 2) + { + y[2] = x[2] - k[2]; + y[3] = x[3] - k[3]; + } + + if (NB > 4) + { + y[4] = x[4] - k[4]; + y[5] = x[5] - k[5]; + y[6] = x[6] - k[6]; + y[7] = x[7] - k[7]; + } +} + +template +static inline void AddConstant(word64 src[NB], word64 dst[NB], word64 constant) +{ + dst[0] = src[0] + constant; + dst[1] = src[1] + constant; + + if (NB > 2) + { + dst[2] = src[2] + constant; + dst[3] = src[3] + constant; + } + + if (NB > 4) + { + dst[4] = src[4] + constant; + dst[5] = src[5] + constant; + dst[6] = src[6] + constant; + dst[7] = src[7] + constant; + } +} + +inline void G0128(const word64 x[2], word64 y[2]) +{ + y[0] = T[0][(byte)x[0]] ^ T[1][(byte)(x[0] >> 8)] ^ T[2][(byte)(x[0] >> 16)] ^ T[3][(byte)(x[0] >> 24)] ^ + T[4][(byte)(x[1] >> 32)] ^ T[5][(byte)(x[1] >> 40)] ^ T[6][(byte)(x[1] >> 48)] ^ T[7][(byte)(x[1] >> 56)]; + y[1] = T[0][(byte)x[1]] ^ T[1][(byte)(x[1] >> 8)] ^ T[2][(byte)(x[1] >> 16)] ^ T[3][(byte)(x[1] >> 24)] ^ + T[4][(byte)(x[0] >> 32)] ^ T[5][(byte)(x[0] >> 40)] ^ T[6][(byte)(x[0] >> 48)] ^ T[7][(byte)(x[0] >> 56)]; +} + +inline void G0256(const word64 x[4], word64 y[4]) +{ + y[0] = T[0][(byte)x[0]] ^ T[1][(byte)(x[0] >> 8)] ^ T[2][(byte)(x[3] >> 16)] ^ T[3][(byte)(x[3] >> 24)] ^ + T[4][(byte)(x[2] >> 32)] ^ T[5][(byte)(x[2] >> 40)] ^ T[6][(byte)(x[1] >> 48)] ^ T[7][(byte)(x[1] >> 56)]; + y[1] = T[0][(byte)x[1]] ^ T[1][(byte)(x[1] >> 8)] ^ T[2][(byte)(x[0] >> 16)] ^ T[3][(byte)(x[0] >> 24)] ^ + T[4][(byte)(x[3] >> 32)] ^ T[5][(byte)(x[3] >> 40)] ^ T[6][(byte)(x[2] >> 48)] ^ T[7][(byte)(x[2] >> 56)]; + y[2] = T[0][(byte)x[2]] ^ T[1][(byte)(x[2] >> 8)] ^ T[2][(byte)(x[1] >> 16)] ^ T[3][(byte)(x[1] >> 24)] ^ + T[4][(byte)(x[0] >> 32)] ^ T[5][(byte)(x[0] >> 40)] ^ T[6][(byte)(x[3] >> 48)] ^ T[7][(byte)(x[3] >> 56)]; + y[3] = T[0][(byte)x[3]] ^ T[1][(byte)(x[3] >> 8)] ^ T[2][(byte)(x[2] >> 16)] ^ T[3][(byte)(x[2] >> 24)] ^ + T[4][(byte)(x[1] >> 32)] ^ T[5][(byte)(x[1] >> 40)] ^ T[6][(byte)(x[0] >> 48)] ^ T[7][(byte)(x[0] >> 56)]; +} + +inline void G0512(const word64 x[8], word64 y[8]) +{ + y[0] = T[0][(byte)x[0]] ^ T[1][(byte)(x[7] >> 8)] ^ T[2][(byte)(x[6] >> 16)] ^ T[3][(byte)(x[5] >> 24)] ^ + T[4][(byte)(x[4] >> 32)] ^ T[5][(byte)(x[3] >> 40)] ^ T[6][(byte)(x[2] >> 48)] ^ T[7][(byte)(x[1] >> 56)]; + y[1] = T[0][(byte)x[1]] ^ T[1][(byte)(x[0] >> 8)] ^ T[2][(byte)(x[7] >> 16)] ^ T[3][(byte)(x[6] >> 24)] ^ + T[4][(byte)(x[5] >> 32)] ^ T[5][(byte)(x[4] >> 40)] ^ T[6][(byte)(x[3] >> 48)] ^ T[7][(byte)(x[2] >> 56)]; + y[2] = T[0][(byte)x[2]] ^ T[1][(byte)(x[1] >> 8)] ^ T[2][(byte)(x[0] >> 16)] ^ T[3][(byte)(x[7] >> 24)] ^ + T[4][(byte)(x[6] >> 32)] ^ T[5][(byte)(x[5] >> 40)] ^ T[6][(byte)(x[4] >> 48)] ^ T[7][(byte)(x[3] >> 56)]; + y[3] = T[0][(byte)x[3]] ^ T[1][(byte)(x[2] >> 8)] ^ T[2][(byte)(x[1] >> 16)] ^ T[3][(byte)(x[0] >> 24)] ^ + T[4][(byte)(x[7] >> 32)] ^ T[5][(byte)(x[6] >> 40)] ^ T[6][(byte)(x[5] >> 48)] ^ T[7][(byte)(x[4] >> 56)]; + y[4] = T[0][(byte)x[4]] ^ T[1][(byte)(x[3] >> 8)] ^ T[2][(byte)(x[2] >> 16)] ^ T[3][(byte)(x[1] >> 24)] ^ + T[4][(byte)(x[0] >> 32)] ^ T[5][(byte)(x[7] >> 40)] ^ T[6][(byte)(x[6] >> 48)] ^ T[7][(byte)(x[5] >> 56)]; + y[5] = T[0][(byte)x[5]] ^ T[1][(byte)(x[4] >> 8)] ^ T[2][(byte)(x[3] >> 16)] ^ T[3][(byte)(x[2] >> 24)] ^ + T[4][(byte)(x[1] >> 32)] ^ T[5][(byte)(x[0] >> 40)] ^ T[6][(byte)(x[7] >> 48)] ^ T[7][(byte)(x[6] >> 56)]; + y[6] = T[0][(byte)x[6]] ^ T[1][(byte)(x[5] >> 8)] ^ T[2][(byte)(x[4] >> 16)] ^ T[3][(byte)(x[3] >> 24)] ^ + T[4][(byte)(x[2] >> 32)] ^ T[5][(byte)(x[1] >> 40)] ^ T[6][(byte)(x[0] >> 48)] ^ T[7][(byte)(x[7] >> 56)]; + y[7] = T[0][(byte)x[7]] ^ T[1][(byte)(x[6] >> 8)] ^ T[2][(byte)(x[5] >> 16)] ^ T[3][(byte)(x[4] >> 24)] ^ + T[4][(byte)(x[3] >> 32)] ^ T[5][(byte)(x[2] >> 40)] ^ T[6][(byte)(x[1] >> 48)] ^ T[7][(byte)(x[0] >> 56)]; +} + +inline void GL128(const word64 x[2], word64 y[2], const word64 k[2]) +{ + y[0] = k[0] + (T[0][(byte)x[0]] ^ T[1][(byte)(x[0] >> 8)] ^ T[2][(byte)(x[0] >> 16)] ^ T[3][(byte)(x[0] >> 24)] ^ + T[4][(byte)(x[1] >> 32)] ^ T[5][(byte)(x[1] >> 40)] ^ T[6][(byte)(x[1] >> 48)] ^ T[7][(byte)(x[1] >> 56)]); + y[1] = k[1] + (T[0][(byte)x[1]] ^ T[1][(byte)(x[1] >> 8)] ^ T[2][(byte)(x[1] >> 16)] ^ T[3][(byte)(x[1] >> 24)] ^ + T[4][(byte)(x[0] >> 32)] ^ T[5][(byte)(x[0] >> 40)] ^ T[6][(byte)(x[0] >> 48)] ^ T[7][(byte)(x[0] >> 56)]); +} + +inline void GL256(const word64 x[4], word64 y[4], const word64 k[4]) +{ + y[0] = k[0] + (T[0][(byte)x[0]] ^ T[1][(byte)(x[0] >> 8)] ^ T[2][(byte)(x[3] >> 16)] ^ T[3][(byte)(x[3] >> 24)] ^ + T[4][(byte)(x[2] >> 32)] ^ T[5][(byte)(x[2] >> 40)] ^ T[6][(byte)(x[1] >> 48)] ^ T[7][(byte)(x[1] >> 56)]); + y[1] = k[1] + (T[0][(byte)x[1]] ^ T[1][(byte)(x[1] >> 8)] ^ T[2][(byte)(x[0] >> 16)] ^ T[3][(byte)(x[0] >> 24)] ^ + T[4][(byte)(x[3] >> 32)] ^ T[5][(byte)(x[3] >> 40)] ^ T[6][(byte)(x[2] >> 48)] ^ T[7][(byte)(x[2] >> 56)]); + y[2] = k[2] + (T[0][(byte)x[2]] ^ T[1][(byte)(x[2] >> 8)] ^ T[2][(byte)(x[1] >> 16)] ^ T[3][(byte)(x[1] >> 24)] ^ + T[4][(byte)(x[0] >> 32)] ^ T[5][(byte)(x[0] >> 40)] ^ T[6][(byte)(x[3] >> 48)] ^ T[7][(byte)(x[3] >> 56)]); + y[3] = k[3] + (T[0][(byte)x[3]] ^ T[1][(byte)(x[3] >> 8)] ^ T[2][(byte)(x[2] >> 16)] ^ T[3][(byte)(x[2] >> 24)] ^ + T[4][(byte)(x[1] >> 32)] ^ T[5][(byte)(x[1] >> 40)] ^ T[6][(byte)(x[0] >> 48)] ^ T[7][(byte)(x[0] >> 56)]); +} + +inline void GL512(const word64 x[8], word64 y[8], const word64 k[8]) +{ + y[0] = k[0] + (T[0][(byte)x[0]] ^ T[1][(byte)(x[7] >> 8)] ^ T[2][(byte)(x[6] >> 16)] ^ T[3][(byte)(x[5] >> 24)] ^ + T[4][(byte)(x[4] >> 32)] ^ T[5][(byte)(x[3] >> 40)] ^ T[6][(byte)(x[2] >> 48)] ^ T[7][(byte)(x[1] >> 56)]); + y[1] = k[1] + (T[0][(byte)x[1]] ^ T[1][(byte)(x[0] >> 8)] ^ T[2][(byte)(x[7] >> 16)] ^ T[3][(byte)(x[6] >> 24)] ^ + T[4][(byte)(x[5] >> 32)] ^ T[5][(byte)(x[4] >> 40)] ^ T[6][(byte)(x[3] >> 48)] ^ T[7][(byte)(x[2] >> 56)]); + y[2] = k[2] + (T[0][(byte)x[2]] ^ T[1][(byte)(x[1] >> 8)] ^ T[2][(byte)(x[0] >> 16)] ^ T[3][(byte)(x[7] >> 24)] ^ + T[4][(byte)(x[6] >> 32)] ^ T[5][(byte)(x[5] >> 40)] ^ T[6][(byte)(x[4] >> 48)] ^ T[7][(byte)(x[3] >> 56)]); + y[3] = k[3] + (T[0][(byte)x[3]] ^ T[1][(byte)(x[2] >> 8)] ^ T[2][(byte)(x[1] >> 16)] ^ T[3][(byte)(x[0] >> 24)] ^ + T[4][(byte)(x[7] >> 32)] ^ T[5][(byte)(x[6] >> 40)] ^ T[6][(byte)(x[5] >> 48)] ^ T[7][(byte)(x[4] >> 56)]); + y[4] = k[4] + (T[0][(byte)x[4]] ^ T[1][(byte)(x[3] >> 8)] ^ T[2][(byte)(x[2] >> 16)] ^ T[3][(byte)(x[1] >> 24)] ^ + T[4][(byte)(x[0] >> 32)] ^ T[5][(byte)(x[7] >> 40)] ^ T[6][(byte)(x[6] >> 48)] ^ T[7][(byte)(x[5] >> 56)]); + y[5] = k[5] + (T[0][(byte)x[5]] ^ T[1][(byte)(x[4] >> 8)] ^ T[2][(byte)(x[3] >> 16)] ^ T[3][(byte)(x[2] >> 24)] ^ + T[4][(byte)(x[1] >> 32)] ^ T[5][(byte)(x[0] >> 40)] ^ T[6][(byte)(x[7] >> 48)] ^ T[7][(byte)(x[6] >> 56)]); + y[6] = k[6] + (T[0][(byte)x[6]] ^ T[1][(byte)(x[5] >> 8)] ^ T[2][(byte)(x[4] >> 16)] ^ T[3][(byte)(x[3] >> 24)] ^ + T[4][(byte)(x[2] >> 32)] ^ T[5][(byte)(x[1] >> 40)] ^ T[6][(byte)(x[0] >> 48)] ^ T[7][(byte)(x[7] >> 56)]); + y[7] = k[7] + (T[0][(byte)x[7]] ^ T[1][(byte)(x[6] >> 8)] ^ T[2][(byte)(x[5] >> 16)] ^ T[3][(byte)(x[4] >> 24)] ^ + T[4][(byte)(x[3] >> 32)] ^ T[5][(byte)(x[2] >> 40)] ^ T[6][(byte)(x[1] >> 48)] ^ T[7][(byte)(x[0] >> 56)]); +} + +inline void IMC128(word64 x[2]) +{ + x[0] = IT[0][S[0][(byte)x[0]]] ^ IT[1][S[1][(byte)(x[0] >> 8)]] ^ IT[2][S[2][(byte)(x[0] >> 16)]] ^ IT[3][S[3][(byte)(x[0] >> 24)]] ^ + IT[4][S[0][(byte)(x[0] >> 32)]] ^ IT[5][S[1][(byte)(x[0] >> 40)]] ^ IT[6][S[2][(byte)(x[0] >> 48)]] ^ IT[7][S[3][(byte)(x[0] >> 56)]]; + x[1] = IT[0][S[0][(byte)x[1]]] ^ IT[1][S[1][(byte)(x[1] >> 8)]] ^ IT[2][S[2][(byte)(x[1] >> 16)]] ^ IT[3][S[3][(byte)(x[1] >> 24)]] ^ + IT[4][S[0][(byte)(x[1] >> 32)]] ^ IT[5][S[1][(byte)(x[1] >> 40)]] ^ IT[6][S[2][(byte)(x[1] >> 48)]] ^ IT[7][S[3][(byte)(x[1] >> 56)]]; +} + +inline void IMC256(word64 x[4]) +{ + x[0] = IT[0][S[0][(byte)x[0]]] ^ IT[1][S[1][(byte)(x[0] >> 8)]] ^ IT[2][S[2][(byte)(x[0] >> 16)]] ^ IT[3][S[3][(byte)(x[0] >> 24)]] ^ + IT[4][S[0][(byte)(x[0] >> 32)]] ^ IT[5][S[1][(byte)(x[0] >> 40)]] ^ IT[6][S[2][(byte)(x[0] >> 48)]] ^ IT[7][S[3][(byte)(x[0] >> 56)]]; + x[1] = IT[0][S[0][(byte)x[1]]] ^ IT[1][S[1][(byte)(x[1] >> 8)]] ^ IT[2][S[2][(byte)(x[1] >> 16)]] ^ IT[3][S[3][(byte)(x[1] >> 24)]] ^ + IT[4][S[0][(byte)(x[1] >> 32)]] ^ IT[5][S[1][(byte)(x[1] >> 40)]] ^ IT[6][S[2][(byte)(x[1] >> 48)]] ^ IT[7][S[3][(byte)(x[1] >> 56)]]; + x[2] = IT[0][S[0][(byte)x[2]]] ^ IT[1][S[1][(byte)(x[2] >> 8)]] ^ IT[2][S[2][(byte)(x[2] >> 16)]] ^ IT[3][S[3][(byte)(x[2] >> 24)]] ^ + IT[4][S[0][(byte)(x[2] >> 32)]] ^ IT[5][S[1][(byte)(x[2] >> 40)]] ^ IT[6][S[2][(byte)(x[2] >> 48)]] ^ IT[7][S[3][(byte)(x[2] >> 56)]]; + x[3] = IT[0][S[0][(byte)x[3]]] ^ IT[1][S[1][(byte)(x[3] >> 8)]] ^ IT[2][S[2][(byte)(x[3] >> 16)]] ^ IT[3][S[3][(byte)(x[3] >> 24)]] ^ + IT[4][S[0][(byte)(x[3] >> 32)]] ^ IT[5][S[1][(byte)(x[3] >> 40)]] ^ IT[6][S[2][(byte)(x[3] >> 48)]] ^ IT[7][S[3][(byte)(x[3] >> 56)]]; +} + +inline void IMC512(word64 x[8]) +{ + x[0] = IT[0][S[0][(byte)x[0]]] ^ IT[1][S[1][(byte)(x[0] >> 8)]] ^ IT[2][S[2][(byte)(x[0] >> 16)]] ^ IT[3][S[3][(byte)(x[0] >> 24)]] ^ + IT[4][S[0][(byte)(x[0] >> 32)]] ^ IT[5][S[1][(byte)(x[0] >> 40)]] ^ IT[6][S[2][(byte)(x[0] >> 48)]] ^ IT[7][S[3][(byte)(x[0] >> 56)]]; + x[1] = IT[0][S[0][(byte)x[1]]] ^ IT[1][S[1][(byte)(x[1] >> 8)]] ^ IT[2][S[2][(byte)(x[1] >> 16)]] ^ IT[3][S[3][(byte)(x[1] >> 24)]] ^ + IT[4][S[0][(byte)(x[1] >> 32)]] ^ IT[5][S[1][(byte)(x[1] >> 40)]] ^ IT[6][S[2][(byte)(x[1] >> 48)]] ^ IT[7][S[3][(byte)(x[1] >> 56)]]; + x[2] = IT[0][S[0][(byte)x[2]]] ^ IT[1][S[1][(byte)(x[2] >> 8)]] ^ IT[2][S[2][(byte)(x[2] >> 16)]] ^ IT[3][S[3][(byte)(x[2] >> 24)]] ^ + IT[4][S[0][(byte)(x[2] >> 32)]] ^ IT[5][S[1][(byte)(x[2] >> 40)]] ^ IT[6][S[2][(byte)(x[2] >> 48)]] ^ IT[7][S[3][(byte)(x[2] >> 56)]]; + x[3] = IT[0][S[0][(byte)x[3]]] ^ IT[1][S[1][(byte)(x[3] >> 8)]] ^ IT[2][S[2][(byte)(x[3] >> 16)]] ^ IT[3][S[3][(byte)(x[3] >> 24)]] ^ + IT[4][S[0][(byte)(x[3] >> 32)]] ^ IT[5][S[1][(byte)(x[3] >> 40)]] ^ IT[6][S[2][(byte)(x[3] >> 48)]] ^ IT[7][S[3][(byte)(x[3] >> 56)]]; + x[4] = IT[0][S[0][(byte)x[4]]] ^ IT[1][S[1][(byte)(x[4] >> 8)]] ^ IT[2][S[2][(byte)(x[4] >> 16)]] ^ IT[3][S[3][(byte)(x[4] >> 24)]] ^ + IT[4][S[0][(byte)(x[4] >> 32)]] ^ IT[5][S[1][(byte)(x[4] >> 40)]] ^ IT[6][S[2][(byte)(x[4] >> 48)]] ^ IT[7][S[3][(byte)(x[4] >> 56)]]; + x[5] = IT[0][S[0][(byte)x[5]]] ^ IT[1][S[1][(byte)(x[5] >> 8)]] ^ IT[2][S[2][(byte)(x[5] >> 16)]] ^ IT[3][S[3][(byte)(x[5] >> 24)]] ^ + IT[4][S[0][(byte)(x[5] >> 32)]] ^ IT[5][S[1][(byte)(x[5] >> 40)]] ^ IT[6][S[2][(byte)(x[5] >> 48)]] ^ IT[7][S[3][(byte)(x[5] >> 56)]]; + x[6] = IT[0][S[0][(byte)x[6]]] ^ IT[1][S[1][(byte)(x[6] >> 8)]] ^ IT[2][S[2][(byte)(x[6] >> 16)]] ^ IT[3][S[3][(byte)(x[6] >> 24)]] ^ + IT[4][S[0][(byte)(x[6] >> 32)]] ^ IT[5][S[1][(byte)(x[6] >> 40)]] ^ IT[6][S[2][(byte)(x[6] >> 48)]] ^ IT[7][S[3][(byte)(x[6] >> 56)]]; + x[7] = IT[0][S[0][(byte)x[7]]] ^ IT[1][S[1][(byte)(x[7] >> 8)]] ^ IT[2][S[2][(byte)(x[7] >> 16)]] ^ IT[3][S[3][(byte)(x[7] >> 24)]] ^ + IT[4][S[0][(byte)(x[7] >> 32)]] ^ IT[5][S[1][(byte)(x[7] >> 40)]] ^ IT[6][S[2][(byte)(x[7] >> 48)]] ^ IT[7][S[3][(byte)(x[7] >> 56)]]; +} + +inline void IG128(const word64 x[2], word64 y[2], const word64 k[2]) +{ + y[0] = k[0] ^ IT[0][(byte)x[0]] ^ IT[1][(byte)(x[0] >> 8)] ^ IT[2][(byte)(x[0] >> 16)] ^ IT[3][(byte)(x[0] >> 24)] ^ + IT[4][(byte)(x[1] >> 32)] ^ IT[5][(byte)(x[1] >> 40)] ^ IT[6][(byte)(x[1] >> 48)] ^ IT[7][(byte)(x[1] >> 56)]; + y[1] = k[1] ^ IT[0][(byte)x[1]] ^ IT[1][(byte)(x[1] >> 8)] ^ IT[2][(byte)(x[1] >> 16)] ^ IT[3][(byte)(x[1] >> 24)] ^ + IT[4][(byte)(x[0] >> 32)] ^ IT[5][(byte)(x[0] >> 40)] ^ IT[6][(byte)(x[0] >> 48)] ^ IT[7][(byte)(x[0] >> 56)]; +} + +inline void IG256(const word64 x[4], word64 y[4], const word64 k[4]) +{ + y[0] = k[0] ^ IT[0][(byte)x[0]] ^ IT[1][(byte)(x[0] >> 8)] ^ IT[2][(byte)(x[1] >> 16)] ^ IT[3][(byte)(x[1] >> 24)] ^ + IT[4][(byte)(x[2] >> 32)] ^ IT[5][(byte)(x[2] >> 40)] ^ IT[6][(byte)(x[3] >> 48)] ^ IT[7][(byte)(x[3] >> 56)]; + y[1] = k[1] ^ IT[0][(byte)x[1]] ^ IT[1][(byte)(x[1] >> 8)] ^ IT[2][(byte)(x[2] >> 16)] ^ IT[3][(byte)(x[2] >> 24)] ^ + IT[4][(byte)(x[3] >> 32)] ^ IT[5][(byte)(x[3] >> 40)] ^ IT[6][(byte)(x[0] >> 48)] ^ IT[7][(byte)(x[0] >> 56)]; + y[2] = k[2] ^ IT[0][(byte)x[2]] ^ IT[1][(byte)(x[2] >> 8)] ^ IT[2][(byte)(x[3] >> 16)] ^ IT[3][(byte)(x[3] >> 24)] ^ + IT[4][(byte)(x[0] >> 32)] ^ IT[5][(byte)(x[0] >> 40)] ^ IT[6][(byte)(x[1] >> 48)] ^ IT[7][(byte)(x[1] >> 56)]; + y[3] = k[3] ^ IT[0][(byte)x[3]] ^ IT[1][(byte)(x[3] >> 8)] ^ IT[2][(byte)(x[0] >> 16)] ^ IT[3][(byte)(x[0] >> 24)] ^ + IT[4][(byte)(x[1] >> 32)] ^ IT[5][(byte)(x[1] >> 40)] ^ IT[6][(byte)(x[2] >> 48)] ^ IT[7][(byte)(x[2] >> 56)]; +} + +inline void IG512(const word64 x[8], word64 y[8], const word64 k[8]) +{ + y[0] = k[0] ^ IT[0][(byte)x[0]] ^ IT[1][(byte)(x[1] >> 8)] ^ IT[2][(byte)(x[2] >> 16)] ^ IT[3][(byte)(x[3] >> 24)] ^ + IT[4][(byte)(x[4] >> 32)] ^ IT[5][(byte)(x[5] >> 40)] ^ IT[6][(byte)(x[6] >> 48)] ^ IT[7][(byte)(x[7] >> 56)]; + y[1] = k[1] ^ IT[0][(byte)x[1]] ^ IT[1][(byte)(x[2] >> 8)] ^ IT[2][(byte)(x[3] >> 16)] ^ IT[3][(byte)(x[4] >> 24)] ^ + IT[4][(byte)(x[5] >> 32)] ^ IT[5][(byte)(x[6] >> 40)] ^ IT[6][(byte)(x[7] >> 48)] ^ IT[7][(byte)(x[0] >> 56)]; + y[2] = k[2] ^ IT[0][(byte)x[2]] ^ IT[1][(byte)(x[3] >> 8)] ^ IT[2][(byte)(x[4] >> 16)] ^ IT[3][(byte)(x[5] >> 24)] ^ + IT[4][(byte)(x[6] >> 32)] ^ IT[5][(byte)(x[7] >> 40)] ^ IT[6][(byte)(x[0] >> 48)] ^ IT[7][(byte)(x[1] >> 56)]; + y[3] = k[3] ^ IT[0][(byte)x[3]] ^ IT[1][(byte)(x[4] >> 8)] ^ IT[2][(byte)(x[5] >> 16)] ^ IT[3][(byte)(x[6] >> 24)] ^ + IT[4][(byte)(x[7] >> 32)] ^ IT[5][(byte)(x[0] >> 40)] ^ IT[6][(byte)(x[1] >> 48)] ^ IT[7][(byte)(x[2] >> 56)]; + y[4] = k[4] ^ IT[0][(byte)x[4]] ^ IT[1][(byte)(x[5] >> 8)] ^ IT[2][(byte)(x[6] >> 16)] ^ IT[3][(byte)(x[7] >> 24)] ^ + IT[4][(byte)(x[0] >> 32)] ^ IT[5][(byte)(x[1] >> 40)] ^ IT[6][(byte)(x[2] >> 48)] ^ IT[7][(byte)(x[3] >> 56)]; + y[5] = k[5] ^ IT[0][(byte)x[5]] ^ IT[1][(byte)(x[6] >> 8)] ^ IT[2][(byte)(x[7] >> 16)] ^ IT[3][(byte)(x[0] >> 24)] ^ + IT[4][(byte)(x[1] >> 32)] ^ IT[5][(byte)(x[2] >> 40)] ^ IT[6][(byte)(x[3] >> 48)] ^ IT[7][(byte)(x[4] >> 56)]; + y[6] = k[6] ^ IT[0][(byte)x[6]] ^ IT[1][(byte)(x[7] >> 8)] ^ IT[2][(byte)(x[0] >> 16)] ^ IT[3][(byte)(x[1] >> 24)] ^ + IT[4][(byte)(x[2] >> 32)] ^ IT[5][(byte)(x[3] >> 40)] ^ IT[6][(byte)(x[4] >> 48)] ^ IT[7][(byte)(x[5] >> 56)]; + y[7] = k[7] ^ IT[0][(byte)x[7]] ^ IT[1][(byte)(x[0] >> 8)] ^ IT[2][(byte)(x[1] >> 16)] ^ IT[3][(byte)(x[2] >> 24)] ^ + IT[4][(byte)(x[3] >> 32)] ^ IT[5][(byte)(x[4] >> 40)] ^ IT[6][(byte)(x[5] >> 48)] ^ IT[7][(byte)(x[6] >> 56)]; +} + +inline void IGL128(const word64 x[2], word64 y[2], const word64 k[2]) +{ + y[0] = (word64(IS[0][(byte)x[0]]) ^ word64(IS[1][(byte)(x[0] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[0] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[0] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[1] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[1] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[1] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[1] >> 56)]) << 56) - k[0]; + y[1] = (word64(IS[0][(byte)x[1]]) ^ word64(IS[1][(byte)(x[1] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[1] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[1] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[0] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[0] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[0] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[0] >> 56)]) << 56) - k[1]; +} + +inline void IGL256(const word64 x[4], word64 y[4], const word64 k[4]) +{ + y[0] = (word64(IS[0][(byte)x[0]]) ^ word64(IS[1][(byte)(x[0] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[1] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[1] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[2] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[2] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[3] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[3] >> 56)]) << 56) - k[0]; + y[1] = (word64(IS[0][(byte)x[1]]) ^ word64(IS[1][(byte)(x[1] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[2] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[2] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[3] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[3] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[0] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[0] >> 56)]) << 56) - k[1]; + y[2] = (word64(IS[0][(byte)x[2]]) ^ word64(IS[1][(byte)(x[2] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[3] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[3] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[0] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[0] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[1] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[1] >> 56)]) << 56) - k[2]; + y[3] = (word64(IS[0][(byte)x[3]]) ^ word64(IS[1][(byte)(x[3] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[0] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[0] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[1] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[1] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[2] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[2] >> 56)]) << 56) - k[3]; +} + +inline void IGL512(const word64 x[8], word64 y[8], const word64 k[8]) +{ + y[0] = (word64(IS[0][(byte)x[0]]) ^ word64(IS[1][(byte)(x[1] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[2] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[3] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[4] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[5] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[6] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[7] >> 56)]) << 56) - k[0]; + y[1] = (word64(IS[0][(byte)x[1]]) ^ word64(IS[1][(byte)(x[2] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[3] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[4] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[5] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[6] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[7] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[0] >> 56)]) << 56) - k[1]; + y[2] = (word64(IS[0][(byte)x[2]]) ^ word64(IS[1][(byte)(x[3] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[4] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[5] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[6] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[7] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[0] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[1] >> 56)]) << 56) - k[2]; + y[3] = (word64(IS[0][(byte)x[3]]) ^ word64(IS[1][(byte)(x[4] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[5] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[6] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[7] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[0] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[1] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[2] >> 56)]) << 56) - k[3]; + y[4] = (word64(IS[0][(byte)x[4]]) ^ word64(IS[1][(byte)(x[5] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[6] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[7] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[0] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[1] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[2] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[3] >> 56)]) << 56) - k[4]; + y[5] = (word64(IS[0][(byte)x[5]]) ^ word64(IS[1][(byte)(x[6] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[7] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[0] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[1] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[2] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[3] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[4] >> 56)]) << 56) - k[5]; + y[6] = (word64(IS[0][(byte)x[6]]) ^ word64(IS[1][(byte)(x[7] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[0] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[1] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[2] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[3] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[4] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[5] >> 56)]) << 56) - k[6]; + y[7] = (word64(IS[0][(byte)x[7]]) ^ word64(IS[1][(byte)(x[0] >> 8)]) << 8 ^ word64(IS[2][(byte)(x[1] >> 16)]) << 16 ^ word64(IS[3][(byte)(x[2] >> 24)]) << 24 ^ + word64(IS[0][(byte)(x[3] >> 32)]) << 32 ^ word64(IS[1][(byte)(x[4] >> 40)]) << 40 ^ word64(IS[2][(byte)(x[5] >> 48)]) << 48 ^ word64(IS[3][(byte)(x[6] >> 56)]) << 56) - k[7]; +} + +inline void G128(const word64 x[2], word64 y[2], const word64 k[2]) +{ + y[0] = k[0] ^ T[0][(byte)x[0]] ^ T[1][(byte)(x[0] >> 8)] ^ T[2][(byte)(x[0] >> 16)] ^ T[3][(byte)(x[0] >> 24)] ^ + T[4][(byte)(x[1] >> 32)] ^ T[5][(byte)(x[1] >> 40)] ^ T[6][(byte)(x[1] >> 48)] ^ T[7][(byte)(x[1] >> 56)]; + y[1] = k[1] ^ T[0][(byte)x[1]] ^ T[1][(byte)(x[1] >> 8)] ^ T[2][(byte)(x[1] >> 16)] ^ T[3][(byte)(x[1] >> 24)] ^ + T[4][(byte)(x[0] >> 32)] ^ T[5][(byte)(x[0] >> 40)] ^ T[6][(byte)(x[0] >> 48)] ^ T[7][(byte)(x[0] >> 56)]; +} + +inline void G256(const word64 x[4], word64 y[4], const word64 k[4]) +{ + y[0] = k[0] ^ T[0][(byte)x[0]] ^ T[1][(byte)(x[0] >> 8)] ^ T[2][(byte)(x[3] >> 16)] ^ T[3][(byte)(x[3] >> 24)] ^ + T[4][(byte)(x[2] >> 32)] ^ T[5][(byte)(x[2] >> 40)] ^ T[6][(byte)(x[1] >> 48)] ^ T[7][(byte)(x[1] >> 56)]; + y[1] = k[1] ^ T[0][(byte)x[1]] ^ T[1][(byte)(x[1] >> 8)] ^ T[2][(byte)(x[0] >> 16)] ^ T[3][(byte)(x[0] >> 24)] ^ + T[4][(byte)(x[3] >> 32)] ^ T[5][(byte)(x[3] >> 40)] ^ T[6][(byte)(x[2] >> 48)] ^ T[7][(byte)(x[2] >> 56)]; + y[2] = k[2] ^ T[0][(byte)x[2]] ^ T[1][(byte)(x[2] >> 8)] ^ T[2][(byte)(x[1] >> 16)] ^ T[3][(byte)(x[1] >> 24)] ^ + T[4][(byte)(x[0] >> 32)] ^ T[5][(byte)(x[0] >> 40)] ^ T[6][(byte)(x[3] >> 48)] ^ T[7][(byte)(x[3] >> 56)]; + y[3] = k[3] ^ T[0][(byte)x[3]] ^ T[1][(byte)(x[3] >> 8)] ^ T[2][(byte)(x[2] >> 16)] ^ T[3][(byte)(x[2] >> 24)] ^ + T[4][(byte)(x[1] >> 32)] ^ T[5][(byte)(x[1] >> 40)] ^ T[6][(byte)(x[0] >> 48)] ^ T[7][(byte)(x[0] >> 56)]; +} + +inline void G512(const word64 x[8], word64 y[8], const word64 k[8]) +{ + y[0] = k[0] ^ T[0][(byte)x[0]] ^ T[1][(byte)(x[7] >> 8)] ^ T[2][(byte)(x[6] >> 16)] ^ T[3][(byte)(x[5] >> 24)] ^ + T[4][(byte)(x[4] >> 32)] ^ T[5][(byte)(x[3] >> 40)] ^ T[6][(byte)(x[2] >> 48)] ^ T[7][(byte)(x[1] >> 56)]; + y[1] = k[1] ^ T[0][(byte)x[1]] ^ T[1][(byte)(x[0] >> 8)] ^ T[2][(byte)(x[7] >> 16)] ^ T[3][(byte)(x[6] >> 24)] ^ + T[4][(byte)(x[5] >> 32)] ^ T[5][(byte)(x[4] >> 40)] ^ T[6][(byte)(x[3] >> 48)] ^ T[7][(byte)(x[2] >> 56)]; + y[2] = k[2] ^ T[0][(byte)x[2]] ^ T[1][(byte)(x[1] >> 8)] ^ T[2][(byte)(x[0] >> 16)] ^ T[3][(byte)(x[7] >> 24)] ^ + T[4][(byte)(x[6] >> 32)] ^ T[5][(byte)(x[5] >> 40)] ^ T[6][(byte)(x[4] >> 48)] ^ T[7][(byte)(x[3] >> 56)]; + y[3] = k[3] ^ T[0][(byte)x[3]] ^ T[1][(byte)(x[2] >> 8)] ^ T[2][(byte)(x[1] >> 16)] ^ T[3][(byte)(x[0] >> 24)] ^ + T[4][(byte)(x[7] >> 32)] ^ T[5][(byte)(x[6] >> 40)] ^ T[6][(byte)(x[5] >> 48)] ^ T[7][(byte)(x[4] >> 56)]; + y[4] = k[4] ^ T[0][(byte)x[4]] ^ T[1][(byte)(x[3] >> 8)] ^ T[2][(byte)(x[2] >> 16)] ^ T[3][(byte)(x[1] >> 24)] ^ + T[4][(byte)(x[0] >> 32)] ^ T[5][(byte)(x[7] >> 40)] ^ T[6][(byte)(x[6] >> 48)] ^ T[7][(byte)(x[5] >> 56)]; + y[5] = k[5] ^ T[0][(byte)x[5]] ^ T[1][(byte)(x[4] >> 8)] ^ T[2][(byte)(x[3] >> 16)] ^ T[3][(byte)(x[2] >> 24)] ^ + T[4][(byte)(x[1] >> 32)] ^ T[5][(byte)(x[0] >> 40)] ^ T[6][(byte)(x[7] >> 48)] ^ T[7][(byte)(x[6] >> 56)]; + y[6] = k[6] ^ T[0][(byte)x[6]] ^ T[1][(byte)(x[5] >> 8)] ^ T[2][(byte)(x[4] >> 16)] ^ T[3][(byte)(x[3] >> 24)] ^ + T[4][(byte)(x[2] >> 32)] ^ T[5][(byte)(x[1] >> 40)] ^ T[6][(byte)(x[0] >> 48)] ^ T[7][(byte)(x[7] >> 56)]; + y[7] = k[7] ^ T[0][(byte)x[7]] ^ T[1][(byte)(x[6] >> 8)] ^ T[2][(byte)(x[5] >> 16)] ^ T[3][(byte)(x[4] >> 24)] ^ + T[4][(byte)(x[3] >> 32)] ^ T[5][(byte)(x[2] >> 40)] ^ T[6][(byte)(x[1] >> 48)] ^ T[7][(byte)(x[0] >> 56)]; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +// *********************** UncheckedSetKey specializations *********************** // + +void Kalyna128::Base::SetKey_22(const word64 key[2]) +{ + word64 *ks = m_wspace+0, *ksc = m_wspace+2, *t1 = m_wspace+4; + word64 *t2 = m_wspace+6, *k = m_wspace+8, *kswapped = m_wspace+10; + + memset(t1, 0, 2*8); + t1[0] = (128 + 128 + 64) / 64; + + AddKey<2>(t1, t2, key); + G128(t2, t1, key); + GL128(t1, t2, key); + G0128(t2, ks); + + word64 constant = W64LIT(0x0001000100010001); + + // round 0 + memcpy(k, key, 16); + kswapped[1] = k[0]; + kswapped[0] = k[1]; + + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[0], ksc); + MakeOddKey<2>(&m_rkeys[0], &m_rkeys[2]); + + // round 2 + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(kswapped, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[4], ksc); + MakeOddKey<2>(&m_rkeys[4], &m_rkeys[6]); + + // round 4 + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[8], ksc); + MakeOddKey<2>(&m_rkeys[8], &m_rkeys[10]); + + // round 6 + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(kswapped, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[12], ksc); + MakeOddKey<2>(&m_rkeys[12], &m_rkeys[14]); + + // round 8 + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[16], ksc); + MakeOddKey<2>(&m_rkeys[16], &m_rkeys[18]); + + // round 10 + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(kswapped, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[20], ksc); + + if (!IsForwardTransformation()) + { + IMC128(&m_rkeys[18]); IMC128(&m_rkeys[16]); + IMC128(&m_rkeys[14]); IMC128(&m_rkeys[12]); + IMC128(&m_rkeys[10]); IMC128(&m_rkeys[ 8]); + IMC128(&m_rkeys[ 6]); IMC128(&m_rkeys[ 4]); + IMC128(&m_rkeys[ 2]); + } +} + +void Kalyna128::Base::SetKey_24(const word64 key[4]) +{ + word64 *ks = m_wspace+0, *ksc = m_wspace+2, *t1 = m_wspace+4, *t2 = m_wspace+6; + word64 *k = m_wspace+8, *ka = m_wspace+12, *ko = m_wspace+14; + + memset(t1, 0, 2*8); + t1[0] = (128 + 256 + 64) / 64; + memcpy(ka, key, 16); + memcpy(ko, key + 2, 16); + + AddKey<2>(t1, t2, ka); + G128(t2, t1, ko); + GL128(t1, t2, ka); + G0128(t2, ks); + + word64 constant = W64LIT(0x0001000100010001); + + // round 0 + memcpy(k, key, 256 / 8); + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[0], ksc); + MakeOddKey<2>(&m_rkeys[0], &m_rkeys[2]); + + // round 2 + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k + 2, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[4], ksc); + MakeOddKey<2>(&m_rkeys[4], &m_rkeys[6]); + + // round 4 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[8], ksc); + MakeOddKey<2>(&m_rkeys[8], &m_rkeys[10]); + + // round 6 + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k + 2, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[12], ksc); + MakeOddKey<2>(&m_rkeys[12], &m_rkeys[14]); + + // round 8 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[16], ksc); + MakeOddKey<2>(&m_rkeys[16], &m_rkeys[18]); + + // round 10 + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k + 2, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[20], ksc); + MakeOddKey<2>(&m_rkeys[20], &m_rkeys[22]); + + // round 12 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[24], ksc); + MakeOddKey<2>(&m_rkeys[24], &m_rkeys[26]); + + // round 14 + constant <<= 1; + AddConstant<2>(ks, ksc, constant); + AddKey<2>(k + 2, t2, ksc); + G128(t2, t1, ksc); + GL128(t1, &m_rkeys[28], ksc); + + if (!IsForwardTransformation()) + { + IMC128(&m_rkeys[26]); + IMC128(&m_rkeys[24]); + IMC128(&m_rkeys[22]); + IMC128(&m_rkeys[20]); + IMC128(&m_rkeys[18]); + IMC128(&m_rkeys[16]); + IMC128(&m_rkeys[14]); + IMC128(&m_rkeys[12]); + IMC128(&m_rkeys[10]); + IMC128(&m_rkeys[8]); + IMC128(&m_rkeys[6]); + IMC128(&m_rkeys[4]); + IMC128(&m_rkeys[2]); + } +} + +void Kalyna256::Base::SetKey_44(const word64 key[4]) +{ + word64 *ks = m_wspace+0, *ksc = m_wspace+4, *t1 = m_wspace+8; + word64 *t2 = m_wspace+12, *k = m_wspace+16; + + memset(t1, 0, 32); + t1[0] = (256 + 256 + 64) / 64; + + AddKey<4>(t1, t2, key); + G256(t2, t1, key); + GL256(t1, t2, key); + G0256(t2, ks); + + word64 constant = W64LIT(0x0001000100010001); + + // round 0 + memcpy(k, key, 32); + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[0], ksc); + MakeOddKey<4>(&m_rkeys[0], &m_rkeys[4]); + + // round 2 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[8], ksc); + MakeOddKey<4>(&m_rkeys[8], &m_rkeys[12]); + + // round 4 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[16], ksc); + MakeOddKey<4>(&m_rkeys[16], &m_rkeys[20]); + + // round 6 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[24], ksc); + MakeOddKey<4>(&m_rkeys[24], &m_rkeys[28]); + + // round 8 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[32], ksc); + MakeOddKey<4>(&m_rkeys[32], &m_rkeys[36]); + + // round 10 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[40], ksc); + MakeOddKey<4>(&m_rkeys[40], &m_rkeys[44]); + + // round 12 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[48], ksc); + MakeOddKey<4>(&m_rkeys[48], &m_rkeys[52]); + + // round 14 + SwapBlocks<4>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[56], ksc); + + if (!IsForwardTransformation()) + { + IMC256(&m_rkeys[52]); + IMC256(&m_rkeys[48]); + IMC256(&m_rkeys[44]); + IMC256(&m_rkeys[40]); + IMC256(&m_rkeys[36]); + IMC256(&m_rkeys[32]); + IMC256(&m_rkeys[28]); + IMC256(&m_rkeys[24]); + IMC256(&m_rkeys[20]); + IMC256(&m_rkeys[16]); + IMC256(&m_rkeys[12]); + IMC256(&m_rkeys[8]); + IMC256(&m_rkeys[4]); + } +} + +void Kalyna256::Base::SetKey_48(const word64 key[8]) +{ + word64 *ks = m_wspace+0, *ksc = m_wspace+4, *t1 = m_wspace+8, *t2 = m_wspace+12; + word64 *k = m_wspace+16, *ka = m_wspace+24, *ko = m_wspace+28; + + memset(t1, 0, 4*8); + t1[0] = (512 + 256 + 64) / 64; + memcpy(ka, key, 32); + memcpy(ko, key+4, 32); + + AddKey<4>(t1, t2, ka); + G256(t2, t1, ko); + GL256(t1, t2, ka); + G0256(t2, ks); + + word64 constant = W64LIT(0x0001000100010001); + + // round 0 + memcpy(k, key, 512 / 8); + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[0], ksc); + MakeOddKey<4>(&m_rkeys[0], &m_rkeys[4]); + + // round 2 + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k+4, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[8], ksc); + MakeOddKey<4>(&m_rkeys[8], &m_rkeys[12]); + + // round 4 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[16], ksc); + MakeOddKey<4>(&m_rkeys[16], &m_rkeys[20]); + + // round 6 + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k+4, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[24], ksc); + MakeOddKey<4>(&m_rkeys[24], &m_rkeys[28]); + + // round 8 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[32], ksc); + MakeOddKey<4>(&m_rkeys[32], &m_rkeys[36]); + + // round 10 + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k+4, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[40], ksc); + MakeOddKey<4>(&m_rkeys[40], &m_rkeys[44]); + + // round 12 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[48], ksc); + MakeOddKey<4>(&m_rkeys[48], &m_rkeys[52]); + + // round 14 + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k+4, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[56], ksc); + MakeOddKey<4>(&m_rkeys[56], &m_rkeys[60]); + + // round 16 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[64], ksc); + MakeOddKey<4>(&m_rkeys[64], &m_rkeys[68]); + + // round 18 + constant <<= 1; + AddConstant<4>(ks, ksc, constant); + AddKey<4>(k+4, t2, ksc); + G256(t2, t1, ksc); + GL256(t1, &m_rkeys[72], ksc); + + if (!IsForwardTransformation()) + { + IMC256(&m_rkeys[68]); + IMC256(&m_rkeys[64]); + IMC256(&m_rkeys[60]); + IMC256(&m_rkeys[56]); + IMC256(&m_rkeys[52]); + IMC256(&m_rkeys[48]); + IMC256(&m_rkeys[44]); + IMC256(&m_rkeys[40]); + IMC256(&m_rkeys[36]); + IMC256(&m_rkeys[32]); + IMC256(&m_rkeys[28]); + IMC256(&m_rkeys[24]); + IMC256(&m_rkeys[20]); + IMC256(&m_rkeys[16]); + IMC256(&m_rkeys[12]); + IMC256(&m_rkeys[8]); + IMC256(&m_rkeys[4]); + } +} + +void Kalyna512::Base::SetKey_88(const word64 key[8]) +{ + word64 *ks = m_wspace+0, *ksc = m_wspace+8, *t1 = m_wspace+16; + word64 *t2 = m_wspace+24, *k = m_wspace+32; + + memset(t1, 0, 8*8); + t1[0] = (512 + 512 + 64) / 64; + + AddKey<8>(t1, t2, key); + G512(t2, t1, key); + GL512(t1, t2, key); + G0512(t2, ks); + + word64 constant = W64LIT(0x0001000100010001); + + // round 0 + memcpy(k, key, 512 / 8); + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[0], ksc); + MakeOddKey<8>(&m_rkeys[0], &m_rkeys[8]); + + // round 2 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[16], ksc); + MakeOddKey<8>(&m_rkeys[16], &m_rkeys[24]); + + // round 4 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[32], ksc); + MakeOddKey<8>(&m_rkeys[32], &m_rkeys[40]); + + // round 6 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[48], ksc); + MakeOddKey<8>(&m_rkeys[48], &m_rkeys[56]); + + // round 8 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[64], ksc); + MakeOddKey<8>(&m_rkeys[64], &m_rkeys[72]); + + // round 10 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[80], ksc); + MakeOddKey<8>(&m_rkeys[80], &m_rkeys[88]); + + // round 12 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[96], ksc); + MakeOddKey<8>(&m_rkeys[96], &m_rkeys[104]); + + // round 14 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[112], ksc); + MakeOddKey<8>(&m_rkeys[112], &m_rkeys[120]); + + // round 16 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[128], ksc); + MakeOddKey<8>(&m_rkeys[128], &m_rkeys[136]); + + // round 18 + SwapBlocks<8>(k); + constant <<= 1; + AddConstant<8>(ks, ksc, constant); + AddKey<8>(k, t2, ksc); + G512(t2, t1, ksc); + GL512(t1, &m_rkeys[144], ksc); + + if (!IsForwardTransformation()) + { + IMC512(&m_rkeys[136]); IMC512(&m_rkeys[128]); IMC512(&m_rkeys[120]); IMC512(&m_rkeys[112]); + IMC512(&m_rkeys[104]); IMC512(&m_rkeys[ 96]); IMC512(&m_rkeys[ 88]); IMC512(&m_rkeys[ 80]); + IMC512(&m_rkeys[ 72]); IMC512(&m_rkeys[ 64]); IMC512(&m_rkeys[ 56]); IMC512(&m_rkeys[ 48]); + IMC512(&m_rkeys[ 40]); IMC512(&m_rkeys[ 32]); IMC512(&m_rkeys[ 24]); IMC512(&m_rkeys[ 16]); + IMC512(&m_rkeys[ 8]); + } +} + +// *********************** ProcessAndXorBlock specializations *********************** // + +void Kalyna128::Base::ProcessBlock_22(const byte* inBlock, const byte* xorBlock, byte* outBlock) const +{ + word64 *t1 = m_wspace+0, *t2 = m_wspace+2, *msg = m_wspace+4; + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(msg[0])(msg[1]); + + if (IsForwardTransformation()) + { + AddKey<2>(msg, t1, m_rkeys); + G128(t1, t2, &m_rkeys[2]); // 1 + G128(t2, t1, &m_rkeys[4]); // 2 + G128(t1, t2, &m_rkeys[6]); // 3 + G128(t2, t1, &m_rkeys[8]); // 4 + G128(t1, t2, &m_rkeys[10]); // 5 + G128(t2, t1, &m_rkeys[12]); // 6 + G128(t1, t2, &m_rkeys[14]); // 7 + G128(t2, t1, &m_rkeys[16]); // 8 + G128(t1, t2, &m_rkeys[18]); // 9 + GL128(t2, t1, &m_rkeys[20]); // 10 + } + else + { + SubKey<2>(msg, t1, &m_rkeys[20]); + IMC128(t1); + IG128(t1, t2, &m_rkeys[18]); + IG128(t2, t1, &m_rkeys[16]); + IG128(t1, t2, &m_rkeys[14]); + IG128(t2, t1, &m_rkeys[12]); + IG128(t1, t2, &m_rkeys[10]); + IG128(t2, t1, &m_rkeys[8]); + IG128(t1, t2, &m_rkeys[6]); + IG128(t2, t1, &m_rkeys[4]); + IG128(t1, t2, &m_rkeys[2]); + IGL128(t2, t1, &m_rkeys[0]); + } + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(t1[0])(t1[1]); +} + +void Kalyna128::Base::ProcessBlock_24(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 *t1 = m_wspace+0, *t2 = m_wspace+2, *msg = m_wspace+4; + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(msg[0])(msg[1]); + + if (IsForwardTransformation()) + { + AddKey<2>(msg, t1, m_rkeys); + G128(t1, t2, &m_rkeys[ 2]); // 1 + G128(t2, t1, &m_rkeys[ 4]); // 2 + G128(t1, t2, &m_rkeys[ 6]); // 3 + G128(t2, t1, &m_rkeys[ 8]); // 4 + G128(t1, t2, &m_rkeys[10]); // 5 + G128(t2, t1, &m_rkeys[12]); // 6 + G128(t1, t2, &m_rkeys[14]); // 7 + G128(t2, t1, &m_rkeys[16]); // 8 + G128(t1, t2, &m_rkeys[18]); // 9 + G128(t2, t1, &m_rkeys[20]); // 10 + G128(t1, t2, &m_rkeys[22]); // 11 + G128(t2, t1, &m_rkeys[24]); // 12 + G128(t1, t2, &m_rkeys[26]); // 13 + GL128(t2, t1, &m_rkeys[28]); // 14 + } + else + { + SubKey<2>(msg, t1, &m_rkeys[28]); + IMC128(t1); + IG128(t1, t2, &m_rkeys[26]); + IG128(t2, t1, &m_rkeys[24]); + IG128(t1, t2, &m_rkeys[22]); + IG128(t2, t1, &m_rkeys[20]); + IG128(t1, t2, &m_rkeys[18]); + IG128(t2, t1, &m_rkeys[16]); + IG128(t1, t2, &m_rkeys[14]); + IG128(t2, t1, &m_rkeys[12]); + IG128(t1, t2, &m_rkeys[10]); + IG128(t2, t1, &m_rkeys[8]); + IG128(t1, t2, &m_rkeys[6]); + IG128(t2, t1, &m_rkeys[4]); + IG128(t1, t2, &m_rkeys[2]); + IGL128(t2, t1, &m_rkeys[0]); + } + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(t1[0])(t1[1]); +} + +void Kalyna256::Base::ProcessBlock_44(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 *t1 = m_wspace+0, *t2 = m_wspace+4, *msg = m_wspace+8; + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(msg[0])(msg[1])(msg[2])(msg[3]); + + if (IsForwardTransformation()) + { + AddKey<4>(msg, t1, m_rkeys); + G256(t1, t2, &m_rkeys[4]); // 1 + G256(t2, t1, &m_rkeys[8]); // 2 + G256(t1, t2, &m_rkeys[12]); // 3 + G256(t2, t1, &m_rkeys[16]); // 4 + G256(t1, t2, &m_rkeys[20]); // 5 + G256(t2, t1, &m_rkeys[24]); // 6 + G256(t1, t2, &m_rkeys[28]); // 7 + G256(t2, t1, &m_rkeys[32]); // 8 + G256(t1, t2, &m_rkeys[36]); // 9 + G256(t2, t1, &m_rkeys[40]); // 10 + G256(t1, t2, &m_rkeys[44]); // 11 + G256(t2, t1, &m_rkeys[48]); // 12 + G256(t1, t2, &m_rkeys[52]); // 13 + GL256(t2, t1, &m_rkeys[56]); // 14 + } + else + { + SubKey<4>(msg, t1, &m_rkeys[56]); + IMC256(t1); + IG256(t1, t2, &m_rkeys[52]); + IG256(t2, t1, &m_rkeys[48]); + IG256(t1, t2, &m_rkeys[44]); + IG256(t2, t1, &m_rkeys[40]); + IG256(t1, t2, &m_rkeys[36]); + IG256(t2, t1, &m_rkeys[32]); + IG256(t1, t2, &m_rkeys[28]); + IG256(t2, t1, &m_rkeys[24]); + IG256(t1, t2, &m_rkeys[20]); + IG256(t2, t1, &m_rkeys[16]); + IG256(t1, t2, &m_rkeys[12]); + IG256(t2, t1, &m_rkeys[8]); + IG256(t1, t2, &m_rkeys[4]); + IGL256(t2, t1, &m_rkeys[0]); + } + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(t1[0])(t1[1])(t1[2])(t1[3]); +} + +void Kalyna256::Base::ProcessBlock_48(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 *t1 = m_wspace+0, *t2 = m_wspace+4, *msg = m_wspace+8; + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(msg[0])(msg[1])(msg[2])(msg[3]); + + if (IsForwardTransformation()) + { + AddKey<4>(msg, t1, m_rkeys); + G256(t1, t2, &m_rkeys[4]); // 1 + G256(t2, t1, &m_rkeys[8]); // 2 + G256(t1, t2, &m_rkeys[12]); // 3 + G256(t2, t1, &m_rkeys[16]); // 4 + G256(t1, t2, &m_rkeys[20]); // 5 + G256(t2, t1, &m_rkeys[24]); // 6 + G256(t1, t2, &m_rkeys[28]); // 7 + G256(t2, t1, &m_rkeys[32]); // 8 + G256(t1, t2, &m_rkeys[36]); // 9 + G256(t2, t1, &m_rkeys[40]); // 10 + G256(t1, t2, &m_rkeys[44]); // 11 + G256(t2, t1, &m_rkeys[48]); // 12 + G256(t1, t2, &m_rkeys[52]); // 13 + G256(t2, t1, &m_rkeys[56]); // 14 + G256(t1, t2, &m_rkeys[60]); // 15 + G256(t2, t1, &m_rkeys[64]); // 16 + G256(t1, t2, &m_rkeys[68]); // 17 + GL256(t2, t1, &m_rkeys[72]); // 18 + } + else + { + SubKey<4>(msg, t1, &m_rkeys[72]); + IMC256(t1); + IG256(t1, t2, &m_rkeys[68]); + IG256(t2, t1, &m_rkeys[64]); + IG256(t1, t2, &m_rkeys[60]); + IG256(t2, t1, &m_rkeys[56]); + IG256(t1, t2, &m_rkeys[52]); + IG256(t2, t1, &m_rkeys[48]); + IG256(t1, t2, &m_rkeys[44]); + IG256(t2, t1, &m_rkeys[40]); + IG256(t1, t2, &m_rkeys[36]); + IG256(t2, t1, &m_rkeys[32]); + IG256(t1, t2, &m_rkeys[28]); + IG256(t2, t1, &m_rkeys[24]); + IG256(t1, t2, &m_rkeys[20]); + IG256(t2, t1, &m_rkeys[16]); + IG256(t1, t2, &m_rkeys[12]); + IG256(t2, t1, &m_rkeys[8]); + IG256(t1, t2, &m_rkeys[4]); + IGL256(t2, t1, &m_rkeys[0]); + } + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(t1[0])(t1[1])(t1[2])(t1[3]); +} + +void Kalyna512::Base::ProcessBlock_88(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 *t1 = m_wspace+0, *t2 = m_wspace+8, *msg = m_wspace+16; + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(msg[0])(msg[1])(msg[2])(msg[3])(msg[4])(msg[5])(msg[6])(msg[7]); + + if (IsForwardTransformation()) + { + AddKey<8>(msg, t1, m_rkeys); + G512(t1, t2, &m_rkeys[8]); // 1 + G512(t2, t1, &m_rkeys[16]); // 2 + G512(t1, t2, &m_rkeys[24]); // 3 + G512(t2, t1, &m_rkeys[32]); // 4 + G512(t1, t2, &m_rkeys[40]); // 5 + G512(t2, t1, &m_rkeys[48]); // 6 + G512(t1, t2, &m_rkeys[56]); // 7 + G512(t2, t1, &m_rkeys[64]); // 8 + G512(t1, t2, &m_rkeys[72]); // 9 + G512(t2, t1, &m_rkeys[80]); // 10 + G512(t1, t2, &m_rkeys[88]); // 11 + G512(t2, t1, &m_rkeys[96]); // 12 + G512(t1, t2, &m_rkeys[104]); // 13 + G512(t2, t1, &m_rkeys[112]); // 14 + G512(t1, t2, &m_rkeys[120]); // 15 + G512(t2, t1, &m_rkeys[128]); // 16 + G512(t1, t2, &m_rkeys[136]); // 17 + GL512(t2, t1, &m_rkeys[144]); // 18 + } + else + { + SubKey<8>(msg, t1, &m_rkeys[144]); + IMC512(t1); + IG512(t1, t2, &m_rkeys[136]); + IG512(t2, t1, &m_rkeys[128]); + IG512(t1, t2, &m_rkeys[120]); + IG512(t2, t1, &m_rkeys[112]); + IG512(t1, t2, &m_rkeys[104]); + IG512(t2, t1, &m_rkeys[96]); + IG512(t1, t2, &m_rkeys[88]); + IG512(t2, t1, &m_rkeys[80]); + IG512(t1, t2, &m_rkeys[72]); + IG512(t2, t1, &m_rkeys[64]); + IG512(t1, t2, &m_rkeys[56]); + IG512(t2, t1, &m_rkeys[48]); + IG512(t1, t2, &m_rkeys[40]); + IG512(t2, t1, &m_rkeys[32]); + IG512(t1, t2, &m_rkeys[24]); + IG512(t2, t1, &m_rkeys[16]); + IG512(t1, t2, &m_rkeys[8]); + IGL512(t2, t1, &m_rkeys[0]); + } + + // Reverse bytes on BigEndian; Align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(t1[0])(t1[1])(t1[2])(t1[3])(t1[4])(t1[5])(t1[6])(t1[7]); +} + +// *********************** Library routines *********************** // + +void Kalyna128::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + m_nb = static_cast(16U / sizeof(word64)); + m_nk = static_cast(keylen / sizeof(word64)); + + switch (keylen) + { + case 16: // 128 + m_kl = 16; + m_mkey.New(2); + m_rkeys.New(11*2); + m_wspace.New(2*6); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 2, key, 16); + SetKey_22(m_mkey.begin()); + break; + case 32: // 256 + m_kl = 32; + m_mkey.New(4); + m_rkeys.New(15*2); + m_wspace.New(6*2+4); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 4, key, 32); + SetKey_24(m_mkey.begin()); + break; + default: + CRYPTOPP_ASSERT(0); + } +} + +void Kalyna128::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Timing attack countermeasure. see comments in Rijndael for more details + const int cacheLineSize = GetCacheLineSize(); + volatile word64 _u = 0; + word64 u = _u; + + const byte* p = reinterpret_cast(KalynaTab::S); + for (unsigned int i=0; i<256; i+=cacheLineSize) + u ^= *reinterpret_cast(p+i); + m_wspace[0] = u; + + switch ((m_nb << 8) | m_nk) + { + case (2 << 8) | 2: + ProcessBlock_22(inBlock, xorBlock, outBlock); + break; + case (2 << 8) | 4: + ProcessBlock_24(inBlock, xorBlock, outBlock); + break; + default: + CRYPTOPP_ASSERT(0); + } +} + +void Kalyna256::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + m_nb = static_cast(32U / sizeof(word64)); + m_nk = static_cast(keylen / sizeof(word64)); + + switch (keylen) + { + case 32: // 256 + m_kl = 32; + m_mkey.New(4); + m_rkeys.New(15*4); + m_wspace.New(5*4); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 4, key, 32); + SetKey_44(m_mkey.begin()); + break; + case 64: // 512 + m_kl = 64; + m_mkey.New(8); + m_rkeys.New(19*4); + m_wspace.New(6*4+8); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 8, key, 64); + SetKey_48(m_mkey.begin()); + break; + default: + CRYPTOPP_ASSERT(0); + } +} + +void Kalyna256::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Timing attack countermeasure. see comments in Rijndael for more details + const int cacheLineSize = GetCacheLineSize(); + volatile word64 _u = 0; + word64 u = _u; + + const byte* p = reinterpret_cast(KalynaTab::S); + for (unsigned int i=0; i<256; i+=cacheLineSize) + u ^= *reinterpret_cast(p+i); + m_wspace[0] = u; + + switch ((m_nb << 8) | m_nk) + { + case (4 << 8) | 4: + ProcessBlock_44(inBlock, xorBlock, outBlock); + break; + case (4 << 8) | 8: + ProcessBlock_48(inBlock, xorBlock, outBlock); + break; + default: + CRYPTOPP_ASSERT(0); + } +} + +void Kalyna512::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + m_nb = static_cast(64U / sizeof(word64)); + m_nk = static_cast(keylen / sizeof(word64)); + + switch (keylen) + { + case 64: // 512 + m_kl = 64; + m_nb = static_cast(64U / sizeof(word64)); + m_nk = static_cast(keylen / sizeof(word64)); + + m_mkey.New(8); + m_rkeys.New(19*8); + m_wspace.New(5*8); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 8, key, 64); + SetKey_88(m_mkey.begin()); + break; + default: + CRYPTOPP_ASSERT(0); + } +} + +void Kalyna512::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Timing attack countermeasure. see comments in Rijndael for more details + const int cacheLineSize = GetCacheLineSize(); + volatile word64 _u = 0; + word64 u = _u; + + const byte* p = reinterpret_cast(KalynaTab::S); + for (unsigned int i=0; i<256; i+=cacheLineSize) + u ^= *reinterpret_cast(p+i); + m_wspace[0] = u; + + ProcessBlock_88(inBlock, xorBlock, outBlock); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/kalyna.h b/external/ours/library/crypto/src/shared/original/kalyna.h new file mode 100755 index 000000000..277fccb52 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/kalynatab.cpp b/external/ours/library/crypto/src/shared/original/kalynatab.cpp new file mode 100755 index 000000000..d4ad171cd --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/kalynatab.cpp @@ -0,0 +1,1232 @@ +// kalynatab.cpp - written and placed in the public domain by Jeffrey Walton + +#include "pch.h" +#include "config.h" +#include "kalyna.h" + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(KalynaTab) + +extern const word64 T[8][256]; // Columns +extern const word64 IT[8][256]; // Inverse +extern const byte S[4][256]; // Substitution +extern const byte IS[4][256]; // Inverse + +const word64 T[8][256] = +{ + { + W64LIT(0xa832a829d77f9aa8), W64LIT(0x4352432297d41143), W64LIT(0x5f3e5fc2df80615f), W64LIT(0x061e063014121806), + W64LIT(0x6bda6b7f670cb16b), W64LIT(0x75bc758f2356c975), W64LIT(0x6cc16c477519ad6c), W64LIT(0x592059f2cb927959), + W64LIT(0x71a871af3b4ad971), W64LIT(0xdf84dfb6f8275bdf), W64LIT(0x87a1874c35b22687), W64LIT(0x95fb95dc59cc6e95), + W64LIT(0x174b17b872655c17), W64LIT(0xf017f0d31aeae7f0), W64LIT(0xd89fd88eea3247d8), W64LIT(0x092d0948363f2409), + W64LIT(0x6dc46d4f731ea96d), W64LIT(0xf318f3cb10e3ebf3), W64LIT(0x1d691de84e53741d), W64LIT(0xcbc0cb16804b0bcb), + W64LIT(0xc9cac9068c4503c9), W64LIT(0x4d644d52b3fe294d), W64LIT(0x2c9c2c7de8c4b02c), W64LIT(0xaf29af11c56a86af), + W64LIT(0x798079ef0b72f979), W64LIT(0xe047e0537a9aa7e0), W64LIT(0x97f197cc55c26697), W64LIT(0xfd2efdbb34c9d3fd), + W64LIT(0x6fce6f5f7f10a16f), W64LIT(0x4b7a4b62a7ec314b), W64LIT(0x454c451283c60945), W64LIT(0x39dd39d596afe439), + W64LIT(0x3ec63eed84baf83e), W64LIT(0xdd8edda6f42953dd), W64LIT(0xa315a371ed4eb6a3), W64LIT(0x4f6e4f42bff0214f), + W64LIT(0xb45eb4c99f2beab4), W64LIT(0xb654b6d99325e2b6), W64LIT(0x9ac89aa47be1529a), W64LIT(0x0e360e70242a380e), + W64LIT(0x1f631ff8425d7c1f), W64LIT(0xbf79bf91a51ac6bf), W64LIT(0x154115a87e6b5415), W64LIT(0xe142e15b7c9da3e1), + W64LIT(0x49704972abe23949), W64LIT(0xd2bdd2ded6046fd2), W64LIT(0x93e593ec4dde7693), W64LIT(0xc6f9c67eae683fc6), + W64LIT(0x92e092e44bd97292), W64LIT(0x72a772b73143d572), W64LIT(0x9edc9e8463fd429e), W64LIT(0x61f8612f5b3a9961), + W64LIT(0xd1b2d1c6dc0d63d1), W64LIT(0x63f2633f57349163), W64LIT(0xfa35fa8326dccffa), W64LIT(0xee71ee235eb09fee), + W64LIT(0xf403f4f302f6f7f4), W64LIT(0x197d19c8564f6419), W64LIT(0xd5a6d5e6c41173d5), W64LIT(0xad23ad01c9648ead), + W64LIT(0x582558facd957d58), W64LIT(0xa40ea449ff5baaa4), W64LIT(0xbb6dbbb1bd06d6bb), W64LIT(0xa11fa161e140bea1), + W64LIT(0xdc8bdcaef22e57dc), W64LIT(0xf21df2c316e4eff2), W64LIT(0x83b5836c2dae3683), W64LIT(0x37eb37a5b285dc37), + W64LIT(0x4257422a91d31542), W64LIT(0xe453e4736286b7e4), W64LIT(0x7a8f7af7017bf57a), W64LIT(0x32fa328dac9ec832), + W64LIT(0x9cd69c946ff34a9c), W64LIT(0xccdbcc2e925e17cc), W64LIT(0xab3dab31dd7696ab), W64LIT(0x4a7f4a6aa1eb354a), + W64LIT(0x8f898f0c058a068f), W64LIT(0x6ecb6e577917a56e), W64LIT(0x04140420181c1004), W64LIT(0x27bb2725d2f59c27), + W64LIT(0x2e962e6de4cab82e), W64LIT(0xe75ce76b688fbbe7), W64LIT(0xe24de2437694afe2), W64LIT(0x5a2f5aeac19b755a), + W64LIT(0x96f496c453c56296), W64LIT(0x164e16b074625816), W64LIT(0x23af2305cae98c23), W64LIT(0x2b872b45fad1ac2b), + W64LIT(0xc2edc25eb6742fc2), W64LIT(0x65ec650f43268965), W64LIT(0x66e36617492f8566), W64LIT(0x0f330f78222d3c0f), + W64LIT(0xbc76bc89af13cabc), W64LIT(0xa937a921d1789ea9), W64LIT(0x474647028fc80147), W64LIT(0x415841329bda1941), + W64LIT(0x34e434bdb88cd034), W64LIT(0x4875487aade53d48), W64LIT(0xfc2bfcb332ced7fc), W64LIT(0xb751b7d19522e6b7), + W64LIT(0x6adf6a77610bb56a), W64LIT(0x88928834179f1a88), W64LIT(0xa50ba541f95caea5), W64LIT(0x530253a2f7a45153), + W64LIT(0x86a4864433b52286), W64LIT(0xf93af99b2cd5c3f9), W64LIT(0x5b2a5be2c79c715b), W64LIT(0xdb90db96e03b4bdb), + W64LIT(0x38d838dd90a8e038), W64LIT(0x7b8a7bff077cf17b), W64LIT(0xc3e8c356b0732bc3), W64LIT(0x1e661ef0445a781e), + W64LIT(0x22aa220dccee8822), W64LIT(0x33ff3385aa99cc33), W64LIT(0x24b4243dd8fc9024), W64LIT(0x2888285df0d8a028), + W64LIT(0x36ee36adb482d836), W64LIT(0xc7fcc776a86f3bc7), W64LIT(0xb240b2f98b39f2b2), W64LIT(0x3bd73bc59aa1ec3b), + W64LIT(0x8e8c8e04038d028e), W64LIT(0x77b6779f2f58c177), W64LIT(0xba68bab9bb01d2ba), W64LIT(0xf506f5fb04f1f3f5), + W64LIT(0x144414a0786c5014), W64LIT(0x9fd99f8c65fa469f), W64LIT(0x0828084030382008), W64LIT(0x551c5592e3b64955), + W64LIT(0x9bcd9bac7de6569b), W64LIT(0x4c614c5ab5f92d4c), W64LIT(0xfe21fea33ec0dffe), W64LIT(0x60fd60275d3d9d60), + W64LIT(0x5c315cdad5896d5c), W64LIT(0xda95da9ee63c4fda), W64LIT(0x187818c050486018), W64LIT(0x4643460a89cf0546), + W64LIT(0xcddecd26945913cd), W64LIT(0x7d947dcf136ee97d), W64LIT(0x21a52115c6e78421), W64LIT(0xb04ab0e98737fab0), + W64LIT(0x3fc33fe582bdfc3f), W64LIT(0x1b771bd85a416c1b), W64LIT(0x8997893c11981e89), W64LIT(0xff24ffab38c7dbff), + W64LIT(0xeb60eb0b40ab8beb), W64LIT(0x84ae84543fbb2a84), W64LIT(0x69d0696f6b02b969), W64LIT(0x3ad23acd9ca6e83a), + W64LIT(0x9dd39d9c69f44e9d), W64LIT(0xd7acd7f6c81f7bd7), W64LIT(0xd3b8d3d6d0036bd3), W64LIT(0x70ad70a73d4ddd70), + W64LIT(0x67e6671f4f288167), W64LIT(0x405d403a9ddd1d40), W64LIT(0xb55bb5c1992ceeb5), W64LIT(0xde81debefe205fde), + W64LIT(0x5d345dd2d38e695d), W64LIT(0x30f0309da090c030), W64LIT(0x91ef91fc41d07e91), W64LIT(0xb14fb1e18130feb1), + W64LIT(0x788578e70d75fd78), W64LIT(0x1155118866774411), W64LIT(0x0105010806070401), W64LIT(0xe556e57b6481b3e5), + W64LIT(0x0000000000000000), W64LIT(0x68d568676d05bd68), W64LIT(0x98c298b477ef5a98), W64LIT(0xa01aa069e747baa0), + W64LIT(0xc5f6c566a46133c5), W64LIT(0x020a02100c0e0802), W64LIT(0xa604a659f355a2a6), W64LIT(0x74b974872551cd74), + W64LIT(0x2d992d75eec3b42d), W64LIT(0x0b270b583a312c0b), W64LIT(0xa210a279eb49b2a2), W64LIT(0x76b37697295fc576), + W64LIT(0xb345b3f18d3ef6b3), W64LIT(0xbe7cbe99a31dc2be), W64LIT(0xced1ce3e9e501fce), W64LIT(0xbd73bd81a914cebd), + W64LIT(0xae2cae19c36d82ae), W64LIT(0xe96ae91b4ca583e9), W64LIT(0x8a988a241b91128a), W64LIT(0x31f53195a697c431), + W64LIT(0x1c6c1ce04854701c), W64LIT(0xec7bec3352be97ec), W64LIT(0xf112f1db1cede3f1), W64LIT(0x99c799bc71e85e99), + W64LIT(0x94fe94d45fcb6a94), W64LIT(0xaa38aa39db7192aa), W64LIT(0xf609f6e30ef8fff6), W64LIT(0x26be262dd4f29826), + W64LIT(0x2f932f65e2cdbc2f), W64LIT(0xef74ef2b58b79bef), W64LIT(0xe86fe8134aa287e8), W64LIT(0x8c868c140f830a8c), + W64LIT(0x35e135b5be8bd435), W64LIT(0x030f03180a090c03), W64LIT(0xd4a3d4eec21677d4), W64LIT(0x7f9e7fdf1f60e17f), + W64LIT(0xfb30fb8b20dbcbfb), W64LIT(0x051105281e1b1405), W64LIT(0xc1e2c146bc7d23c1), W64LIT(0x5e3b5ecad987655e), + W64LIT(0x90ea90f447d77a90), W64LIT(0x20a0201dc0e08020), W64LIT(0x3dc93df58eb3f43d), W64LIT(0x82b082642ba93282), + W64LIT(0xf70cf7eb08fffbf7), W64LIT(0xea65ea0346ac8fea), W64LIT(0x0a220a503c36280a), W64LIT(0x0d390d682e23340d), + W64LIT(0x7e9b7ed71967e57e), W64LIT(0xf83ff8932ad2c7f8), W64LIT(0x500d50bafdad5d50), W64LIT(0x1a721ad05c46681a), + W64LIT(0xc4f3c46ea26637c4), W64LIT(0x071b073812151c07), W64LIT(0x57165782efb84157), W64LIT(0xb862b8a9b70fdab8), + W64LIT(0x3ccc3cfd88b4f03c), W64LIT(0x62f7623751339562), W64LIT(0xe348e34b7093abe3), W64LIT(0xc8cfc80e8a4207c8), + W64LIT(0xac26ac09cf638aac), W64LIT(0x520752aaf1a35552), W64LIT(0x64e9640745218d64), W64LIT(0x1050108060704010), + W64LIT(0xd0b7d0ceda0a67d0), W64LIT(0xd99ad986ec3543d9), W64LIT(0x135f13986a794c13), W64LIT(0x0c3c0c602824300c), + W64LIT(0x125a12906c7e4812), W64LIT(0x298d2955f6dfa429), W64LIT(0x510851b2fbaa5951), W64LIT(0xb967b9a1b108deb9), + W64LIT(0xcfd4cf3698571bcf), W64LIT(0xd6a9d6fece187fd6), W64LIT(0x73a273bf3744d173), W64LIT(0x8d838d1c09840e8d), + W64LIT(0x81bf817c21a03e81), W64LIT(0x5419549ae5b14d54), W64LIT(0xc0e7c04eba7a27c0), W64LIT(0xed7eed3b54b993ed), + W64LIT(0x4e6b4e4ab9f7254e), W64LIT(0x4449441a85c10d44), W64LIT(0xa701a751f552a6a7), W64LIT(0x2a822a4dfcd6a82a), + W64LIT(0x85ab855c39bc2e85), W64LIT(0x25b12535defb9425), W64LIT(0xe659e6636e88bfe6), W64LIT(0xcac5ca1e864c0fca), + W64LIT(0x7c917cc71569ed7c), W64LIT(0x8b9d8b2c1d96168b), W64LIT(0x5613568ae9bf4556), W64LIT(0x80ba807427a73a80) + }, + { + W64LIT(0xd1ce3e9e501fcece), W64LIT(0x6dbbb1bd06d6bbbb), W64LIT(0x60eb0b40ab8bebeb), W64LIT(0xe092e44bd9729292), + W64LIT(0x65ea0346ac8feaea), W64LIT(0xc0cb16804b0bcbcb), W64LIT(0x5f13986a794c1313), W64LIT(0xe2c146bc7d23c1c1), + W64LIT(0x6ae91b4ca583e9e9), W64LIT(0xd23acd9ca6e83a3a), W64LIT(0xa9d6fece187fd6d6), W64LIT(0x40b2f98b39f2b2b2), + W64LIT(0xbdd2ded6046fd2d2), W64LIT(0xea90f447d77a9090), W64LIT(0x4b17b872655c1717), W64LIT(0x3ff8932ad2c7f8f8), + W64LIT(0x57422a91d3154242), W64LIT(0x4115a87e6b541515), W64LIT(0x13568ae9bf455656), W64LIT(0x5eb4c99f2beab4b4), + W64LIT(0xec650f4326896565), W64LIT(0x6c1ce04854701c1c), W64LIT(0x928834179f1a8888), W64LIT(0x52432297d4114343), + W64LIT(0xf6c566a46133c5c5), W64LIT(0x315cdad5896d5c5c), W64LIT(0xee36adb482d83636), W64LIT(0x68bab9bb01d2baba), + W64LIT(0x06f5fb04f1f3f5f5), W64LIT(0x165782efb8415757), W64LIT(0xe6671f4f28816767), W64LIT(0x838d1c09840e8d8d), + W64LIT(0xf53195a697c43131), W64LIT(0x09f6e30ef8fff6f6), W64LIT(0xe9640745218d6464), W64LIT(0x2558facd957d5858), + W64LIT(0xdc9e8463fd429e9e), W64LIT(0x03f4f302f6f7f4f4), W64LIT(0xaa220dccee882222), W64LIT(0x38aa39db7192aaaa), + W64LIT(0xbc758f2356c97575), W64LIT(0x330f78222d3c0f0f), W64LIT(0x0a02100c0e080202), W64LIT(0x4fb1e18130feb1b1), + W64LIT(0x84dfb6f8275bdfdf), W64LIT(0xc46d4f731ea96d6d), W64LIT(0xa273bf3744d17373), W64LIT(0x644d52b3fe294d4d), + W64LIT(0x917cc71569ed7c7c), W64LIT(0xbe262dd4f2982626), W64LIT(0x962e6de4cab82e2e), W64LIT(0x0cf7eb08fffbf7f7), + W64LIT(0x2808403038200808), W64LIT(0x345dd2d38e695d5d), W64LIT(0x49441a85c10d4444), W64LIT(0xc63eed84baf83e3e), + W64LIT(0xd99f8c65fa469f9f), W64LIT(0x4414a0786c501414), W64LIT(0xcfc80e8a4207c8c8), W64LIT(0x2cae19c36d82aeae), + W64LIT(0x19549ae5b14d5454), W64LIT(0x5010806070401010), W64LIT(0x9fd88eea3247d8d8), W64LIT(0x76bc89af13cabcbc), + W64LIT(0x721ad05c46681a1a), W64LIT(0xda6b7f670cb16b6b), W64LIT(0xd0696f6b02b96969), W64LIT(0x18f3cb10e3ebf3f3), + W64LIT(0x73bd81a914cebdbd), W64LIT(0xff3385aa99cc3333), W64LIT(0x3dab31dd7696abab), W64LIT(0x35fa8326dccffafa), + W64LIT(0xb2d1c6dc0d63d1d1), W64LIT(0xcd9bac7de6569b9b), W64LIT(0xd568676d05bd6868), W64LIT(0x6b4e4ab9f7254e4e), + W64LIT(0x4e16b07462581616), W64LIT(0xfb95dc59cc6e9595), W64LIT(0xef91fc41d07e9191), W64LIT(0x71ee235eb09feeee), + W64LIT(0x614c5ab5f92d4c4c), W64LIT(0xf2633f5734916363), W64LIT(0x8c8e04038d028e8e), W64LIT(0x2a5be2c79c715b5b), + W64LIT(0xdbcc2e925e17cccc), W64LIT(0xcc3cfd88b4f03c3c), W64LIT(0x7d19c8564f641919), W64LIT(0x1fa161e140bea1a1), + W64LIT(0xbf817c21a03e8181), W64LIT(0x704972abe2394949), W64LIT(0x8a7bff077cf17b7b), W64LIT(0x9ad986ec3543d9d9), + W64LIT(0xce6f5f7f10a16f6f), W64LIT(0xeb37a5b285dc3737), W64LIT(0xfd60275d3d9d6060), W64LIT(0xc5ca1e864c0fcaca), + W64LIT(0x5ce76b688fbbe7e7), W64LIT(0x872b45fad1ac2b2b), W64LIT(0x75487aade53d4848), W64LIT(0x2efdbb34c9d3fdfd), + W64LIT(0xf496c453c5629696), W64LIT(0x4c451283c6094545), W64LIT(0x2bfcb332ced7fcfc), W64LIT(0x5841329bda194141), + W64LIT(0x5a12906c7e481212), W64LIT(0x390d682e23340d0d), W64LIT(0x8079ef0b72f97979), W64LIT(0x56e57b6481b3e5e5), + W64LIT(0x97893c11981e8989), W64LIT(0x868c140f830a8c8c), W64LIT(0x48e34b7093abe3e3), W64LIT(0xa0201dc0e0802020), + W64LIT(0xf0309da090c03030), W64LIT(0x8bdcaef22e57dcdc), W64LIT(0x51b7d19522e6b7b7), W64LIT(0xc16c477519ad6c6c), + W64LIT(0x7f4a6aa1eb354a4a), W64LIT(0x5bb5c1992ceeb5b5), W64LIT(0xc33fe582bdfc3f3f), W64LIT(0xf197cc55c2669797), + W64LIT(0xa3d4eec21677d4d4), W64LIT(0xf762375133956262), W64LIT(0x992d75eec3b42d2d), W64LIT(0x1e06301412180606), + W64LIT(0x0ea449ff5baaa4a4), W64LIT(0x0ba541f95caea5a5), W64LIT(0xb5836c2dae368383), W64LIT(0x3e5fc2df80615f5f), + W64LIT(0x822a4dfcd6a82a2a), W64LIT(0x95da9ee63c4fdada), W64LIT(0xcac9068c4503c9c9), W64LIT(0x0000000000000000), + W64LIT(0x9b7ed71967e57e7e), W64LIT(0x10a279eb49b2a2a2), W64LIT(0x1c5592e3b6495555), W64LIT(0x79bf91a51ac6bfbf), + W64LIT(0x5511886677441111), W64LIT(0xa6d5e6c41173d5d5), W64LIT(0xd69c946ff34a9c9c), W64LIT(0xd4cf3698571bcfcf), + W64LIT(0x360e70242a380e0e), W64LIT(0x220a503c36280a0a), W64LIT(0xc93df58eb3f43d3d), W64LIT(0x0851b2fbaa595151), + W64LIT(0x947dcf136ee97d7d), W64LIT(0xe593ec4dde769393), W64LIT(0x771bd85a416c1b1b), W64LIT(0x21fea33ec0dffefe), + W64LIT(0xf3c46ea26637c4c4), W64LIT(0x4647028fc8014747), W64LIT(0x2d0948363f240909), W64LIT(0xa4864433b5228686), + W64LIT(0x270b583a312c0b0b), W64LIT(0x898f0c058a068f8f), W64LIT(0xd39d9c69f44e9d9d), W64LIT(0xdf6a77610bb56a6a), + W64LIT(0x1b073812151c0707), W64LIT(0x67b9a1b108deb9b9), W64LIT(0x4ab0e98737fab0b0), W64LIT(0xc298b477ef5a9898), + W64LIT(0x7818c05048601818), W64LIT(0xfa328dac9ec83232), W64LIT(0xa871af3b4ad97171), W64LIT(0x7a4b62a7ec314b4b), + W64LIT(0x74ef2b58b79befef), W64LIT(0xd73bc59aa1ec3b3b), W64LIT(0xad70a73d4ddd7070), W64LIT(0x1aa069e747baa0a0), + W64LIT(0x53e4736286b7e4e4), W64LIT(0x5d403a9ddd1d4040), W64LIT(0x24ffab38c7dbffff), W64LIT(0xe8c356b0732bc3c3), + W64LIT(0x37a921d1789ea9a9), W64LIT(0x59e6636e88bfe6e6), W64LIT(0x8578e70d75fd7878), W64LIT(0x3af99b2cd5c3f9f9), + W64LIT(0x9d8b2c1d96168b8b), W64LIT(0x43460a89cf054646), W64LIT(0xba807427a73a8080), W64LIT(0x661ef0445a781e1e), + W64LIT(0xd838dd90a8e03838), W64LIT(0x42e15b7c9da3e1e1), W64LIT(0x62b8a9b70fdab8b8), W64LIT(0x32a829d77f9aa8a8), + W64LIT(0x47e0537a9aa7e0e0), W64LIT(0x3c0c602824300c0c), W64LIT(0xaf2305cae98c2323), W64LIT(0xb37697295fc57676), + W64LIT(0x691de84e53741d1d), W64LIT(0xb12535defb942525), W64LIT(0xb4243dd8fc902424), W64LIT(0x1105281e1b140505), + W64LIT(0x12f1db1cede3f1f1), W64LIT(0xcb6e577917a56e6e), W64LIT(0xfe94d45fcb6a9494), W64LIT(0x88285df0d8a02828), + W64LIT(0xc89aa47be1529a9a), W64LIT(0xae84543fbb2a8484), W64LIT(0x6fe8134aa287e8e8), W64LIT(0x15a371ed4eb6a3a3), + W64LIT(0x6e4f42bff0214f4f), W64LIT(0xb6779f2f58c17777), W64LIT(0xb8d3d6d0036bd3d3), W64LIT(0xab855c39bc2e8585), + W64LIT(0x4de2437694afe2e2), W64LIT(0x0752aaf1a3555252), W64LIT(0x1df2c316e4eff2f2), W64LIT(0xb082642ba9328282), + W64LIT(0x0d50bafdad5d5050), W64LIT(0x8f7af7017bf57a7a), W64LIT(0x932f65e2cdbc2f2f), W64LIT(0xb974872551cd7474), + W64LIT(0x0253a2f7a4515353), W64LIT(0x45b3f18d3ef6b3b3), W64LIT(0xf8612f5b3a996161), W64LIT(0x29af11c56a86afaf), + W64LIT(0xdd39d596afe43939), W64LIT(0xe135b5be8bd43535), W64LIT(0x81debefe205fdede), W64LIT(0xdecd26945913cdcd), + W64LIT(0x631ff8425d7c1f1f), W64LIT(0xc799bc71e85e9999), W64LIT(0x26ac09cf638aacac), W64LIT(0x23ad01c9648eadad), + W64LIT(0xa772b73143d57272), W64LIT(0x9c2c7de8c4b02c2c), W64LIT(0x8edda6f42953dddd), W64LIT(0xb7d0ceda0a67d0d0), + W64LIT(0xa1874c35b2268787), W64LIT(0x7cbe99a31dc2bebe), W64LIT(0x3b5ecad987655e5e), W64LIT(0x04a659f355a2a6a6), + W64LIT(0x7bec3352be97ecec), W64LIT(0x140420181c100404), W64LIT(0xf9c67eae683fc6c6), W64LIT(0x0f03180a090c0303), + W64LIT(0xe434bdb88cd03434), W64LIT(0x30fb8b20dbcbfbfb), W64LIT(0x90db96e03b4bdbdb), W64LIT(0x2059f2cb92795959), + W64LIT(0x54b6d99325e2b6b6), W64LIT(0xedc25eb6742fc2c2), W64LIT(0x0501080607040101), W64LIT(0x17f0d31aeae7f0f0), + W64LIT(0x2f5aeac19b755a5a), W64LIT(0x7eed3b54b993eded), W64LIT(0x01a751f552a6a7a7), W64LIT(0xe36617492f856666), + W64LIT(0xa52115c6e7842121), W64LIT(0x9e7fdf1f60e17f7f), W64LIT(0x988a241b91128a8a), W64LIT(0xbb2725d2f59c2727), + W64LIT(0xfcc776a86f3bc7c7), W64LIT(0xe7c04eba7a27c0c0), W64LIT(0x8d2955f6dfa42929), W64LIT(0xacd7f6c81f7bd7d7) + }, + { + W64LIT(0x93ec4dde769393e5), W64LIT(0xd986ec3543d9d99a), W64LIT(0x9aa47be1529a9ac8), W64LIT(0xb5c1992ceeb5b55b), + W64LIT(0x98b477ef5a9898c2), W64LIT(0x220dccee882222aa), W64LIT(0x451283c60945454c), W64LIT(0xfcb332ced7fcfc2b), + W64LIT(0xbab9bb01d2baba68), W64LIT(0x6a77610bb56a6adf), W64LIT(0xdfb6f8275bdfdf84), W64LIT(0x02100c0e0802020a), + W64LIT(0x9f8c65fa469f9fd9), W64LIT(0xdcaef22e57dcdc8b), W64LIT(0x51b2fbaa59515108), W64LIT(0x59f2cb9279595920), + W64LIT(0x4a6aa1eb354a4a7f), W64LIT(0x17b872655c17174b), W64LIT(0x2b45fad1ac2b2b87), W64LIT(0xc25eb6742fc2c2ed), + W64LIT(0x94d45fcb6a9494fe), W64LIT(0xf4f302f6f7f4f403), W64LIT(0xbbb1bd06d6bbbb6d), W64LIT(0xa371ed4eb6a3a315), + W64LIT(0x62375133956262f7), W64LIT(0xe4736286b7e4e453), W64LIT(0x71af3b4ad97171a8), W64LIT(0xd4eec21677d4d4a3), + W64LIT(0xcd26945913cdcdde), W64LIT(0x70a73d4ddd7070ad), W64LIT(0x16b074625816164e), W64LIT(0xe15b7c9da3e1e142), + W64LIT(0x4972abe239494970), W64LIT(0x3cfd88b4f03c3ccc), W64LIT(0xc04eba7a27c0c0e7), W64LIT(0xd88eea3247d8d89f), + W64LIT(0x5cdad5896d5c5c31), W64LIT(0x9bac7de6569b9bcd), W64LIT(0xad01c9648eadad23), W64LIT(0x855c39bc2e8585ab), + W64LIT(0x53a2f7a451535302), W64LIT(0xa161e140bea1a11f), W64LIT(0x7af7017bf57a7a8f), W64LIT(0xc80e8a4207c8c8cf), + W64LIT(0x2d75eec3b42d2d99), W64LIT(0xe0537a9aa7e0e047), W64LIT(0xd1c6dc0d63d1d1b2), W64LIT(0x72b73143d57272a7), + W64LIT(0xa659f355a2a6a604), W64LIT(0x2c7de8c4b02c2c9c), W64LIT(0xc46ea26637c4c4f3), W64LIT(0xe34b7093abe3e348), + W64LIT(0x7697295fc57676b3), W64LIT(0x78e70d75fd787885), W64LIT(0xb7d19522e6b7b751), W64LIT(0xb4c99f2beab4b45e), + W64LIT(0x0948363f2409092d), W64LIT(0x3bc59aa1ec3b3bd7), W64LIT(0x0e70242a380e0e36), W64LIT(0x41329bda19414158), + W64LIT(0x4c5ab5f92d4c4c61), W64LIT(0xdebefe205fdede81), W64LIT(0xb2f98b39f2b2b240), W64LIT(0x90f447d77a9090ea), + W64LIT(0x2535defb942525b1), W64LIT(0xa541f95caea5a50b), W64LIT(0xd7f6c81f7bd7d7ac), W64LIT(0x03180a090c03030f), + W64LIT(0x1188667744111155), W64LIT(0x0000000000000000), W64LIT(0xc356b0732bc3c3e8), W64LIT(0x2e6de4cab82e2e96), + W64LIT(0x92e44bd9729292e0), W64LIT(0xef2b58b79befef74), W64LIT(0x4e4ab9f7254e4e6b), W64LIT(0x12906c7e4812125a), + W64LIT(0x9d9c69f44e9d9dd3), W64LIT(0x7dcf136ee97d7d94), W64LIT(0xcb16804b0bcbcbc0), W64LIT(0x35b5be8bd43535e1), + W64LIT(0x1080607040101050), W64LIT(0xd5e6c41173d5d5a6), W64LIT(0x4f42bff0214f4f6e), W64LIT(0x9e8463fd429e9edc), + W64LIT(0x4d52b3fe294d4d64), W64LIT(0xa921d1789ea9a937), W64LIT(0x5592e3b64955551c), W64LIT(0xc67eae683fc6c6f9), + W64LIT(0xd0ceda0a67d0d0b7), W64LIT(0x7bff077cf17b7b8a), W64LIT(0x18c0504860181878), W64LIT(0x97cc55c2669797f1), + W64LIT(0xd3d6d0036bd3d3b8), W64LIT(0x36adb482d83636ee), W64LIT(0xe6636e88bfe6e659), W64LIT(0x487aade53d484875), + W64LIT(0x568ae9bf45565613), W64LIT(0x817c21a03e8181bf), W64LIT(0x8f0c058a068f8f89), W64LIT(0x779f2f58c17777b6), + W64LIT(0xcc2e925e17ccccdb), W64LIT(0x9c946ff34a9c9cd6), W64LIT(0xb9a1b108deb9b967), W64LIT(0xe2437694afe2e24d), + W64LIT(0xac09cf638aacac26), W64LIT(0xb8a9b70fdab8b862), W64LIT(0x2f65e2cdbc2f2f93), W64LIT(0x15a87e6b54151541), + W64LIT(0xa449ff5baaa4a40e), W64LIT(0x7cc71569ed7c7c91), W64LIT(0xda9ee63c4fdada95), W64LIT(0x38dd90a8e03838d8), + W64LIT(0x1ef0445a781e1e66), W64LIT(0x0b583a312c0b0b27), W64LIT(0x05281e1b14050511), W64LIT(0xd6fece187fd6d6a9), + W64LIT(0x14a0786c50141444), W64LIT(0x6e577917a56e6ecb), W64LIT(0x6c477519ad6c6cc1), W64LIT(0x7ed71967e57e7e9b), + W64LIT(0x6617492f856666e3), W64LIT(0xfdbb34c9d3fdfd2e), W64LIT(0xb1e18130feb1b14f), W64LIT(0xe57b6481b3e5e556), + W64LIT(0x60275d3d9d6060fd), W64LIT(0xaf11c56a86afaf29), W64LIT(0x5ecad987655e5e3b), W64LIT(0x3385aa99cc3333ff), + W64LIT(0x874c35b2268787a1), W64LIT(0xc9068c4503c9c9ca), W64LIT(0xf0d31aeae7f0f017), W64LIT(0x5dd2d38e695d5d34), + W64LIT(0x6d4f731ea96d6dc4), W64LIT(0x3fe582bdfc3f3fc3), W64LIT(0x8834179f1a888892), W64LIT(0x8d1c09840e8d8d83), + W64LIT(0xc776a86f3bc7c7fc), W64LIT(0xf7eb08fffbf7f70c), W64LIT(0x1de84e53741d1d69), W64LIT(0xe91b4ca583e9e96a), + W64LIT(0xec3352be97ecec7b), W64LIT(0xed3b54b993eded7e), W64LIT(0x807427a73a8080ba), W64LIT(0x2955f6dfa429298d), + W64LIT(0x2725d2f59c2727bb), W64LIT(0xcf3698571bcfcfd4), W64LIT(0x99bc71e85e9999c7), W64LIT(0xa829d77f9aa8a832), + W64LIT(0x50bafdad5d50500d), W64LIT(0x0f78222d3c0f0f33), W64LIT(0x37a5b285dc3737eb), W64LIT(0x243dd8fc902424b4), + W64LIT(0x285df0d8a0282888), W64LIT(0x309da090c03030f0), W64LIT(0x95dc59cc6e9595fb), W64LIT(0xd2ded6046fd2d2bd), + W64LIT(0x3eed84baf83e3ec6), W64LIT(0x5be2c79c715b5b2a), W64LIT(0x403a9ddd1d40405d), W64LIT(0x836c2dae368383b5), + W64LIT(0xb3f18d3ef6b3b345), W64LIT(0x696f6b02b96969d0), W64LIT(0x5782efb841575716), W64LIT(0x1ff8425d7c1f1f63), + W64LIT(0x073812151c07071b), W64LIT(0x1ce04854701c1c6c), W64LIT(0x8a241b91128a8a98), W64LIT(0xbc89af13cabcbc76), + W64LIT(0x201dc0e0802020a0), W64LIT(0xeb0b40ab8bebeb60), W64LIT(0xce3e9e501fceced1), W64LIT(0x8e04038d028e8e8c), + W64LIT(0xab31dd7696abab3d), W64LIT(0xee235eb09feeee71), W64LIT(0x3195a697c43131f5), W64LIT(0xa279eb49b2a2a210), + W64LIT(0x73bf3744d17373a2), W64LIT(0xf99b2cd5c3f9f93a), W64LIT(0xca1e864c0fcacac5), W64LIT(0x3acd9ca6e83a3ad2), + W64LIT(0x1ad05c46681a1a72), W64LIT(0xfb8b20dbcbfbfb30), W64LIT(0x0d682e23340d0d39), W64LIT(0xc146bc7d23c1c1e2), + W64LIT(0xfea33ec0dffefe21), W64LIT(0xfa8326dccffafa35), W64LIT(0xf2c316e4eff2f21d), W64LIT(0x6f5f7f10a16f6fce), + W64LIT(0xbd81a914cebdbd73), W64LIT(0x96c453c5629696f4), W64LIT(0xdda6f42953dddd8e), W64LIT(0x432297d411434352), + W64LIT(0x52aaf1a355525207), W64LIT(0xb6d99325e2b6b654), W64LIT(0x0840303820080828), W64LIT(0xf3cb10e3ebf3f318), + W64LIT(0xae19c36d82aeae2c), W64LIT(0xbe99a31dc2bebe7c), W64LIT(0x19c8564f6419197d), W64LIT(0x893c11981e898997), + W64LIT(0x328dac9ec83232fa), W64LIT(0x262dd4f2982626be), W64LIT(0xb0e98737fab0b04a), W64LIT(0xea0346ac8feaea65), + W64LIT(0x4b62a7ec314b4b7a), W64LIT(0x640745218d6464e9), W64LIT(0x84543fbb2a8484ae), W64LIT(0x82642ba9328282b0), + W64LIT(0x6b7f670cb16b6bda), W64LIT(0xf5fb04f1f3f5f506), W64LIT(0x79ef0b72f9797980), W64LIT(0xbf91a51ac6bfbf79), + W64LIT(0x0108060704010105), W64LIT(0x5fc2df80615f5f3e), W64LIT(0x758f2356c97575bc), W64LIT(0x633f5734916363f2), + W64LIT(0x1bd85a416c1b1b77), W64LIT(0x2305cae98c2323af), W64LIT(0x3df58eb3f43d3dc9), W64LIT(0x68676d05bd6868d5), + W64LIT(0x2a4dfcd6a82a2a82), W64LIT(0x650f4326896565ec), W64LIT(0xe8134aa287e8e86f), W64LIT(0x91fc41d07e9191ef), + W64LIT(0xf6e30ef8fff6f609), W64LIT(0xffab38c7dbffff24), W64LIT(0x13986a794c13135f), W64LIT(0x58facd957d585825), + W64LIT(0xf1db1cede3f1f112), W64LIT(0x47028fc801474746), W64LIT(0x0a503c36280a0a22), W64LIT(0x7fdf1f60e17f7f9e), + W64LIT(0xc566a46133c5c5f6), W64LIT(0xa751f552a6a7a701), W64LIT(0xe76b688fbbe7e75c), W64LIT(0x612f5b3a996161f8), + W64LIT(0x5aeac19b755a5a2f), W64LIT(0x063014121806061e), W64LIT(0x460a89cf05464643), W64LIT(0x441a85c10d444449), + W64LIT(0x422a91d315424257), W64LIT(0x0420181c10040414), W64LIT(0xa069e747baa0a01a), W64LIT(0xdb96e03b4bdbdb90), + W64LIT(0x39d596afe43939dd), W64LIT(0x864433b5228686a4), W64LIT(0x549ae5b14d545419), W64LIT(0xaa39db7192aaaa38), + W64LIT(0x8c140f830a8c8c86), W64LIT(0x34bdb88cd03434e4), W64LIT(0x2115c6e7842121a5), W64LIT(0x8b2c1d96168b8b9d), + W64LIT(0xf8932ad2c7f8f83f), W64LIT(0x0c602824300c0c3c), W64LIT(0x74872551cd7474b9), W64LIT(0x671f4f28816767e6) + }, + { + W64LIT(0x676d05bd6868d568), W64LIT(0x1c09840e8d8d838d), W64LIT(0x1e864c0fcacac5ca), W64LIT(0x52b3fe294d4d644d), + W64LIT(0xbf3744d17373a273), W64LIT(0x62a7ec314b4b7a4b), W64LIT(0x4ab9f7254e4e6b4e), W64LIT(0x4dfcd6a82a2a822a), + W64LIT(0xeec21677d4d4a3d4), W64LIT(0xaaf1a35552520752), W64LIT(0x2dd4f2982626be26), W64LIT(0xf18d3ef6b3b345b3), + W64LIT(0x9ae5b14d54541954), W64LIT(0xf0445a781e1e661e), W64LIT(0xc8564f6419197d19), W64LIT(0xf8425d7c1f1f631f), + W64LIT(0x0dccee882222aa22), W64LIT(0x180a090c03030f03), W64LIT(0x0a89cf0546464346), W64LIT(0xf58eb3f43d3dc93d), + W64LIT(0x75eec3b42d2d992d), W64LIT(0x6aa1eb354a4a7f4a), W64LIT(0xa2f7a45153530253), W64LIT(0x6c2dae368383b583), + W64LIT(0x986a794c13135f13), W64LIT(0x241b91128a8a988a), W64LIT(0xd19522e6b7b751b7), W64LIT(0xe6c41173d5d5a6d5), + W64LIT(0x35defb942525b125), W64LIT(0xef0b72f979798079), W64LIT(0xfb04f1f3f5f506f5), W64LIT(0x81a914cebdbd73bd), + W64LIT(0xfacd957d58582558), W64LIT(0x65e2cdbc2f2f932f), W64LIT(0x682e23340d0d390d), W64LIT(0x100c0e0802020a02), + W64LIT(0x3b54b993eded7eed), W64LIT(0xb2fbaa5951510851), W64LIT(0x8463fd429e9edc9e), W64LIT(0x8866774411115511), + W64LIT(0xc316e4eff2f21df2), W64LIT(0xed84baf83e3ec63e), W64LIT(0x92e3b64955551c55), W64LIT(0xcad987655e5e3b5e), + W64LIT(0xc6dc0d63d1d1b2d1), W64LIT(0xb074625816164e16), W64LIT(0xfd88b4f03c3ccc3c), W64LIT(0x17492f856666e366), + W64LIT(0xa73d4ddd7070ad70), W64LIT(0xd2d38e695d5d345d), W64LIT(0xcb10e3ebf3f318f3), W64LIT(0x1283c60945454c45), + W64LIT(0x3a9ddd1d40405d40), W64LIT(0x2e925e17ccccdbcc), W64LIT(0x134aa287e8e86fe8), W64LIT(0xd45fcb6a9494fe94), + W64LIT(0x8ae9bf4556561356), W64LIT(0x4030382008082808), W64LIT(0x3e9e501fceced1ce), W64LIT(0xd05c46681a1a721a), + W64LIT(0xcd9ca6e83a3ad23a), W64LIT(0xded6046fd2d2bdd2), W64LIT(0x5b7c9da3e1e142e1), W64LIT(0xb6f8275bdfdf84df), + W64LIT(0xc1992ceeb5b55bb5), W64LIT(0xdd90a8e03838d838), W64LIT(0x577917a56e6ecb6e), W64LIT(0x70242a380e0e360e), + W64LIT(0x7b6481b3e5e556e5), W64LIT(0xf302f6f7f4f403f4), W64LIT(0x9b2cd5c3f9f93af9), W64LIT(0x4433b5228686a486), + W64LIT(0x1b4ca583e9e96ae9), W64LIT(0x42bff0214f4f6e4f), W64LIT(0xfece187fd6d6a9d6), W64LIT(0x5c39bc2e8585ab85), + W64LIT(0x05cae98c2323af23), W64LIT(0x3698571bcfcfd4cf), W64LIT(0x8dac9ec83232fa32), W64LIT(0xbc71e85e9999c799), + W64LIT(0x95a697c43131f531), W64LIT(0xa0786c5014144414), W64LIT(0x19c36d82aeae2cae), W64LIT(0x235eb09feeee71ee), + W64LIT(0x0e8a4207c8c8cfc8), W64LIT(0x7aade53d48487548), W64LIT(0xd6d0036bd3d3b8d3), W64LIT(0x9da090c03030f030), + W64LIT(0x61e140bea1a11fa1), W64LIT(0xe44bd9729292e092), W64LIT(0x329bda1941415841), W64LIT(0xe18130feb1b14fb1), + W64LIT(0xc050486018187818), W64LIT(0x6ea26637c4c4f3c4), W64LIT(0x7de8c4b02c2c9c2c), W64LIT(0xaf3b4ad97171a871), + W64LIT(0xb73143d57272a772), W64LIT(0x1a85c10d44444944), W64LIT(0xa87e6b5415154115), W64LIT(0xbb34c9d3fdfd2efd), + W64LIT(0xa5b285dc3737eb37), W64LIT(0x99a31dc2bebe7cbe), W64LIT(0xc2df80615f5f3e5f), W64LIT(0x39db7192aaaa38aa), + W64LIT(0xac7de6569b9bcd9b), W64LIT(0x34179f1a88889288), W64LIT(0x8eea3247d8d89fd8), W64LIT(0x31dd7696abab3dab), + W64LIT(0x3c11981e89899789), W64LIT(0x946ff34a9c9cd69c), W64LIT(0x8326dccffafa35fa), W64LIT(0x275d3d9d6060fd60), + W64LIT(0x0346ac8feaea65ea), W64LIT(0x89af13cabcbc76bc), W64LIT(0x375133956262f762), W64LIT(0x602824300c0c3c0c), + W64LIT(0x3dd8fc902424b424), W64LIT(0x59f355a2a6a604a6), W64LIT(0x29d77f9aa8a832a8), W64LIT(0x3352be97ecec7bec), + W64LIT(0x1f4f28816767e667), W64LIT(0x1dc0e0802020a020), W64LIT(0x96e03b4bdbdb90db), W64LIT(0xc71569ed7c7c917c), + W64LIT(0x5df0d8a028288828), W64LIT(0xa6f42953dddd8edd), W64LIT(0x09cf638aacac26ac), W64LIT(0xe2c79c715b5b2a5b), + W64LIT(0xbdb88cd03434e434), W64LIT(0xd71967e57e7e9b7e), W64LIT(0x8060704010105010), W64LIT(0xdb1cede3f1f112f1), + W64LIT(0xff077cf17b7b8a7b), W64LIT(0x0c058a068f8f898f), W64LIT(0x3f5734916363f263), W64LIT(0x69e747baa0a01aa0), + W64LIT(0x281e1b1405051105), W64LIT(0xa47be1529a9ac89a), W64LIT(0x2297d41143435243), W64LIT(0x9f2f58c17777b677), + W64LIT(0x15c6e7842121a521), W64LIT(0x91a51ac6bfbf79bf), W64LIT(0x25d2f59c2727bb27), W64LIT(0x48363f2409092d09), + W64LIT(0x56b0732bc3c3e8c3), W64LIT(0x8c65fa469f9fd99f), W64LIT(0xd99325e2b6b654b6), W64LIT(0xf6c81f7bd7d7acd7), + W64LIT(0x55f6dfa429298d29), W64LIT(0x5eb6742fc2c2edc2), W64LIT(0x0b40ab8bebeb60eb), W64LIT(0x4eba7a27c0c0e7c0), + W64LIT(0x49ff5baaa4a40ea4), W64LIT(0x2c1d96168b8b9d8b), W64LIT(0x140f830a8c8c868c), W64LIT(0xe84e53741d1d691d), + W64LIT(0x8b20dbcbfbfb30fb), W64LIT(0xab38c7dbffff24ff), W64LIT(0x46bc7d23c1c1e2c1), W64LIT(0xf98b39f2b2b240b2), + W64LIT(0xcc55c2669797f197), W64LIT(0x6de4cab82e2e962e), W64LIT(0x932ad2c7f8f83ff8), W64LIT(0x0f4326896565ec65), + W64LIT(0xe30ef8fff6f609f6), W64LIT(0x8f2356c97575bc75), W64LIT(0x3812151c07071b07), W64LIT(0x20181c1004041404), + W64LIT(0x72abe23949497049), W64LIT(0x85aa99cc3333ff33), W64LIT(0x736286b7e4e453e4), W64LIT(0x86ec3543d9d99ad9), + W64LIT(0xa1b108deb9b967b9), W64LIT(0xceda0a67d0d0b7d0), W64LIT(0x2a91d31542425742), W64LIT(0x76a86f3bc7c7fcc7), + W64LIT(0x477519ad6c6cc16c), W64LIT(0xf447d77a9090ea90), W64LIT(0x0000000000000000), W64LIT(0x04038d028e8e8c8e), + W64LIT(0x5f7f10a16f6fce6f), W64LIT(0xbafdad5d50500d50), W64LIT(0x0806070401010501), W64LIT(0x66a46133c5c5f6c5), + W64LIT(0x9ee63c4fdada95da), W64LIT(0x028fc80147474647), W64LIT(0xe582bdfc3f3fc33f), W64LIT(0x26945913cdcddecd), + W64LIT(0x6f6b02b96969d069), W64LIT(0x79eb49b2a2a210a2), W64LIT(0x437694afe2e24de2), W64LIT(0xf7017bf57a7a8f7a), + W64LIT(0x51f552a6a7a701a7), W64LIT(0x7eae683fc6c6f9c6), W64LIT(0xec4dde769393e593), W64LIT(0x78222d3c0f0f330f), + W64LIT(0x503c36280a0a220a), W64LIT(0x3014121806061e06), W64LIT(0x636e88bfe6e659e6), W64LIT(0x45fad1ac2b2b872b), + W64LIT(0xc453c5629696f496), W64LIT(0x71ed4eb6a3a315a3), W64LIT(0xe04854701c1c6c1c), W64LIT(0x11c56a86afaf29af), + W64LIT(0x77610bb56a6adf6a), W64LIT(0x906c7e4812125a12), W64LIT(0x543fbb2a8484ae84), W64LIT(0xd596afe43939dd39), + W64LIT(0x6b688fbbe7e75ce7), W64LIT(0xe98737fab0b04ab0), W64LIT(0x642ba9328282b082), W64LIT(0xeb08fffbf7f70cf7), + W64LIT(0xa33ec0dffefe21fe), W64LIT(0x9c69f44e9d9dd39d), W64LIT(0x4c35b2268787a187), W64LIT(0xdad5896d5c5c315c), + W64LIT(0x7c21a03e8181bf81), W64LIT(0xb5be8bd43535e135), W64LIT(0xbefe205fdede81de), W64LIT(0xc99f2beab4b45eb4), + W64LIT(0x41f95caea5a50ba5), W64LIT(0xb332ced7fcfc2bfc), W64LIT(0x7427a73a8080ba80), W64LIT(0x2b58b79befef74ef), + W64LIT(0x16804b0bcbcbc0cb), W64LIT(0xb1bd06d6bbbb6dbb), W64LIT(0x7f670cb16b6bda6b), W64LIT(0x97295fc57676b376), + W64LIT(0xb9bb01d2baba68ba), W64LIT(0xeac19b755a5a2f5a), W64LIT(0xcf136ee97d7d947d), W64LIT(0xe70d75fd78788578), + W64LIT(0x583a312c0b0b270b), W64LIT(0xdc59cc6e9595fb95), W64LIT(0x4b7093abe3e348e3), W64LIT(0x01c9648eadad23ad), + W64LIT(0x872551cd7474b974), W64LIT(0xb477ef5a9898c298), W64LIT(0xc59aa1ec3b3bd73b), W64LIT(0xadb482d83636ee36), + W64LIT(0x0745218d6464e964), W64LIT(0x4f731ea96d6dc46d), W64LIT(0xaef22e57dcdc8bdc), W64LIT(0xd31aeae7f0f017f0), + W64LIT(0xf2cb927959592059), W64LIT(0x21d1789ea9a937a9), W64LIT(0x5ab5f92d4c4c614c), W64LIT(0xb872655c17174b17), + W64LIT(0xdf1f60e17f7f9e7f), W64LIT(0xfc41d07e9191ef91), W64LIT(0xa9b70fdab8b862b8), W64LIT(0x068c4503c9c9cac9), + W64LIT(0x82efb84157571657), W64LIT(0xd85a416c1b1b771b), W64LIT(0x537a9aa7e0e047e0), W64LIT(0x2f5b3a996161f861) + }, + { + W64LIT(0xd77f9aa8a832a829), W64LIT(0x97d4114343524322), W64LIT(0xdf80615f5f3e5fc2), W64LIT(0x14121806061e0630), + W64LIT(0x670cb16b6bda6b7f), W64LIT(0x2356c97575bc758f), W64LIT(0x7519ad6c6cc16c47), W64LIT(0xcb927959592059f2), + W64LIT(0x3b4ad97171a871af), W64LIT(0xf8275bdfdf84dfb6), W64LIT(0x35b2268787a1874c), W64LIT(0x59cc6e9595fb95dc), + W64LIT(0x72655c17174b17b8), W64LIT(0x1aeae7f0f017f0d3), W64LIT(0xea3247d8d89fd88e), W64LIT(0x363f2409092d0948), + W64LIT(0x731ea96d6dc46d4f), W64LIT(0x10e3ebf3f318f3cb), W64LIT(0x4e53741d1d691de8), W64LIT(0x804b0bcbcbc0cb16), + W64LIT(0x8c4503c9c9cac906), W64LIT(0xb3fe294d4d644d52), W64LIT(0xe8c4b02c2c9c2c7d), W64LIT(0xc56a86afaf29af11), + W64LIT(0x0b72f979798079ef), W64LIT(0x7a9aa7e0e047e053), W64LIT(0x55c2669797f197cc), W64LIT(0x34c9d3fdfd2efdbb), + W64LIT(0x7f10a16f6fce6f5f), W64LIT(0xa7ec314b4b7a4b62), W64LIT(0x83c60945454c4512), W64LIT(0x96afe43939dd39d5), + W64LIT(0x84baf83e3ec63eed), W64LIT(0xf42953dddd8edda6), W64LIT(0xed4eb6a3a315a371), W64LIT(0xbff0214f4f6e4f42), + W64LIT(0x9f2beab4b45eb4c9), W64LIT(0x9325e2b6b654b6d9), W64LIT(0x7be1529a9ac89aa4), W64LIT(0x242a380e0e360e70), + W64LIT(0x425d7c1f1f631ff8), W64LIT(0xa51ac6bfbf79bf91), W64LIT(0x7e6b5415154115a8), W64LIT(0x7c9da3e1e142e15b), + W64LIT(0xabe2394949704972), W64LIT(0xd6046fd2d2bdd2de), W64LIT(0x4dde769393e593ec), W64LIT(0xae683fc6c6f9c67e), + W64LIT(0x4bd9729292e092e4), W64LIT(0x3143d57272a772b7), W64LIT(0x63fd429e9edc9e84), W64LIT(0x5b3a996161f8612f), + W64LIT(0xdc0d63d1d1b2d1c6), W64LIT(0x5734916363f2633f), W64LIT(0x26dccffafa35fa83), W64LIT(0x5eb09feeee71ee23), + W64LIT(0x02f6f7f4f403f4f3), W64LIT(0x564f6419197d19c8), W64LIT(0xc41173d5d5a6d5e6), W64LIT(0xc9648eadad23ad01), + W64LIT(0xcd957d58582558fa), W64LIT(0xff5baaa4a40ea449), W64LIT(0xbd06d6bbbb6dbbb1), W64LIT(0xe140bea1a11fa161), + W64LIT(0xf22e57dcdc8bdcae), W64LIT(0x16e4eff2f21df2c3), W64LIT(0x2dae368383b5836c), W64LIT(0xb285dc3737eb37a5), + W64LIT(0x91d315424257422a), W64LIT(0x6286b7e4e453e473), W64LIT(0x017bf57a7a8f7af7), W64LIT(0xac9ec83232fa328d), + W64LIT(0x6ff34a9c9cd69c94), W64LIT(0x925e17ccccdbcc2e), W64LIT(0xdd7696abab3dab31), W64LIT(0xa1eb354a4a7f4a6a), + W64LIT(0x058a068f8f898f0c), W64LIT(0x7917a56e6ecb6e57), W64LIT(0x181c100404140420), W64LIT(0xd2f59c2727bb2725), + W64LIT(0xe4cab82e2e962e6d), W64LIT(0x688fbbe7e75ce76b), W64LIT(0x7694afe2e24de243), W64LIT(0xc19b755a5a2f5aea), + W64LIT(0x53c5629696f496c4), W64LIT(0x74625816164e16b0), W64LIT(0xcae98c2323af2305), W64LIT(0xfad1ac2b2b872b45), + W64LIT(0xb6742fc2c2edc25e), W64LIT(0x4326896565ec650f), W64LIT(0x492f856666e36617), W64LIT(0x222d3c0f0f330f78), + W64LIT(0xaf13cabcbc76bc89), W64LIT(0xd1789ea9a937a921), W64LIT(0x8fc8014747464702), W64LIT(0x9bda194141584132), + W64LIT(0xb88cd03434e434bd), W64LIT(0xade53d484875487a), W64LIT(0x32ced7fcfc2bfcb3), W64LIT(0x9522e6b7b751b7d1), + W64LIT(0x610bb56a6adf6a77), W64LIT(0x179f1a8888928834), W64LIT(0xf95caea5a50ba541), W64LIT(0xf7a45153530253a2), + W64LIT(0x33b5228686a48644), W64LIT(0x2cd5c3f9f93af99b), W64LIT(0xc79c715b5b2a5be2), W64LIT(0xe03b4bdbdb90db96), + W64LIT(0x90a8e03838d838dd), W64LIT(0x077cf17b7b8a7bff), W64LIT(0xb0732bc3c3e8c356), W64LIT(0x445a781e1e661ef0), + W64LIT(0xccee882222aa220d), W64LIT(0xaa99cc3333ff3385), W64LIT(0xd8fc902424b4243d), W64LIT(0xf0d8a0282888285d), + W64LIT(0xb482d83636ee36ad), W64LIT(0xa86f3bc7c7fcc776), W64LIT(0x8b39f2b2b240b2f9), W64LIT(0x9aa1ec3b3bd73bc5), + W64LIT(0x038d028e8e8c8e04), W64LIT(0x2f58c17777b6779f), W64LIT(0xbb01d2baba68bab9), W64LIT(0x04f1f3f5f506f5fb), + W64LIT(0x786c5014144414a0), W64LIT(0x65fa469f9fd99f8c), W64LIT(0x3038200808280840), W64LIT(0xe3b64955551c5592), + W64LIT(0x7de6569b9bcd9bac), W64LIT(0xb5f92d4c4c614c5a), W64LIT(0x3ec0dffefe21fea3), W64LIT(0x5d3d9d6060fd6027), + W64LIT(0xd5896d5c5c315cda), W64LIT(0xe63c4fdada95da9e), W64LIT(0x50486018187818c0), W64LIT(0x89cf05464643460a), + W64LIT(0x945913cdcddecd26), W64LIT(0x136ee97d7d947dcf), W64LIT(0xc6e7842121a52115), W64LIT(0x8737fab0b04ab0e9), + W64LIT(0x82bdfc3f3fc33fe5), W64LIT(0x5a416c1b1b771bd8), W64LIT(0x11981e898997893c), W64LIT(0x38c7dbffff24ffab), + W64LIT(0x40ab8bebeb60eb0b), W64LIT(0x3fbb2a8484ae8454), W64LIT(0x6b02b96969d0696f), W64LIT(0x9ca6e83a3ad23acd), + W64LIT(0x69f44e9d9dd39d9c), W64LIT(0xc81f7bd7d7acd7f6), W64LIT(0xd0036bd3d3b8d3d6), W64LIT(0x3d4ddd7070ad70a7), + W64LIT(0x4f28816767e6671f), W64LIT(0x9ddd1d40405d403a), W64LIT(0x992ceeb5b55bb5c1), W64LIT(0xfe205fdede81debe), + W64LIT(0xd38e695d5d345dd2), W64LIT(0xa090c03030f0309d), W64LIT(0x41d07e9191ef91fc), W64LIT(0x8130feb1b14fb1e1), + W64LIT(0x0d75fd78788578e7), W64LIT(0x6677441111551188), W64LIT(0x0607040101050108), W64LIT(0x6481b3e5e556e57b), + W64LIT(0x0000000000000000), W64LIT(0x6d05bd6868d56867), W64LIT(0x77ef5a9898c298b4), W64LIT(0xe747baa0a01aa069), + W64LIT(0xa46133c5c5f6c566), W64LIT(0x0c0e0802020a0210), W64LIT(0xf355a2a6a604a659), W64LIT(0x2551cd7474b97487), + W64LIT(0xeec3b42d2d992d75), W64LIT(0x3a312c0b0b270b58), W64LIT(0xeb49b2a2a210a279), W64LIT(0x295fc57676b37697), + W64LIT(0x8d3ef6b3b345b3f1), W64LIT(0xa31dc2bebe7cbe99), W64LIT(0x9e501fceced1ce3e), W64LIT(0xa914cebdbd73bd81), + W64LIT(0xc36d82aeae2cae19), W64LIT(0x4ca583e9e96ae91b), W64LIT(0x1b91128a8a988a24), W64LIT(0xa697c43131f53195), + W64LIT(0x4854701c1c6c1ce0), W64LIT(0x52be97ecec7bec33), W64LIT(0x1cede3f1f112f1db), W64LIT(0x71e85e9999c799bc), + W64LIT(0x5fcb6a9494fe94d4), W64LIT(0xdb7192aaaa38aa39), W64LIT(0x0ef8fff6f609f6e3), W64LIT(0xd4f2982626be262d), + W64LIT(0xe2cdbc2f2f932f65), W64LIT(0x58b79befef74ef2b), W64LIT(0x4aa287e8e86fe813), W64LIT(0x0f830a8c8c868c14), + W64LIT(0xbe8bd43535e135b5), W64LIT(0x0a090c03030f0318), W64LIT(0xc21677d4d4a3d4ee), W64LIT(0x1f60e17f7f9e7fdf), + W64LIT(0x20dbcbfbfb30fb8b), W64LIT(0x1e1b140505110528), W64LIT(0xbc7d23c1c1e2c146), W64LIT(0xd987655e5e3b5eca), + W64LIT(0x47d77a9090ea90f4), W64LIT(0xc0e0802020a0201d), W64LIT(0x8eb3f43d3dc93df5), W64LIT(0x2ba9328282b08264), + W64LIT(0x08fffbf7f70cf7eb), W64LIT(0x46ac8feaea65ea03), W64LIT(0x3c36280a0a220a50), W64LIT(0x2e23340d0d390d68), + W64LIT(0x1967e57e7e9b7ed7), W64LIT(0x2ad2c7f8f83ff893), W64LIT(0xfdad5d50500d50ba), W64LIT(0x5c46681a1a721ad0), + W64LIT(0xa26637c4c4f3c46e), W64LIT(0x12151c07071b0738), W64LIT(0xefb8415757165782), W64LIT(0xb70fdab8b862b8a9), + W64LIT(0x88b4f03c3ccc3cfd), W64LIT(0x5133956262f76237), W64LIT(0x7093abe3e348e34b), W64LIT(0x8a4207c8c8cfc80e), + W64LIT(0xcf638aacac26ac09), W64LIT(0xf1a35552520752aa), W64LIT(0x45218d6464e96407), W64LIT(0x6070401010501080), + W64LIT(0xda0a67d0d0b7d0ce), W64LIT(0xec3543d9d99ad986), W64LIT(0x6a794c13135f1398), W64LIT(0x2824300c0c3c0c60), + W64LIT(0x6c7e4812125a1290), W64LIT(0xf6dfa429298d2955), W64LIT(0xfbaa5951510851b2), W64LIT(0xb108deb9b967b9a1), + W64LIT(0x98571bcfcfd4cf36), W64LIT(0xce187fd6d6a9d6fe), W64LIT(0x3744d17373a273bf), W64LIT(0x09840e8d8d838d1c), + W64LIT(0x21a03e8181bf817c), W64LIT(0xe5b14d545419549a), W64LIT(0xba7a27c0c0e7c04e), W64LIT(0x54b993eded7eed3b), + W64LIT(0xb9f7254e4e6b4e4a), W64LIT(0x85c10d444449441a), W64LIT(0xf552a6a7a701a751), W64LIT(0xfcd6a82a2a822a4d), + W64LIT(0x39bc2e8585ab855c), W64LIT(0xdefb942525b12535), W64LIT(0x6e88bfe6e659e663), W64LIT(0x864c0fcacac5ca1e), + W64LIT(0x1569ed7c7c917cc7), W64LIT(0x1d96168b8b9d8b2c), W64LIT(0xe9bf45565613568a), W64LIT(0x27a73a8080ba8074) + }, + { + W64LIT(0x501fceced1ce3e9e), W64LIT(0x06d6bbbb6dbbb1bd), W64LIT(0xab8bebeb60eb0b40), W64LIT(0xd9729292e092e44b), + W64LIT(0xac8feaea65ea0346), W64LIT(0x4b0bcbcbc0cb1680), W64LIT(0x794c13135f13986a), W64LIT(0x7d23c1c1e2c146bc), + W64LIT(0xa583e9e96ae91b4c), W64LIT(0xa6e83a3ad23acd9c), W64LIT(0x187fd6d6a9d6fece), W64LIT(0x39f2b2b240b2f98b), + W64LIT(0x046fd2d2bdd2ded6), W64LIT(0xd77a9090ea90f447), W64LIT(0x655c17174b17b872), W64LIT(0xd2c7f8f83ff8932a), + W64LIT(0xd315424257422a91), W64LIT(0x6b5415154115a87e), W64LIT(0xbf45565613568ae9), W64LIT(0x2beab4b45eb4c99f), + W64LIT(0x26896565ec650f43), W64LIT(0x54701c1c6c1ce048), W64LIT(0x9f1a888892883417), W64LIT(0xd411434352432297), + W64LIT(0x6133c5c5f6c566a4), W64LIT(0x896d5c5c315cdad5), W64LIT(0x82d83636ee36adb4), W64LIT(0x01d2baba68bab9bb), + W64LIT(0xf1f3f5f506f5fb04), W64LIT(0xb8415757165782ef), W64LIT(0x28816767e6671f4f), W64LIT(0x840e8d8d838d1c09), + W64LIT(0x97c43131f53195a6), W64LIT(0xf8fff6f609f6e30e), W64LIT(0x218d6464e9640745), W64LIT(0x957d58582558facd), + W64LIT(0xfd429e9edc9e8463), W64LIT(0xf6f7f4f403f4f302), W64LIT(0xee882222aa220dcc), W64LIT(0x7192aaaa38aa39db), + W64LIT(0x56c97575bc758f23), W64LIT(0x2d3c0f0f330f7822), W64LIT(0x0e0802020a02100c), W64LIT(0x30feb1b14fb1e181), + W64LIT(0x275bdfdf84dfb6f8), W64LIT(0x1ea96d6dc46d4f73), W64LIT(0x44d17373a273bf37), W64LIT(0xfe294d4d644d52b3), + W64LIT(0x69ed7c7c917cc715), W64LIT(0xf2982626be262dd4), W64LIT(0xcab82e2e962e6de4), W64LIT(0xfffbf7f70cf7eb08), + W64LIT(0x3820080828084030), W64LIT(0x8e695d5d345dd2d3), W64LIT(0xc10d444449441a85), W64LIT(0xbaf83e3ec63eed84), + W64LIT(0xfa469f9fd99f8c65), W64LIT(0x6c5014144414a078), W64LIT(0x4207c8c8cfc80e8a), W64LIT(0x6d82aeae2cae19c3), + W64LIT(0xb14d545419549ae5), W64LIT(0x7040101050108060), W64LIT(0x3247d8d89fd88eea), W64LIT(0x13cabcbc76bc89af), + W64LIT(0x46681a1a721ad05c), W64LIT(0x0cb16b6bda6b7f67), W64LIT(0x02b96969d0696f6b), W64LIT(0xe3ebf3f318f3cb10), + W64LIT(0x14cebdbd73bd81a9), W64LIT(0x99cc3333ff3385aa), W64LIT(0x7696abab3dab31dd), W64LIT(0xdccffafa35fa8326), + W64LIT(0x0d63d1d1b2d1c6dc), W64LIT(0xe6569b9bcd9bac7d), W64LIT(0x05bd6868d568676d), W64LIT(0xf7254e4e6b4e4ab9), + W64LIT(0x625816164e16b074), W64LIT(0xcc6e9595fb95dc59), W64LIT(0xd07e9191ef91fc41), W64LIT(0xb09feeee71ee235e), + W64LIT(0xf92d4c4c614c5ab5), W64LIT(0x34916363f2633f57), W64LIT(0x8d028e8e8c8e0403), W64LIT(0x9c715b5b2a5be2c7), + W64LIT(0x5e17ccccdbcc2e92), W64LIT(0xb4f03c3ccc3cfd88), W64LIT(0x4f6419197d19c856), W64LIT(0x40bea1a11fa161e1), + W64LIT(0xa03e8181bf817c21), W64LIT(0xe2394949704972ab), W64LIT(0x7cf17b7b8a7bff07), W64LIT(0x3543d9d99ad986ec), + W64LIT(0x10a16f6fce6f5f7f), W64LIT(0x85dc3737eb37a5b2), W64LIT(0x3d9d6060fd60275d), W64LIT(0x4c0fcacac5ca1e86), + W64LIT(0x8fbbe7e75ce76b68), W64LIT(0xd1ac2b2b872b45fa), W64LIT(0xe53d484875487aad), W64LIT(0xc9d3fdfd2efdbb34), + W64LIT(0xc5629696f496c453), W64LIT(0xc60945454c451283), W64LIT(0xced7fcfc2bfcb332), W64LIT(0xda1941415841329b), + W64LIT(0x7e4812125a12906c), W64LIT(0x23340d0d390d682e), W64LIT(0x72f979798079ef0b), W64LIT(0x81b3e5e556e57b64), + W64LIT(0x981e898997893c11), W64LIT(0x830a8c8c868c140f), W64LIT(0x93abe3e348e34b70), W64LIT(0xe0802020a0201dc0), + W64LIT(0x90c03030f0309da0), W64LIT(0x2e57dcdc8bdcaef2), W64LIT(0x22e6b7b751b7d195), W64LIT(0x19ad6c6cc16c4775), + W64LIT(0xeb354a4a7f4a6aa1), W64LIT(0x2ceeb5b55bb5c199), W64LIT(0xbdfc3f3fc33fe582), W64LIT(0xc2669797f197cc55), + W64LIT(0x1677d4d4a3d4eec2), W64LIT(0x33956262f7623751), W64LIT(0xc3b42d2d992d75ee), W64LIT(0x121806061e063014), + W64LIT(0x5baaa4a40ea449ff), W64LIT(0x5caea5a50ba541f9), W64LIT(0xae368383b5836c2d), W64LIT(0x80615f5f3e5fc2df), + W64LIT(0xd6a82a2a822a4dfc), W64LIT(0x3c4fdada95da9ee6), W64LIT(0x4503c9c9cac9068c), W64LIT(0x0000000000000000), + W64LIT(0x67e57e7e9b7ed719), W64LIT(0x49b2a2a210a279eb), W64LIT(0xb64955551c5592e3), W64LIT(0x1ac6bfbf79bf91a5), + W64LIT(0x7744111155118866), W64LIT(0x1173d5d5a6d5e6c4), W64LIT(0xf34a9c9cd69c946f), W64LIT(0x571bcfcfd4cf3698), + W64LIT(0x2a380e0e360e7024), W64LIT(0x36280a0a220a503c), W64LIT(0xb3f43d3dc93df58e), W64LIT(0xaa5951510851b2fb), + W64LIT(0x6ee97d7d947dcf13), W64LIT(0xde769393e593ec4d), W64LIT(0x416c1b1b771bd85a), W64LIT(0xc0dffefe21fea33e), + W64LIT(0x6637c4c4f3c46ea2), W64LIT(0xc80147474647028f), W64LIT(0x3f2409092d094836), W64LIT(0xb5228686a4864433), + W64LIT(0x312c0b0b270b583a), W64LIT(0x8a068f8f898f0c05), W64LIT(0xf44e9d9dd39d9c69), W64LIT(0x0bb56a6adf6a7761), + W64LIT(0x151c07071b073812), W64LIT(0x08deb9b967b9a1b1), W64LIT(0x37fab0b04ab0e987), W64LIT(0xef5a9898c298b477), + W64LIT(0x486018187818c050), W64LIT(0x9ec83232fa328dac), W64LIT(0x4ad97171a871af3b), W64LIT(0xec314b4b7a4b62a7), + W64LIT(0xb79befef74ef2b58), W64LIT(0xa1ec3b3bd73bc59a), W64LIT(0x4ddd7070ad70a73d), W64LIT(0x47baa0a01aa069e7), + W64LIT(0x86b7e4e453e47362), W64LIT(0xdd1d40405d403a9d), W64LIT(0xc7dbffff24ffab38), W64LIT(0x732bc3c3e8c356b0), + W64LIT(0x789ea9a937a921d1), W64LIT(0x88bfe6e659e6636e), W64LIT(0x75fd78788578e70d), W64LIT(0xd5c3f9f93af99b2c), + W64LIT(0x96168b8b9d8b2c1d), W64LIT(0xcf05464643460a89), W64LIT(0xa73a8080ba807427), W64LIT(0x5a781e1e661ef044), + W64LIT(0xa8e03838d838dd90), W64LIT(0x9da3e1e142e15b7c), W64LIT(0x0fdab8b862b8a9b7), W64LIT(0x7f9aa8a832a829d7), + W64LIT(0x9aa7e0e047e0537a), W64LIT(0x24300c0c3c0c6028), W64LIT(0xe98c2323af2305ca), W64LIT(0x5fc57676b3769729), + W64LIT(0x53741d1d691de84e), W64LIT(0xfb942525b12535de), W64LIT(0xfc902424b4243dd8), W64LIT(0x1b1405051105281e), + W64LIT(0xede3f1f112f1db1c), W64LIT(0x17a56e6ecb6e5779), W64LIT(0xcb6a9494fe94d45f), W64LIT(0xd8a0282888285df0), + W64LIT(0xe1529a9ac89aa47b), W64LIT(0xbb2a8484ae84543f), W64LIT(0xa287e8e86fe8134a), W64LIT(0x4eb6a3a315a371ed), + W64LIT(0xf0214f4f6e4f42bf), W64LIT(0x58c17777b6779f2f), W64LIT(0x036bd3d3b8d3d6d0), W64LIT(0xbc2e8585ab855c39), + W64LIT(0x94afe2e24de24376), W64LIT(0xa35552520752aaf1), W64LIT(0xe4eff2f21df2c316), W64LIT(0xa9328282b082642b), + W64LIT(0xad5d50500d50bafd), W64LIT(0x7bf57a7a8f7af701), W64LIT(0xcdbc2f2f932f65e2), W64LIT(0x51cd7474b9748725), + W64LIT(0xa45153530253a2f7), W64LIT(0x3ef6b3b345b3f18d), W64LIT(0x3a996161f8612f5b), W64LIT(0x6a86afaf29af11c5), + W64LIT(0xafe43939dd39d596), W64LIT(0x8bd43535e135b5be), W64LIT(0x205fdede81debefe), W64LIT(0x5913cdcddecd2694), + W64LIT(0x5d7c1f1f631ff842), W64LIT(0xe85e9999c799bc71), W64LIT(0x638aacac26ac09cf), W64LIT(0x648eadad23ad01c9), + W64LIT(0x43d57272a772b731), W64LIT(0xc4b02c2c9c2c7de8), W64LIT(0x2953dddd8edda6f4), W64LIT(0x0a67d0d0b7d0ceda), + W64LIT(0xb2268787a1874c35), W64LIT(0x1dc2bebe7cbe99a3), W64LIT(0x87655e5e3b5ecad9), W64LIT(0x55a2a6a604a659f3), + W64LIT(0xbe97ecec7bec3352), W64LIT(0x1c10040414042018), W64LIT(0x683fc6c6f9c67eae), W64LIT(0x090c03030f03180a), + W64LIT(0x8cd03434e434bdb8), W64LIT(0xdbcbfbfb30fb8b20), W64LIT(0x3b4bdbdb90db96e0), W64LIT(0x927959592059f2cb), + W64LIT(0x25e2b6b654b6d993), W64LIT(0x742fc2c2edc25eb6), W64LIT(0x0704010105010806), W64LIT(0xeae7f0f017f0d31a), + W64LIT(0x9b755a5a2f5aeac1), W64LIT(0xb993eded7eed3b54), W64LIT(0x52a6a7a701a751f5), W64LIT(0x2f856666e3661749), + W64LIT(0xe7842121a52115c6), W64LIT(0x60e17f7f9e7fdf1f), W64LIT(0x91128a8a988a241b), W64LIT(0xf59c2727bb2725d2), + W64LIT(0x6f3bc7c7fcc776a8), W64LIT(0x7a27c0c0e7c04eba), W64LIT(0xdfa429298d2955f6), W64LIT(0x1f7bd7d7acd7f6c8) + }, + { + W64LIT(0x769393e593ec4dde), W64LIT(0x43d9d99ad986ec35), W64LIT(0x529a9ac89aa47be1), W64LIT(0xeeb5b55bb5c1992c), + W64LIT(0x5a9898c298b477ef), W64LIT(0x882222aa220dccee), W64LIT(0x0945454c451283c6), W64LIT(0xd7fcfc2bfcb332ce), + W64LIT(0xd2baba68bab9bb01), W64LIT(0xb56a6adf6a77610b), W64LIT(0x5bdfdf84dfb6f827), W64LIT(0x0802020a02100c0e), + W64LIT(0x469f9fd99f8c65fa), W64LIT(0x57dcdc8bdcaef22e), W64LIT(0x5951510851b2fbaa), W64LIT(0x7959592059f2cb92), + W64LIT(0x354a4a7f4a6aa1eb), W64LIT(0x5c17174b17b87265), W64LIT(0xac2b2b872b45fad1), W64LIT(0x2fc2c2edc25eb674), + W64LIT(0x6a9494fe94d45fcb), W64LIT(0xf7f4f403f4f302f6), W64LIT(0xd6bbbb6dbbb1bd06), W64LIT(0xb6a3a315a371ed4e), + W64LIT(0x956262f762375133), W64LIT(0xb7e4e453e4736286), W64LIT(0xd97171a871af3b4a), W64LIT(0x77d4d4a3d4eec216), + W64LIT(0x13cdcddecd269459), W64LIT(0xdd7070ad70a73d4d), W64LIT(0x5816164e16b07462), W64LIT(0xa3e1e142e15b7c9d), + W64LIT(0x394949704972abe2), W64LIT(0xf03c3ccc3cfd88b4), W64LIT(0x27c0c0e7c04eba7a), W64LIT(0x47d8d89fd88eea32), + W64LIT(0x6d5c5c315cdad589), W64LIT(0x569b9bcd9bac7de6), W64LIT(0x8eadad23ad01c964), W64LIT(0x2e8585ab855c39bc), + W64LIT(0x5153530253a2f7a4), W64LIT(0xbea1a11fa161e140), W64LIT(0xf57a7a8f7af7017b), W64LIT(0x07c8c8cfc80e8a42), + W64LIT(0xb42d2d992d75eec3), W64LIT(0xa7e0e047e0537a9a), W64LIT(0x63d1d1b2d1c6dc0d), W64LIT(0xd57272a772b73143), + W64LIT(0xa2a6a604a659f355), W64LIT(0xb02c2c9c2c7de8c4), W64LIT(0x37c4c4f3c46ea266), W64LIT(0xabe3e348e34b7093), + W64LIT(0xc57676b37697295f), W64LIT(0xfd78788578e70d75), W64LIT(0xe6b7b751b7d19522), W64LIT(0xeab4b45eb4c99f2b), + W64LIT(0x2409092d0948363f), W64LIT(0xec3b3bd73bc59aa1), W64LIT(0x380e0e360e70242a), W64LIT(0x1941415841329bda), + W64LIT(0x2d4c4c614c5ab5f9), W64LIT(0x5fdede81debefe20), W64LIT(0xf2b2b240b2f98b39), W64LIT(0x7a9090ea90f447d7), + W64LIT(0x942525b12535defb), W64LIT(0xaea5a50ba541f95c), W64LIT(0x7bd7d7acd7f6c81f), W64LIT(0x0c03030f03180a09), + W64LIT(0x4411115511886677), W64LIT(0x0000000000000000), W64LIT(0x2bc3c3e8c356b073), W64LIT(0xb82e2e962e6de4ca), + W64LIT(0x729292e092e44bd9), W64LIT(0x9befef74ef2b58b7), W64LIT(0x254e4e6b4e4ab9f7), W64LIT(0x4812125a12906c7e), + W64LIT(0x4e9d9dd39d9c69f4), W64LIT(0xe97d7d947dcf136e), W64LIT(0x0bcbcbc0cb16804b), W64LIT(0xd43535e135b5be8b), + W64LIT(0x4010105010806070), W64LIT(0x73d5d5a6d5e6c411), W64LIT(0x214f4f6e4f42bff0), W64LIT(0x429e9edc9e8463fd), + W64LIT(0x294d4d644d52b3fe), W64LIT(0x9ea9a937a921d178), W64LIT(0x4955551c5592e3b6), W64LIT(0x3fc6c6f9c67eae68), + W64LIT(0x67d0d0b7d0ceda0a), W64LIT(0xf17b7b8a7bff077c), W64LIT(0x6018187818c05048), W64LIT(0x669797f197cc55c2), + W64LIT(0x6bd3d3b8d3d6d003), W64LIT(0xd83636ee36adb482), W64LIT(0xbfe6e659e6636e88), W64LIT(0x3d484875487aade5), + W64LIT(0x45565613568ae9bf), W64LIT(0x3e8181bf817c21a0), W64LIT(0x068f8f898f0c058a), W64LIT(0xc17777b6779f2f58), + W64LIT(0x17ccccdbcc2e925e), W64LIT(0x4a9c9cd69c946ff3), W64LIT(0xdeb9b967b9a1b108), W64LIT(0xafe2e24de2437694), + W64LIT(0x8aacac26ac09cf63), W64LIT(0xdab8b862b8a9b70f), W64LIT(0xbc2f2f932f65e2cd), W64LIT(0x5415154115a87e6b), + W64LIT(0xaaa4a40ea449ff5b), W64LIT(0xed7c7c917cc71569), W64LIT(0x4fdada95da9ee63c), W64LIT(0xe03838d838dd90a8), + W64LIT(0x781e1e661ef0445a), W64LIT(0x2c0b0b270b583a31), W64LIT(0x1405051105281e1b), W64LIT(0x7fd6d6a9d6fece18), + W64LIT(0x5014144414a0786c), W64LIT(0xa56e6ecb6e577917), W64LIT(0xad6c6cc16c477519), W64LIT(0xe57e7e9b7ed71967), + W64LIT(0x856666e36617492f), W64LIT(0xd3fdfd2efdbb34c9), W64LIT(0xfeb1b14fb1e18130), W64LIT(0xb3e5e556e57b6481), + W64LIT(0x9d6060fd60275d3d), W64LIT(0x86afaf29af11c56a), W64LIT(0x655e5e3b5ecad987), W64LIT(0xcc3333ff3385aa99), + W64LIT(0x268787a1874c35b2), W64LIT(0x03c9c9cac9068c45), W64LIT(0xe7f0f017f0d31aea), W64LIT(0x695d5d345dd2d38e), + W64LIT(0xa96d6dc46d4f731e), W64LIT(0xfc3f3fc33fe582bd), W64LIT(0x1a8888928834179f), W64LIT(0x0e8d8d838d1c0984), + W64LIT(0x3bc7c7fcc776a86f), W64LIT(0xfbf7f70cf7eb08ff), W64LIT(0x741d1d691de84e53), W64LIT(0x83e9e96ae91b4ca5), + W64LIT(0x97ecec7bec3352be), W64LIT(0x93eded7eed3b54b9), W64LIT(0x3a8080ba807427a7), W64LIT(0xa429298d2955f6df), + W64LIT(0x9c2727bb2725d2f5), W64LIT(0x1bcfcfd4cf369857), W64LIT(0x5e9999c799bc71e8), W64LIT(0x9aa8a832a829d77f), + W64LIT(0x5d50500d50bafdad), W64LIT(0x3c0f0f330f78222d), W64LIT(0xdc3737eb37a5b285), W64LIT(0x902424b4243dd8fc), + W64LIT(0xa0282888285df0d8), W64LIT(0xc03030f0309da090), W64LIT(0x6e9595fb95dc59cc), W64LIT(0x6fd2d2bdd2ded604), + W64LIT(0xf83e3ec63eed84ba), W64LIT(0x715b5b2a5be2c79c), W64LIT(0x1d40405d403a9ddd), W64LIT(0x368383b5836c2dae), + W64LIT(0xf6b3b345b3f18d3e), W64LIT(0xb96969d0696f6b02), W64LIT(0x415757165782efb8), W64LIT(0x7c1f1f631ff8425d), + W64LIT(0x1c07071b07381215), W64LIT(0x701c1c6c1ce04854), W64LIT(0x128a8a988a241b91), W64LIT(0xcabcbc76bc89af13), + W64LIT(0x802020a0201dc0e0), W64LIT(0x8bebeb60eb0b40ab), W64LIT(0x1fceced1ce3e9e50), W64LIT(0x028e8e8c8e04038d), + W64LIT(0x96abab3dab31dd76), W64LIT(0x9feeee71ee235eb0), W64LIT(0xc43131f53195a697), W64LIT(0xb2a2a210a279eb49), + W64LIT(0xd17373a273bf3744), W64LIT(0xc3f9f93af99b2cd5), W64LIT(0x0fcacac5ca1e864c), W64LIT(0xe83a3ad23acd9ca6), + W64LIT(0x681a1a721ad05c46), W64LIT(0xcbfbfb30fb8b20db), W64LIT(0x340d0d390d682e23), W64LIT(0x23c1c1e2c146bc7d), + W64LIT(0xdffefe21fea33ec0), W64LIT(0xcffafa35fa8326dc), W64LIT(0xeff2f21df2c316e4), W64LIT(0xa16f6fce6f5f7f10), + W64LIT(0xcebdbd73bd81a914), W64LIT(0x629696f496c453c5), W64LIT(0x53dddd8edda6f429), W64LIT(0x11434352432297d4), + W64LIT(0x5552520752aaf1a3), W64LIT(0xe2b6b654b6d99325), W64LIT(0x2008082808403038), W64LIT(0xebf3f318f3cb10e3), + W64LIT(0x82aeae2cae19c36d), W64LIT(0xc2bebe7cbe99a31d), W64LIT(0x6419197d19c8564f), W64LIT(0x1e898997893c1198), + W64LIT(0xc83232fa328dac9e), W64LIT(0x982626be262dd4f2), W64LIT(0xfab0b04ab0e98737), W64LIT(0x8feaea65ea0346ac), + W64LIT(0x314b4b7a4b62a7ec), W64LIT(0x8d6464e964074521), W64LIT(0x2a8484ae84543fbb), W64LIT(0x328282b082642ba9), + W64LIT(0xb16b6bda6b7f670c), W64LIT(0xf3f5f506f5fb04f1), W64LIT(0xf979798079ef0b72), W64LIT(0xc6bfbf79bf91a51a), + W64LIT(0x0401010501080607), W64LIT(0x615f5f3e5fc2df80), W64LIT(0xc97575bc758f2356), W64LIT(0x916363f2633f5734), + W64LIT(0x6c1b1b771bd85a41), W64LIT(0x8c2323af2305cae9), W64LIT(0xf43d3dc93df58eb3), W64LIT(0xbd6868d568676d05), + W64LIT(0xa82a2a822a4dfcd6), W64LIT(0x896565ec650f4326), W64LIT(0x87e8e86fe8134aa2), W64LIT(0x7e9191ef91fc41d0), + W64LIT(0xfff6f609f6e30ef8), W64LIT(0xdbffff24ffab38c7), W64LIT(0x4c13135f13986a79), W64LIT(0x7d58582558facd95), + W64LIT(0xe3f1f112f1db1ced), W64LIT(0x0147474647028fc8), W64LIT(0x280a0a220a503c36), W64LIT(0xe17f7f9e7fdf1f60), + W64LIT(0x33c5c5f6c566a461), W64LIT(0xa6a7a701a751f552), W64LIT(0xbbe7e75ce76b688f), W64LIT(0x996161f8612f5b3a), + W64LIT(0x755a5a2f5aeac19b), W64LIT(0x1806061e06301412), W64LIT(0x05464643460a89cf), W64LIT(0x0d444449441a85c1), + W64LIT(0x15424257422a91d3), W64LIT(0x100404140420181c), W64LIT(0xbaa0a01aa069e747), W64LIT(0x4bdbdb90db96e03b), + W64LIT(0xe43939dd39d596af), W64LIT(0x228686a4864433b5), W64LIT(0x4d545419549ae5b1), W64LIT(0x92aaaa38aa39db71), + W64LIT(0x0a8c8c868c140f83), W64LIT(0xd03434e434bdb88c), W64LIT(0x842121a52115c6e7), W64LIT(0x168b8b9d8b2c1d96), + W64LIT(0xc7f8f83ff8932ad2), W64LIT(0x300c0c3c0c602824), W64LIT(0xcd7474b974872551), W64LIT(0x816767e6671f4f28) + }, + { + W64LIT(0x6868d568676d05bd), W64LIT(0x8d8d838d1c09840e), W64LIT(0xcacac5ca1e864c0f), W64LIT(0x4d4d644d52b3fe29), + W64LIT(0x7373a273bf3744d1), W64LIT(0x4b4b7a4b62a7ec31), W64LIT(0x4e4e6b4e4ab9f725), W64LIT(0x2a2a822a4dfcd6a8), + W64LIT(0xd4d4a3d4eec21677), W64LIT(0x52520752aaf1a355), W64LIT(0x2626be262dd4f298), W64LIT(0xb3b345b3f18d3ef6), + W64LIT(0x545419549ae5b14d), W64LIT(0x1e1e661ef0445a78), W64LIT(0x19197d19c8564f64), W64LIT(0x1f1f631ff8425d7c), + W64LIT(0x2222aa220dccee88), W64LIT(0x03030f03180a090c), W64LIT(0x464643460a89cf05), W64LIT(0x3d3dc93df58eb3f4), + W64LIT(0x2d2d992d75eec3b4), W64LIT(0x4a4a7f4a6aa1eb35), W64LIT(0x53530253a2f7a451), W64LIT(0x8383b5836c2dae36), + W64LIT(0x13135f13986a794c), W64LIT(0x8a8a988a241b9112), W64LIT(0xb7b751b7d19522e6), W64LIT(0xd5d5a6d5e6c41173), + W64LIT(0x2525b12535defb94), W64LIT(0x79798079ef0b72f9), W64LIT(0xf5f506f5fb04f1f3), W64LIT(0xbdbd73bd81a914ce), + W64LIT(0x58582558facd957d), W64LIT(0x2f2f932f65e2cdbc), W64LIT(0x0d0d390d682e2334), W64LIT(0x02020a02100c0e08), + W64LIT(0xeded7eed3b54b993), W64LIT(0x51510851b2fbaa59), W64LIT(0x9e9edc9e8463fd42), W64LIT(0x1111551188667744), + W64LIT(0xf2f21df2c316e4ef), W64LIT(0x3e3ec63eed84baf8), W64LIT(0x55551c5592e3b649), W64LIT(0x5e5e3b5ecad98765), + W64LIT(0xd1d1b2d1c6dc0d63), W64LIT(0x16164e16b0746258), W64LIT(0x3c3ccc3cfd88b4f0), W64LIT(0x6666e36617492f85), + W64LIT(0x7070ad70a73d4ddd), W64LIT(0x5d5d345dd2d38e69), W64LIT(0xf3f318f3cb10e3eb), W64LIT(0x45454c451283c609), + W64LIT(0x40405d403a9ddd1d), W64LIT(0xccccdbcc2e925e17), W64LIT(0xe8e86fe8134aa287), W64LIT(0x9494fe94d45fcb6a), + W64LIT(0x565613568ae9bf45), W64LIT(0x0808280840303820), W64LIT(0xceced1ce3e9e501f), W64LIT(0x1a1a721ad05c4668), + W64LIT(0x3a3ad23acd9ca6e8), W64LIT(0xd2d2bdd2ded6046f), W64LIT(0xe1e142e15b7c9da3), W64LIT(0xdfdf84dfb6f8275b), + W64LIT(0xb5b55bb5c1992cee), W64LIT(0x3838d838dd90a8e0), W64LIT(0x6e6ecb6e577917a5), W64LIT(0x0e0e360e70242a38), + W64LIT(0xe5e556e57b6481b3), W64LIT(0xf4f403f4f302f6f7), W64LIT(0xf9f93af99b2cd5c3), W64LIT(0x8686a4864433b522), + W64LIT(0xe9e96ae91b4ca583), W64LIT(0x4f4f6e4f42bff021), W64LIT(0xd6d6a9d6fece187f), W64LIT(0x8585ab855c39bc2e), + W64LIT(0x2323af2305cae98c), W64LIT(0xcfcfd4cf3698571b), W64LIT(0x3232fa328dac9ec8), W64LIT(0x9999c799bc71e85e), + W64LIT(0x3131f53195a697c4), W64LIT(0x14144414a0786c50), W64LIT(0xaeae2cae19c36d82), W64LIT(0xeeee71ee235eb09f), + W64LIT(0xc8c8cfc80e8a4207), W64LIT(0x484875487aade53d), W64LIT(0xd3d3b8d3d6d0036b), W64LIT(0x3030f0309da090c0), + W64LIT(0xa1a11fa161e140be), W64LIT(0x9292e092e44bd972), W64LIT(0x41415841329bda19), W64LIT(0xb1b14fb1e18130fe), + W64LIT(0x18187818c0504860), W64LIT(0xc4c4f3c46ea26637), W64LIT(0x2c2c9c2c7de8c4b0), W64LIT(0x7171a871af3b4ad9), + W64LIT(0x7272a772b73143d5), W64LIT(0x444449441a85c10d), W64LIT(0x15154115a87e6b54), W64LIT(0xfdfd2efdbb34c9d3), + W64LIT(0x3737eb37a5b285dc), W64LIT(0xbebe7cbe99a31dc2), W64LIT(0x5f5f3e5fc2df8061), W64LIT(0xaaaa38aa39db7192), + W64LIT(0x9b9bcd9bac7de656), W64LIT(0x8888928834179f1a), W64LIT(0xd8d89fd88eea3247), W64LIT(0xabab3dab31dd7696), + W64LIT(0x898997893c11981e), W64LIT(0x9c9cd69c946ff34a), W64LIT(0xfafa35fa8326dccf), W64LIT(0x6060fd60275d3d9d), + W64LIT(0xeaea65ea0346ac8f), W64LIT(0xbcbc76bc89af13ca), W64LIT(0x6262f76237513395), W64LIT(0x0c0c3c0c60282430), + W64LIT(0x2424b4243dd8fc90), W64LIT(0xa6a604a659f355a2), W64LIT(0xa8a832a829d77f9a), W64LIT(0xecec7bec3352be97), + W64LIT(0x6767e6671f4f2881), W64LIT(0x2020a0201dc0e080), W64LIT(0xdbdb90db96e03b4b), W64LIT(0x7c7c917cc71569ed), + W64LIT(0x282888285df0d8a0), W64LIT(0xdddd8edda6f42953), W64LIT(0xacac26ac09cf638a), W64LIT(0x5b5b2a5be2c79c71), + W64LIT(0x3434e434bdb88cd0), W64LIT(0x7e7e9b7ed71967e5), W64LIT(0x1010501080607040), W64LIT(0xf1f112f1db1cede3), + W64LIT(0x7b7b8a7bff077cf1), W64LIT(0x8f8f898f0c058a06), W64LIT(0x6363f2633f573491), W64LIT(0xa0a01aa069e747ba), + W64LIT(0x05051105281e1b14), W64LIT(0x9a9ac89aa47be152), W64LIT(0x434352432297d411), W64LIT(0x7777b6779f2f58c1), + W64LIT(0x2121a52115c6e784), W64LIT(0xbfbf79bf91a51ac6), W64LIT(0x2727bb2725d2f59c), W64LIT(0x09092d0948363f24), + W64LIT(0xc3c3e8c356b0732b), W64LIT(0x9f9fd99f8c65fa46), W64LIT(0xb6b654b6d99325e2), W64LIT(0xd7d7acd7f6c81f7b), + W64LIT(0x29298d2955f6dfa4), W64LIT(0xc2c2edc25eb6742f), W64LIT(0xebeb60eb0b40ab8b), W64LIT(0xc0c0e7c04eba7a27), + W64LIT(0xa4a40ea449ff5baa), W64LIT(0x8b8b9d8b2c1d9616), W64LIT(0x8c8c868c140f830a), W64LIT(0x1d1d691de84e5374), + W64LIT(0xfbfb30fb8b20dbcb), W64LIT(0xffff24ffab38c7db), W64LIT(0xc1c1e2c146bc7d23), W64LIT(0xb2b240b2f98b39f2), + W64LIT(0x9797f197cc55c266), W64LIT(0x2e2e962e6de4cab8), W64LIT(0xf8f83ff8932ad2c7), W64LIT(0x6565ec650f432689), + W64LIT(0xf6f609f6e30ef8ff), W64LIT(0x7575bc758f2356c9), W64LIT(0x07071b073812151c), W64LIT(0x0404140420181c10), + W64LIT(0x4949704972abe239), W64LIT(0x3333ff3385aa99cc), W64LIT(0xe4e453e4736286b7), W64LIT(0xd9d99ad986ec3543), + W64LIT(0xb9b967b9a1b108de), W64LIT(0xd0d0b7d0ceda0a67), W64LIT(0x424257422a91d315), W64LIT(0xc7c7fcc776a86f3b), + W64LIT(0x6c6cc16c477519ad), W64LIT(0x9090ea90f447d77a), W64LIT(0x0000000000000000), W64LIT(0x8e8e8c8e04038d02), + W64LIT(0x6f6fce6f5f7f10a1), W64LIT(0x50500d50bafdad5d), W64LIT(0x0101050108060704), W64LIT(0xc5c5f6c566a46133), + W64LIT(0xdada95da9ee63c4f), W64LIT(0x47474647028fc801), W64LIT(0x3f3fc33fe582bdfc), W64LIT(0xcdcddecd26945913), + W64LIT(0x6969d0696f6b02b9), W64LIT(0xa2a210a279eb49b2), W64LIT(0xe2e24de2437694af), W64LIT(0x7a7a8f7af7017bf5), + W64LIT(0xa7a701a751f552a6), W64LIT(0xc6c6f9c67eae683f), W64LIT(0x9393e593ec4dde76), W64LIT(0x0f0f330f78222d3c), + W64LIT(0x0a0a220a503c3628), W64LIT(0x06061e0630141218), W64LIT(0xe6e659e6636e88bf), W64LIT(0x2b2b872b45fad1ac), + W64LIT(0x9696f496c453c562), W64LIT(0xa3a315a371ed4eb6), W64LIT(0x1c1c6c1ce0485470), W64LIT(0xafaf29af11c56a86), + W64LIT(0x6a6adf6a77610bb5), W64LIT(0x12125a12906c7e48), W64LIT(0x8484ae84543fbb2a), W64LIT(0x3939dd39d596afe4), + W64LIT(0xe7e75ce76b688fbb), W64LIT(0xb0b04ab0e98737fa), W64LIT(0x8282b082642ba932), W64LIT(0xf7f70cf7eb08fffb), + W64LIT(0xfefe21fea33ec0df), W64LIT(0x9d9dd39d9c69f44e), W64LIT(0x8787a1874c35b226), W64LIT(0x5c5c315cdad5896d), + W64LIT(0x8181bf817c21a03e), W64LIT(0x3535e135b5be8bd4), W64LIT(0xdede81debefe205f), W64LIT(0xb4b45eb4c99f2bea), + W64LIT(0xa5a50ba541f95cae), W64LIT(0xfcfc2bfcb332ced7), W64LIT(0x8080ba807427a73a), W64LIT(0xefef74ef2b58b79b), + W64LIT(0xcbcbc0cb16804b0b), W64LIT(0xbbbb6dbbb1bd06d6), W64LIT(0x6b6bda6b7f670cb1), W64LIT(0x7676b37697295fc5), + W64LIT(0xbaba68bab9bb01d2), W64LIT(0x5a5a2f5aeac19b75), W64LIT(0x7d7d947dcf136ee9), W64LIT(0x78788578e70d75fd), + W64LIT(0x0b0b270b583a312c), W64LIT(0x9595fb95dc59cc6e), W64LIT(0xe3e348e34b7093ab), W64LIT(0xadad23ad01c9648e), + W64LIT(0x7474b974872551cd), W64LIT(0x9898c298b477ef5a), W64LIT(0x3b3bd73bc59aa1ec), W64LIT(0x3636ee36adb482d8), + W64LIT(0x6464e9640745218d), W64LIT(0x6d6dc46d4f731ea9), W64LIT(0xdcdc8bdcaef22e57), W64LIT(0xf0f017f0d31aeae7), + W64LIT(0x59592059f2cb9279), W64LIT(0xa9a937a921d1789e), W64LIT(0x4c4c614c5ab5f92d), W64LIT(0x17174b17b872655c), + W64LIT(0x7f7f9e7fdf1f60e1), W64LIT(0x9191ef91fc41d07e), W64LIT(0xb8b862b8a9b70fda), W64LIT(0xc9c9cac9068c4503), + W64LIT(0x5757165782efb841), W64LIT(0x1b1b771bd85a416c), W64LIT(0xe0e047e0537a9aa7), W64LIT(0x6161f8612f5b3a99) + } +}; + +const word64 IT[8][256] = +{ + { + W64LIT(0x7826942b9f5f8a9a), W64LIT(0x210f43c934970c53), W64LIT(0x5f028fdd9d0551b8), W64LIT(0x14facd82b494c83b), + W64LIT(0x2b72ab886edd68c0), W64LIT(0xa6a87e5bff19d9b4), W64LIT(0xa29ae571db6443ea), W64LIT(0x039b2c911be8e5b6), + W64LIT(0xd9275dcb5fd32cc6), W64LIT(0x10c856a890e95265), W64LIT(0x7d96e085b27ab85d), W64LIT(0x31c71561a47e5e36), + W64LIT(0x74702455f3d83978), W64LIT(0xe8e048aafbad72f0), W64LIT(0x9b39db4437e03460), W64LIT(0x75f2cbd1fa8091e1), + W64LIT(0x1ab5bee9caa336f6), W64LIT(0x8395a6b8eff34fb9), W64LIT(0x64b872fd63316b1d), W64LIT(0xe1068c7aba0ff3d5), + W64LIT(0xeecb1095cd60a581), W64LIT(0xbc1dc0b235baef42), W64LIT(0xf04c355623be0929), W64LIT(0xb252b3d94b8d118f), + W64LIT(0x18ac7dfcd8137bd9), W64LIT(0xbbb477090a2f90aa), W64LIT(0x8625d216c2d67d7e), W64LIT(0x66a1b1e871812632), + W64LIT(0x6f4775383023a717), W64LIT(0x92df1f947642b545), W64LIT(0xe962a72ef2f5da69), W64LIT(0x8bf18deca7096605), + W64LIT(0xc86de4e7c662d63a), W64LIT(0xaafece25939e6a56), W64LIT(0x5c99a34c86edb40e), W64LIT(0x52d6d027f8da4ac3), + W64LIT(0x6b75ee12145e3d49), W64LIT(0x54fd8818ce179db2), W64LIT(0xa3180af5d23ceb73), W64LIT(0xbe0403a7270aa26d), + W64LIT(0xfe03463d5d89f7e4), W64LIT(0xf1cedad22ae6a1b0), W64LIT(0xd143769f1729057a), W64LIT(0xc7a07808b10d806e), + W64LIT(0xfc1a85284f39bacb), W64LIT(0xa4b1bd4eeda9949b), W64LIT(0x0bff07c55312cc0a), W64LIT(0xef49ff11c4380d18), + W64LIT(0xc392e32295701a30), W64LIT(0x7f8f2390a0caf572), W64LIT(0x62932ac255fcbc6c), W64LIT(0xc9ef0b63cf3a7ea3), + W64LIT(0xf9aaf186621c880c), W64LIT(0x818c65adfd430296), W64LIT(0x325c39f0bf96bb80), W64LIT(0x0c56b07e6c87b3e2), + W64LIT(0x4bf8425f29919983), W64LIT(0xb5fb046274186e67), W64LIT(0x462c1da54c4e82f8), W64LIT(0x90c6dc8164f2f86a), + W64LIT(0xf8281e026b442095), W64LIT(0x6af701961d0695d0), W64LIT(0x5766a489d5ff7804), W64LIT(0xf3d719c73856ec9f), + W64LIT(0xad57799eac0b15be), W64LIT(0x1b37516dc3fb9e6f), W64LIT(0xc009cfb38e98ff86), W64LIT(0x9576a82f49d7caad), + W64LIT(0xe6af3bc1859a8c3d), W64LIT(0x208dac4d3dcfa4ca), W64LIT(0x8ddad5d391c4b174), W64LIT(0x8e41f9428a2c54c2), + W64LIT(0x6cdc59a92bcb42a1), W64LIT(0xe53417509e72698b), W64LIT(0xd0c1991b1e71ade3), W64LIT(0x8217493ce6abe720), + W64LIT(0xd4f302313a0c37bd), W64LIT(0x5e806059945df921), W64LIT(0x73d993eecc4d4690), W64LIT(0xf5fc41f80e9b3bee), + W64LIT(0x13537a398b01b7d3), W64LIT(0x53543fa3f182e25a), W64LIT(0x2d59f3b75810bfb1), W64LIT(0x35f58e4b8003c468), + W64LIT(0x886aa17dbce183b3), W64LIT(0x4c51f5e41604e66b), W64LIT(0x98a2f7d52c08d1d6), W64LIT(0xa101c9e0c08ca65c), + W64LIT(0x4007459a7a835589), W64LIT(0xcc5f7fcde21f4c64), W64LIT(0xa965e2b488768fe0), W64LIT(0x12d195bd82591f4a), + W64LIT(0x2f4030a24aa0f29e), W64LIT(0x56e44b0ddca7d09d), W64LIT(0x914433056daa50f3), W64LIT(0x37ec4d5e92b38947), + W64LIT(0xe31f4f6fa8bfbefa), W64LIT(0x50cf1332ea6a07ec), W64LIT(0x6d5eb62d2293ea38), W64LIT(0x09e6c4d041a28125), + W64LIT(0x8fc316c68374fc5b), W64LIT(0x421e868f683318a6), W64LIT(0xe08463feb3575b4c), W64LIT(0x3821d1b1e5dcdf13), + W64LIT(0xed503c04d6884037), W64LIT(0xd35ab58a05994855), W64LIT(0x976f6b3a5b678782), W64LIT(0x6ec59abc397b0f8e), + W64LIT(0x5929d7e2abc886c9), W64LIT(0xa53352cae4f13c02), W64LIT(0x89e84ef9b5b92b2a), W64LIT(0x1761e113af7c2d8d), + W64LIT(0x28e9871975358d76), W64LIT(0xdc97296572f61e01), W64LIT(0x67235e6c78d98eab), W64LIT(0x3d91a51fc8f9edd4), + W64LIT(0x68eec2830fb6d8ff), W64LIT(0xfbb3329370acc523), W64LIT(0x062b583f36cdd771), W64LIT(0x15782206bdcc60a2), + W64LIT(0x16e30e97a6248514), W64LIT(0x79a47baf96072203), W64LIT(0xf7e582ed1c2b76c1), W64LIT(0xde8eea706046532e), + W64LIT(0xaf4eba8bbebb5891), W64LIT(0x08642b5448fa29bc), W64LIT(0x24bf376719b23e94), W64LIT(0x231680dc2627417c), + W64LIT(0x0dd45ffa65df1b7b), W64LIT(0x1d1c0952f536491e), W64LIT(0xff81a9b954d15f7d), W64LIT(0x992018512550794f), + W64LIT(0x71c050fbdefd0bbf), W64LIT(0xc18b203787c0571f), W64LIT(0x253dd8e310ea960d), W64LIT(0xeb7b643be0459746), + W64LIT(0x0219c31512b04d2f), W64LIT(0xc43b5499aae565d8), W64LIT(0xeaf98bbfe91d3fdf), W64LIT(0x3a3812a4f76c923c), + W64LIT(0x4dd31a601f5c4ef2), W64LIT(0xa8e70d30812e2779), W64LIT(0x800e8a29f41baa0f), W64LIT(0x1c9ee6d6fc6ee187), + W64LIT(0x5d1b4cc88fb51c97), W64LIT(0x610806534e1459da), W64LIT(0xf255f643310e4406), W64LIT(0xd2d85a0e0cc1e0cc), + W64LIT(0x0182ef840958a899), W64LIT(0x7e0dcc14a9925deb), W64LIT(0x653a9d796a69c384), W64LIT(0x4e4836f104b4ab44), + W64LIT(0x4fcad9750dec03dd), W64LIT(0xcddd9049eb47e4fd), W64LIT(0x0e4f736b7e37fecd), W64LIT(0x4185aa1e73dbfd10), + W64LIT(0x725b7c6ac515ee09), W64LIT(0x8a736268ae51ce9c), W64LIT(0xc5b9bb1da3bdcd41), W64LIT(0x7bbdb8ba84b76f2c), + W64LIT(0xdabc715a443bc970), W64LIT(0xe29da0eba1e71663), W64LIT(0x935df0107f1a1ddc), W64LIT(0x608ae9d7474cf143), + W64LIT(0xd571edb533549f24), W64LIT(0xa0832664c9d40ec5), W64LIT(0xfd986aac46611252), W64LIT(0x4435deb05efecfd7), + W64LIT(0x0000000000000000), W64LIT(0x2cdb1c3351481728), W64LIT(0x94f447ab408f6234), W64LIT(0x45b7313457a6674e), + W64LIT(0xb82f5b9811c7751c), W64LIT(0x8c583a57989c19ed), W64LIT(0xdd15c6e17baeb698), W64LIT(0x696c2d0706ee7066), + W64LIT(0x3f88660ada49a0fb), W64LIT(0xf47eae7c07c39377), W64LIT(0x05b074ae2d2532c7), W64LIT(0xb3d05c5d42d5b916), + W64LIT(0x39a33e35ec84778a), W64LIT(0x0fcd9cef776f5654), W64LIT(0xacd5961aa553bd27), W64LIT(0x5b3014f7b978cbe6), + W64LIT(0x347761cf895b6cf1), W64LIT(0xc622978cb85528f7), W64LIT(0xb7e2c77766a82348), W64LIT(0x77eb08c4e830dcce), + W64LIT(0xb9adb41c189fdd85), W64LIT(0x114ab92c99b1fafc), W64LIT(0x26a6f4720b0273bb), W64LIT(0x1e8725c3eedeaca8), + W64LIT(0x2af0440c6785c059), W64LIT(0x04329b2a247d9a5e), W64LIT(0xd7682ea021e4d20b), W64LIT(0x7c140f01bb2210c4), + W64LIT(0x96ed84be523f2f1b), W64LIT(0xca7427f2d4d29b15), W64LIT(0x47aef22145162a61), W64LIT(0xa72a91dff641712d), + W64LIT(0x5ab2fb73b020637f), W64LIT(0xcbf6c876dd8a338c), W64LIT(0x6311c5465ca414f5), W64LIT(0x07a9b7bb3f957fe8), + W64LIT(0xe72dd4458cc224a4), W64LIT(0x9d12837b012de311), W64LIT(0x843c1103d0663051), W64LIT(0x0a7de8415a4a6493), + W64LIT(0xd6eac12428bc7a92), W64LIT(0x9c906cff08754b88), W64LIT(0x7042bf7fd7a5a326), W64LIT(0xbd9f2f363ce247db), + W64LIT(0xb66028f36ff08bd1), W64LIT(0x192e9278d14bd340), W64LIT(0x9f0b406e139dae3e), W64LIT(0x1f05ca47e7860431), + W64LIT(0x85befe87d93e98c8), W64LIT(0x439c690b616bb03f), W64LIT(0xba36988d03773833), W64LIT(0x87a73d92cb8ed5e7), + W64LIT(0xaecc550fb7e3f008), W64LIT(0xc2100ca69c28b2a9), W64LIT(0x9abb34c03eb89cf9), W64LIT(0x49e1814a3b21d4ac), + W64LIT(0xecd2d380dfd0e8ae), W64LIT(0x296b689d7c6d25ef), W64LIT(0x3c134a9bc1a1454d), W64LIT(0xcfc4535cf9f7a9d2), + W64LIT(0x557f679cc74f352b), W64LIT(0xb479ebe67d40c6fe), W64LIT(0xf6676d691573de58), W64LIT(0x9e89afea1ac506a7), + W64LIT(0xd8a5b24f568b845f), W64LIT(0x48636ece32797c35), W64LIT(0xdf0c05f4691efbb7), W64LIT(0xe4b6f8d4972ac112), + W64LIT(0xfa31dd1779f46dba), W64LIT(0xbf86ec232e520af4), W64LIT(0x3e0a898ed3110862), W64LIT(0x7a3f573e8defc7b5), + W64LIT(0x27241bf6025adb22), W64LIT(0x58ab3866a2902e50), W64LIT(0x3bbafd20fe343aa5), W64LIT(0x3045fae5ad26f6af), + W64LIT(0x2ec2df2643f85a07), W64LIT(0x22946f582f7fe9e5), W64LIT(0x366ea2da9beb21de), W64LIT(0x4a7aaddb20c9311a), + W64LIT(0xb1c99f485065f439), W64LIT(0xb04b70cc593d5ca0), W64LIT(0xab7c21a19ac6c2cf), W64LIT(0x33ded674b6ce1319), + W64LIT(0xce46bcd8f0af014b), W64LIT(0xdb3e9ede4d6361e9), W64LIT(0x7669e740e1687457), W64LIT(0x514dfcb6e332af75) + }, + { + W64LIT(0x1f4f6fa8bfbefae3), W64LIT(0xf0440c6785c0592a), W64LIT(0x1dc0b235baef42bc), W64LIT(0x22978cb85528f7c6), + W64LIT(0xcedad22ae6a1b0f1), W64LIT(0x180af5d23ceb73a3), W64LIT(0x946f582f7fe9e522), W64LIT(0xe44b0ddca7d09d56), + W64LIT(0x906cff08754b889c), W64LIT(0x9f2f363ce247dbbd), W64LIT(0xa1b1e87181263266), W64LIT(0x21d1b1e5dcdf1338), + W64LIT(0x31dd1779f46dbafa), W64LIT(0x4b70cc593d5ca0b0), W64LIT(0xd719c73856ec9ff3), W64LIT(0x8725c3eedeaca81e), + W64LIT(0x71edb533549f24d5), W64LIT(0x12837b012de3119d), W64LIT(0x3dd8e310ea960d25), W64LIT(0x29d7e2abc886c959), + W64LIT(0xb477090a2f90aabb), W64LIT(0x45fae5ad26f6af30), W64LIT(0x9ee6d6fc6ee1871c), W64LIT(0xbefe87d93e98c885), + W64LIT(0xe30e97a624851416), W64LIT(0xd6d027f8da4ac352), W64LIT(0xcc550fb7e3f008ae), W64LIT(0x5ab58a05994855d3), + W64LIT(0x806059945df9215e), W64LIT(0x82ef840958a89901), W64LIT(0x4ab92c99b1fafc11), W64LIT(0x281e026b442095f8), + W64LIT(0x62a72ef2f5da69e9), W64LIT(0x8b203787c0571fc1), W64LIT(0x4f736b7e37fecd0e), W64LIT(0xab3866a2902e5058), + W64LIT(0x6ea2da9beb21de36), W64LIT(0xf447ab408f623494), W64LIT(0x235e6c78d98eab67), W64LIT(0x11c5465ca414f563), + W64LIT(0xd31a601f5c4ef24d), W64LIT(0xa2f7d52c08d1d698), W64LIT(0x85aa1e73dbfd1041), W64LIT(0xdc59a92bcb42a16c), + W64LIT(0x59f3b75810bfb12d), W64LIT(0xe2c77766a82348b7), W64LIT(0xb9bb1da3bdcd41c5), W64LIT(0x96e085b27ab85d7d), + W64LIT(0x99a34c86edb40e5c), W64LIT(0x66a489d5ff780457), W64LIT(0x95a6b8eff34fb983), W64LIT(0x7f679cc74f352b55), + W64LIT(0x7de8415a4a64930a), W64LIT(0x9b2c911be8e5b603), W64LIT(0x4836f104b4ab444e), W64LIT(0xdb1c33514817282c), + W64LIT(0x15c6e17baeb698dd), W64LIT(0xed84be523f2f1b96), W64LIT(0xe1814a3b21d4ac49), W64LIT(0x503c04d6884037ed), + W64LIT(0x4c355623be0929f0), W64LIT(0x3b5499aae565d8c4), W64LIT(0x0a898ed31108623e), W64LIT(0xb074ae2d2532c705), + W64LIT(0x028fdd9d0551b85f), W64LIT(0xf58e4b8003c46835), W64LIT(0x3352cae4f13c02a5), W64LIT(0x6c2d0706ee706669), + W64LIT(0x7c21a19ac6c2cfab), W64LIT(0x19c31512b04d2f02), W64LIT(0xa6f4720b0273bb26), W64LIT(0x05ca47e78604311f), + W64LIT(0x46bcd8f0af014bce), W64LIT(0x1e868f683318a642), W64LIT(0x5c39f0bf96bb8032), W64LIT(0x79ebe67d40c6feb4), + W64LIT(0xff07c55312cc0a0b), W64LIT(0xaef22145162a6147), W64LIT(0xc1991b1e71ade3d0), W64LIT(0xded674b6ce131933), + W64LIT(0x7aaddb20c9311a4a), W64LIT(0x4dfcb6e332af7551), W64LIT(0x6de4e7c662d63ac8), W64LIT(0xbf376719b23e9424), + W64LIT(0x07459a7a83558940), W64LIT(0xac7dfcd8137bd918), W64LIT(0xdf1f947642b54592), W64LIT(0x17493ce6abe72082), + W64LIT(0xfc41f80e9b3beef5), W64LIT(0xe70d30812e2779a8), W64LIT(0xd993eecc4d469073), W64LIT(0x65e2b488768fe0a9), + W64LIT(0xd2d380dfd0e8aeec), W64LIT(0xe6c4d041a2812509), W64LIT(0x068c7aba0ff3d5e1), W64LIT(0x51f5e41604e66b4c), + W64LIT(0x41f9428a2c54c28e), W64LIT(0x537a398b01b7d313), W64LIT(0x782206bdcc60a215), W64LIT(0x89afea1ac506a79e), + W64LIT(0x8ae9d7474cf14360), W64LIT(0xf6c876dd8a338ccb), W64LIT(0x43769f1729057ad1), W64LIT(0x8dac4d3dcfa4ca20), + W64LIT(0xb7313457a6674e45), W64LIT(0x2018512550794f99), W64LIT(0xbb34c03eb89cf99a), W64LIT(0xbafd20fe343aa53b), + W64LIT(0x03463d5d89f7e4fe), W64LIT(0x42bf7fd7a5a32670), W64LIT(0x3f573e8defc7b57a), W64LIT(0xadb41c189fdd85b9), + W64LIT(0xcad9750dec03dd4f), W64LIT(0x0f43c934970c5321), W64LIT(0x2f5b9811c7751cb8), W64LIT(0xd85a0e0cc1e0ccd2), + W64LIT(0xe048aafbad72f0e8), W64LIT(0xf18deca70966058b), W64LIT(0xdd9049eb47e4fdcd), W64LIT(0xa87e5bff19d9b4a6), + W64LIT(0x5df0107f1a1ddc93), W64LIT(0xd195bd82591f4a12), W64LIT(0x0c05f4691efbb7df), W64LIT(0x8463feb3575b4ce0), + W64LIT(0x55f643310e4406f2), W64LIT(0xb6f8d4972ac112e4), W64LIT(0x4030a24aa0f29e2f), W64LIT(0xfd8818ce179db254), + W64LIT(0x3c1103d066305184), W64LIT(0x682ea021e4d20bd7), W64LIT(0x81a9b954d15f7dff), W64LIT(0x275dcb5fd32cc6d9), + W64LIT(0xfacd82b494c83b14), W64LIT(0x4433056daa50f391), W64LIT(0xe9871975358d7628), W64LIT(0xeac12428bc7a92d6), + W64LIT(0x1a85284f39bacbfc), W64LIT(0xf8425f299199834b), W64LIT(0x676d691573de58f6), W64LIT(0xd05c5d42d5b916b3), + W64LIT(0x8eea706046532ede), W64LIT(0xfb046274186e67b5), W64LIT(0x134a9bc1a1454d3c), W64LIT(0x57799eac0b15bead), + W64LIT(0x241bf6025adb2227), W64LIT(0x72ab886edd68c02b), W64LIT(0x9ae571db6443eaa2), W64LIT(0xc050fbdefd0bbf71), + W64LIT(0xa5b24f568b845fd8), W64LIT(0xe84ef9b5b92b2a89), W64LIT(0x6f6b3a5b67878297), W64LIT(0xc6dc8164f2f86a90), + W64LIT(0x7eae7c07c39377f4), W64LIT(0x5eb62d2293ea386d), W64LIT(0x8c65adfd43029681), W64LIT(0x2dd4458cc224a4e7), + W64LIT(0xfece25939e6a56aa), W64LIT(0xcd9cef776f56540f), W64LIT(0xa33e35ec84778a39), W64LIT(0xc2df2643f85a072e), + W64LIT(0xbc715a443bc970da), W64LIT(0xa07808b10d806ec7), W64LIT(0x36988d03773833ba), W64LIT(0x1680dc2627417c23), + W64LIT(0xcb1095cd60a581ee), W64LIT(0xbdb8ba84b76f2c7b), W64LIT(0x702455f3d8397874), W64LIT(0x35deb05efecfd744), + W64LIT(0x8f2390a0caf5727f), W64LIT(0xb1bd4eeda9949ba4), W64LIT(0x39db4437e034609b), W64LIT(0xe582ed1c2b76c1f7), + W64LIT(0xc4535cf9f7a9d2cf), W64LIT(0xb2fb73b020637f5a), W64LIT(0x583a57989c19ed8c), W64LIT(0x25d216c2d67d7e86), + W64LIT(0x0806534e1459da61), W64LIT(0x6b689d7c6d25ef29), W64LIT(0x0dcc14a9925deb7e), W64LIT(0xc99f485065f439b1), + W64LIT(0xa9b7bb3f957fe807), W64LIT(0x2a91dff641712da7), W64LIT(0x1c0952f536491e1d), W64LIT(0x75ee12145e3d496b), + W64LIT(0xf98bbfe91d3fdfea), W64LIT(0x92e32295701a30c3), W64LIT(0x3e9ede4d6361e9db), W64LIT(0x76a82f49d7caad95), + W64LIT(0x9da0eba1e71663e2), W64LIT(0x09cfb38e98ff86c0), W64LIT(0x9c690b616bb03f43), W64LIT(0xdad5d391c4b1748d), + W64LIT(0x3812a4f76c923c3a), W64LIT(0x5f7fcde21f4c64cc), W64LIT(0x6aa17dbce183b388), W64LIT(0xeec2830fb6d8ff68), + W64LIT(0x736268ae51ce9c8a), W64LIT(0xa47baf9607220379), W64LIT(0x543fa3f182e25a53), W64LIT(0x4eba8bbebb5891af), + W64LIT(0x2e9278d14bd34019), W64LIT(0x69e740e168745776), W64LIT(0x37516dc3fb9e6f1b), W64LIT(0xb3329370acc523fb), + W64LIT(0x3a9d796a69c38465), W64LIT(0x7761cf895b6cf134), W64LIT(0x0000000000000000), W64LIT(0x88660ada49a0fb3f), + W64LIT(0xb5bee9caa336f61a), W64LIT(0x5b7c6ac515ee0972), W64LIT(0x52b3d94b8d118fb2), W64LIT(0x329b2a247d9a5e04), + W64LIT(0x0e8a29f41baa0f80), W64LIT(0x642b5448fa29bc08), W64LIT(0x7b643be0459746eb), W64LIT(0xd45ffa65df1b7b0d), + W64LIT(0xeb08c4e830dcce77), W64LIT(0xf2cbd1fa8091e175), W64LIT(0xf302313a0c37bdd4), W64LIT(0x91a51fc8f9edd43d), + W64LIT(0xef0b63cf3a7ea3c9), W64LIT(0xc316c68374fc5b8f), W64LIT(0x01c9e0c08ca65ca1), W64LIT(0x3417509e72698be5), + W64LIT(0x4775383023a7176f), W64LIT(0x636ece32797c3548), W64LIT(0x1b4cc88fb51c975d), W64LIT(0x140f01bb2210c47c), + W64LIT(0x7427f2d4d29b15ca), W64LIT(0xa73d92cb8ed5e787), W64LIT(0xc71561a47e5e3631), W64LIT(0xaaf186621c880cf9), + W64LIT(0x6028f36ff08bd1b6), W64LIT(0x97296572f61e01dc), W64LIT(0xc59abc397b0f8e6e), W64LIT(0xec4d5e92b3894737), + W64LIT(0xb872fd63316b1d64), W64LIT(0xaf3bc1859a8c3de6), W64LIT(0x0403a7270aa26dbe), W64LIT(0x26942b9f5f8a9a78), + W64LIT(0x86ec232e520af4bf), W64LIT(0x49ff11c4380d18ef), W64LIT(0xf701961d0695d06a), W64LIT(0x56b07e6c87b3e20c), + W64LIT(0xd5961aa553bd27ac), W64LIT(0x61e113af7c2d8d17), W64LIT(0x100ca69c28b2a9c2), W64LIT(0xcf1332ea6a07ec50), + W64LIT(0xc856a890e9526510), W64LIT(0x2b583f36cdd77106), W64LIT(0x932ac255fcbc6c62), W64LIT(0x0b406e139dae3e9f), + W64LIT(0x832664c9d40ec5a0), W64LIT(0x3014f7b978cbe65b), W64LIT(0x2c1da54c4e82f846), W64LIT(0x986aac46611252fd) + }, + { + W64LIT(0x679cc74f352b557f), W64LIT(0x376719b23e9424bf), W64LIT(0xcc14a9925deb7e0d), W64LIT(0xb07e6c87b3e20c56), + W64LIT(0xa17dbce183b3886a), W64LIT(0xee12145e3d496b75), W64LIT(0x406e139dae3e9f0b), W64LIT(0x942b9f5f8a9a7826), + W64LIT(0xb24f568b845fd8a5), W64LIT(0xdf2643f85a072ec2), W64LIT(0x8c7aba0ff3d5e106), W64LIT(0x0b63cf3a7ea3c9ef), + W64LIT(0x12a4f76c923c3a38), W64LIT(0x8bbfe91d3fdfeaf9), W64LIT(0x9278d14bd340192e), W64LIT(0xca47e78604311f05), + W64LIT(0x07c55312cc0a0bff), W64LIT(0xcfb38e98ff86c009), W64LIT(0x991b1e71ade3d0c1), W64LIT(0x16c68374fc5b8fc3), + W64LIT(0x39f0bf96bb80325c), W64LIT(0x3d92cb8ed5e787a7), W64LIT(0xac4d3dcfa4ca208d), W64LIT(0xfae5ad26f6af3045), + W64LIT(0x63feb3575b4ce084), W64LIT(0x28f36ff08bd1b660), W64LIT(0xc6e17baeb698dd15), W64LIT(0x84be523f2f1b96ed), + W64LIT(0x3c04d6884037ed50), W64LIT(0xce25939e6a56aafe), W64LIT(0xa34c86edb40e5c99), W64LIT(0xebe67d40c6feb479), + W64LIT(0x27f2d4d29b15ca74), W64LIT(0x6d691573de58f667), W64LIT(0x329370acc523fbb3), W64LIT(0x2c911be8e5b6039b), + W64LIT(0x871975358d7628e9), W64LIT(0x550fb7e3f008aecc), W64LIT(0x7e5bff19d9b4a6a8), W64LIT(0xf8d4972ac112e4b6), + W64LIT(0xd1b1e5dcdf133821), W64LIT(0xfcb6e332af75514d), W64LIT(0x1e026b442095f828), W64LIT(0x1f947642b54592df), + W64LIT(0x5e6c78d98eab6723), W64LIT(0x17509e72698be534), W64LIT(0x2ac255fcbc6c6293), W64LIT(0x95bd82591f4a12d1), + W64LIT(0x799eac0b15bead57), W64LIT(0xf0107f1a1ddc935d), W64LIT(0xd674b6ce131933de), W64LIT(0xf5e41604e66b4c51), + W64LIT(0x8818ce179db254fd), W64LIT(0x03a7270aa26dbe04), W64LIT(0x1c33514817282cdb), W64LIT(0x2f363ce247dbbd9f), + W64LIT(0xa72ef2f5da69e962), W64LIT(0x93eecc4d469073d9), W64LIT(0xb92c99b1fafc114a), W64LIT(0x77090a2f90aabbb4), + W64LIT(0x0ca69c28b2a9c210), W64LIT(0xc9e0c08ca65ca101), W64LIT(0x4b0ddca7d09d56e4), W64LIT(0x988d03773833ba36), + W64LIT(0x06534e1459da6108), W64LIT(0x3a57989c19ed8c58), W64LIT(0x0952f536491e1d1c), W64LIT(0x0af5d23ceb73a318), + W64LIT(0x0d30812e2779a8e7), W64LIT(0xd7e2abc886c95929), W64LIT(0xa51fc8f9edd43d91), W64LIT(0x690b616bb03f439c), + W64LIT(0x516dc3fb9e6f1b37), W64LIT(0xa489d5ff78045766), W64LIT(0x52cae4f13c02a533), W64LIT(0x4cc88fb51c975d1b), + W64LIT(0x459a7a8355894007), W64LIT(0x9d796a69c384653a), W64LIT(0x313457a6674e45b7), W64LIT(0x4a9bc1a1454d3c13), + W64LIT(0x6268ae51ce9c8a73), W64LIT(0xfe87d93e98c885be), W64LIT(0xff11c4380d18ef49), W64LIT(0x8deca70966058bf1), + W64LIT(0xdeb05efecfd74435), W64LIT(0xd027f8da4ac352d6), W64LIT(0xf186621c880cf9aa), W64LIT(0x43c934970c53210f), + W64LIT(0xbee9caa336f61ab5), W64LIT(0x56a890e9526510c8), W64LIT(0xe8415a4a64930a7d), W64LIT(0xe32295701a30c392), + W64LIT(0x3e35ec84778a39a3), W64LIT(0x4f6fa8bfbefae31f), W64LIT(0x5dcb5fd32cc6d927), W64LIT(0x9f485065f439b1c9), + W64LIT(0x1095cd60a581eecb), W64LIT(0x978cb85528f7c622), W64LIT(0x7baf9607220379a4), W64LIT(0xd216c2d67d7e8625), + W64LIT(0xe4e7c662d63ac86d), W64LIT(0xb62d2293ea386d5e), W64LIT(0x8a29f41baa0f800e), W64LIT(0x5ffa65df1b7b0dd4), + W64LIT(0x61cf895b6cf13477), W64LIT(0xa6b8eff34fb98395), W64LIT(0x814a3b21d4ac49e1), W64LIT(0xaddb20c9311a4a7a), + W64LIT(0x74ae2d2532c705b0), W64LIT(0x30a24aa0f29e2f40), W64LIT(0x91dff641712da72a), W64LIT(0x9049eb47e4fdcddd), + W64LIT(0x493ce6abe7208217), W64LIT(0x36f104b4ab444e48), W64LIT(0xf22145162a6147ae), W64LIT(0x5c5d42d5b916b3d0), + W64LIT(0xf7d52c08d1d698a2), W64LIT(0x7a398b01b7d31353), W64LIT(0x6cff08754b889c90), W64LIT(0x14f7b978cbe65b30), + W64LIT(0xc4d041a2812509e6), W64LIT(0xe085b27ab85d7d96), W64LIT(0xc0b235baef42bc1d), W64LIT(0x868f683318a6421e), + W64LIT(0xea706046532ede8e), W64LIT(0x4ef9b5b92b2a89e8), W64LIT(0xdc8164f2f86a90c6), W64LIT(0x2455f3d839787470), + W64LIT(0x5499aae565d8c43b), W64LIT(0x59a92bcb42a16cdc), W64LIT(0xa9b954d15f7dff81), W64LIT(0xae7c07c39377f47e), + W64LIT(0x01961d0695d06af7), W64LIT(0xdb4437e034609b39), W64LIT(0x3bc1859a8c3de6af), W64LIT(0xaa1e73dbfd104185), + W64LIT(0x7dfcd8137bd918ac), W64LIT(0x80dc2627417c2316), W64LIT(0xd9750dec03dd4fca), W64LIT(0xc5465ca414f56311), + W64LIT(0x203787c0571fc18b), W64LIT(0xd5d391c4b1748dda), W64LIT(0xc2830fb6d8ff68ee), W64LIT(0xbcd8f0af014bce46), + W64LIT(0xa0eba1e71663e29d), W64LIT(0xfb73b020637f5ab2), W64LIT(0x7c6ac515ee09725b), W64LIT(0x0000000000000000), + W64LIT(0xc876dd8a338ccbf6), W64LIT(0x9cef776f56540fcd), W64LIT(0x47ab408f623494f4), W64LIT(0xcbd1fa8091e175f2), + W64LIT(0x9abc397b0f8e6ec5), W64LIT(0xb58a05994855d35a), W64LIT(0x4d5e92b3894737ec), W64LIT(0x961aa553bd27acd5), + W64LIT(0xc31512b04d2f0219), W64LIT(0xe6d6fc6ee1871c9e), W64LIT(0xe2b488768fe0a965), W64LIT(0xb3d94b8d118fb252), + W64LIT(0x440c6785c0592af0), W64LIT(0x25c3eedeaca81e87), W64LIT(0x583f36cdd771062b), W64LIT(0x2d0706ee7066696c), + W64LIT(0x425f299199834bf8), W64LIT(0xfd20fe343aa53bba), W64LIT(0xf643310e4406f255), W64LIT(0xdad22ae6a1b0f1ce), + W64LIT(0x1da54c4e82f8462c), W64LIT(0x355623be0929f04c), W64LIT(0x769f1729057ad143), W64LIT(0xbd4eeda9949ba4b1), + W64LIT(0xd8e310ea960d253d), W64LIT(0x736b7e37fecd0e4f), W64LIT(0x65adfd430296818c), W64LIT(0xb8ba84b76f2c7bbd), + W64LIT(0x9b2a247d9a5e0432), W64LIT(0xc77766a82348b7e2), W64LIT(0x08c4e830dcce77eb), W64LIT(0x0e97a624851416e3), + W64LIT(0x898ed31108623e0a), W64LIT(0xe571db6443eaa29a), W64LIT(0x573e8defc7b57a3f), W64LIT(0x21a19ac6c2cfab7c), + W64LIT(0x70cc593d5ca0b04b), W64LIT(0x2664c9d40ec5a083), W64LIT(0x296572f61e01dc97), W64LIT(0x85284f39bacbfc1a), + W64LIT(0x715a443bc970dabc), W64LIT(0xef840958a8990182), W64LIT(0xcd82b494c83b14fa), W64LIT(0x48aafbad72f0e8e0), + W64LIT(0xe9d7474cf143608a), W64LIT(0x2390a0caf5727f8f), W64LIT(0xb7bb3f957fe807a9), W64LIT(0x82ed1c2b76c1f7e5), + W64LIT(0xbb1da3bdcd41c5b9), W64LIT(0x72fd63316b1d64b8), W64LIT(0x7808b10d806ec7a0), W64LIT(0x837b012de3119d12), + W64LIT(0x689d7c6d25ef296b), W64LIT(0x02313a0c37bdd4f3), W64LIT(0x1103d0663051843c), W64LIT(0xab886edd68c02b72), + W64LIT(0x6b3a5b678782976f), W64LIT(0xe113af7c2d8d1761), W64LIT(0x6aac46611252fd98), W64LIT(0x50fbdefd0bbf71c0), + W64LIT(0x2ea021e4d20bd768), W64LIT(0x5a0e0cc1e0ccd2d8), W64LIT(0x34c03eb89cf99abb), W64LIT(0xb41c189fdd85b9ad), + W64LIT(0x9ede4d6361e9db3e), W64LIT(0xafea1ac506a79e89), W64LIT(0x463d5d89f7e4fe03), W64LIT(0x18512550794f9920), + W64LIT(0x41f80e9b3beef5fc), W64LIT(0xa82f49d7caad9576), W64LIT(0x0f01bb2210c47c14), W64LIT(0xec232e520af4bf86), + W64LIT(0x1bf6025adb222724), W64LIT(0xa2da9beb21de366e), W64LIT(0xedb533549f24d571), W64LIT(0x643be0459746eb7b), + W64LIT(0xbf7fd7a5a3267042), W64LIT(0x046274186e67b5fb), W64LIT(0x8e4b8003c46835f5), W64LIT(0x1332ea6a07ec50cf), + W64LIT(0xd380dfd0e8aeecd2), W64LIT(0x6f582f7fe9e52294), W64LIT(0xf9428a2c54c28e41), W64LIT(0x3fa3f182e25a5354), + W64LIT(0x535cf9f7a9d2cfc4), W64LIT(0x660ada49a0fb3f88), W64LIT(0x33056daa50f39144), W64LIT(0x8fdd9d0551b85f02), + W64LIT(0x19c73856ec9ff3d7), W64LIT(0xb1e87181263266a1), W64LIT(0x1561a47e5e3631c7), W64LIT(0xd4458cc224a4e72d), + W64LIT(0xe740e16874577669), W64LIT(0xc12428bc7a92d6ea), W64LIT(0x3866a2902e5058ab), W64LIT(0x1a601f5c4ef24dd3), + W64LIT(0x6059945df9215e80), W64LIT(0x05f4691efbb7df0c), W64LIT(0x5b9811c7751cb82f), W64LIT(0x2b5448fa29bc0864), + W64LIT(0xba8bbebb5891af4e), W64LIT(0xf4720b0273bb26a6), W64LIT(0xdd1779f46dbafa31), W64LIT(0x6ece32797c354863), + W64LIT(0x7fcde21f4c64cc5f), W64LIT(0x2206bdcc60a21578), W64LIT(0x75383023a7176f47), W64LIT(0xf3b75810bfb12d59) + }, + { + W64LIT(0x03d0663051843c11), W64LIT(0xbfe91d3fdfeaf98b), W64LIT(0xf80e9b3beef5fc41), W64LIT(0xe5ad26f6af3045fa), + W64LIT(0x5a443bc970dabc71), W64LIT(0x7b012de3119d1283), W64LIT(0x82b494c83b14facd), W64LIT(0x750dec03dd4fcad9), + W64LIT(0x090a2f90aabbb477), W64LIT(0xb6e332af75514dfc), W64LIT(0xadfd430296818c65), W64LIT(0xfd63316b1d64b872), + W64LIT(0x3d5d89f7e4fe0346), W64LIT(0xd7474cf143608ae9), W64LIT(0x7e6c87b3e20c56b0), W64LIT(0x601f5c4ef24dd31a), + W64LIT(0x40e16874577669e7), W64LIT(0x4437e034609b39db), W64LIT(0xe7c662d63ac86de4), W64LIT(0xaf9607220379a47b), + W64LIT(0xea1ac506a79e89af), W64LIT(0xd8f0af014bce46bc), W64LIT(0x7fd7a5a3267042bf), W64LIT(0x9f1729057ad14376), + W64LIT(0x1c189fdd85b9adb4), W64LIT(0x87d93e98c885befe), W64LIT(0x57989c19ed8c583a), W64LIT(0xa4f76c923c3a3812), + W64LIT(0x2a247d9a5e04329b), W64LIT(0xc03eb89cf99abb34), W64LIT(0xf6025adb2227241b), W64LIT(0xa890e9526510c856), + W64LIT(0x06bdcc60a2157822), W64LIT(0xc73856ec9ff3d719), W64LIT(0xcae4f13c02a53352), W64LIT(0xd6fc6ee1871c9ee6), + W64LIT(0xf0bf96bb80325c39), W64LIT(0x13af7c2d8d1761e1), W64LIT(0x3be0459746eb7b64), W64LIT(0x99aae565d8c43b54), + W64LIT(0x95cd60a581eecb10), W64LIT(0x68ae51ce9c8a7362), W64LIT(0xcde21f4c64cc5f7f), W64LIT(0xdc2627417c231680), + W64LIT(0x428a2c54c28e41f9), W64LIT(0x76dd8a338ccbf6c8), W64LIT(0xb8eff34fb98395a6), W64LIT(0xa69c28b2a9c2100c), + W64LIT(0x08b10d806ec7a078), W64LIT(0xc55312cc0a0bff07), W64LIT(0x886edd68c02b72ab), W64LIT(0xdd9d0551b85f028f), + W64LIT(0x1e73dbfd104185aa), W64LIT(0x911be8e5b6039b2c), W64LIT(0x30812e2779a8e70d), W64LIT(0x3a5b678782976f6b), + W64LIT(0x20fe343aa53bbafd), W64LIT(0xb954d15f7dff81a9), W64LIT(0x9a7a835589400745), W64LIT(0x1fc8f9edd43d91a5), + W64LIT(0x0e0cc1e0ccd2d85a), W64LIT(0xbb3f957fe807a9b7), W64LIT(0xc3eedeaca81e8725), W64LIT(0x66a2902e5058ab38), + W64LIT(0xff08754b889c906c), W64LIT(0xfeb3575b4ce08463), W64LIT(0x107f1a1ddc935df0), W64LIT(0x25939e6a56aafece), + W64LIT(0xa92bcb42a16cdc59), W64LIT(0x32ea6a07ec50cf13), W64LIT(0x947642b54592df1f), W64LIT(0x1779f46dbafa31dd), + W64LIT(0x5623be0929f04c35), W64LIT(0xf2d4d29b15ca7427), W64LIT(0x59945df9215e8060), W64LIT(0x9370acc523fbb332), + W64LIT(0xb05efecfd74435de), W64LIT(0x71db6443eaa29ae5), W64LIT(0xe2abc886c95929d7), W64LIT(0x458cc224a4e72dd4), + W64LIT(0xce32797c3548636e), W64LIT(0x1aa553bd27acd596), W64LIT(0x4a3b21d4ac49e181), W64LIT(0x284f39bacbfc1a85), + W64LIT(0xd94b8d118fb252b3), W64LIT(0xb235baef42bc1dc0), W64LIT(0x2643f85a072ec2df), W64LIT(0x8bbebb5891af4eba), + W64LIT(0x89d5ff78045766a4), W64LIT(0xeecc4d469073d993), W64LIT(0x0b616bb03f439c69), W64LIT(0xe41604e66b4c51f5), + W64LIT(0x16c2d67d7e8625d2), W64LIT(0x6c78d98eab67235e), W64LIT(0x9d7c6d25ef296b68), W64LIT(0x64c9d40ec5a08326), + W64LIT(0x2ef2f5da69e962a7), W64LIT(0xfa65df1b7b0dd45f), W64LIT(0x12145e3d496b75ee), W64LIT(0xfcd8137bd918ac7d), + W64LIT(0x52f536491e1d1c09), W64LIT(0xe67d40c6feb479eb), W64LIT(0x2145162a6147aef2), W64LIT(0x29f41baa0f800e8a), + W64LIT(0x0000000000000000), W64LIT(0x840958a8990182ef), W64LIT(0xc88fb51c975d1b4c), W64LIT(0xc68374fc5b8fc316), + W64LIT(0x5d42d5b916b3d05c), W64LIT(0x7dbce183b3886aa1), W64LIT(0x512550794f992018), W64LIT(0xe17baeb698dd15c6), + W64LIT(0x43310e4406f255f6), W64LIT(0x6dc3fb9e6f1b3751), W64LIT(0x86621c880cf9aaf1), W64LIT(0xbc397b0f8e6ec59a), + W64LIT(0x415a4a64930a7de8), W64LIT(0x04d6884037ed503c), W64LIT(0xe9caa336f61ab5be), W64LIT(0x0ada49a0fb3f8866), + W64LIT(0x55f3d83978747024), W64LIT(0x3ce6abe720821749), W64LIT(0xf5d23ceb73a3180a), W64LIT(0xa24aa0f29e2f4030), + W64LIT(0x582f7fe9e522946f), W64LIT(0x7aba0ff3d5e1068c), W64LIT(0x313a0c37bdd4f302), W64LIT(0x3787c0571fc18b20), + W64LIT(0x5cf9f7a9d2cfc453), W64LIT(0xbe523f2f1b96ed84), W64LIT(0x85b27ab85d7d96e0), W64LIT(0x0706ee7066696c2d), + W64LIT(0x961d0695d06af701), W64LIT(0x1b1e71ade3d0c199), W64LIT(0xc255fcbc6c62932a), W64LIT(0x398b01b7d313537a), + W64LIT(0xcc593d5ca0b04b70), W64LIT(0x5f299199834bf842), W64LIT(0x80dfd0e8aeecd2d3), W64LIT(0x9eac0b15bead5779), + W64LIT(0xef776f56540fcd9c), W64LIT(0x2f49d7caad9576a8), W64LIT(0x2c99b1fafc114ab9), W64LIT(0x8d03773833ba3698), + W64LIT(0x720b0273bb26a6f4), W64LIT(0x18ce179db254fd88), W64LIT(0x8f683318a6421e86), W64LIT(0x4f568b845fd8a5b2), + W64LIT(0x8ed31108623e0a89), W64LIT(0xd22ae6a1b0f1ceda), W64LIT(0x74b6ce131933ded6), W64LIT(0x97a624851416e30e), + W64LIT(0x6e139dae3e9f0b40), W64LIT(0xa7270aa26dbe0403), W64LIT(0x5448fa29bc08642b), W64LIT(0xe310ea960d253dd8), + W64LIT(0x706046532ede8eea), W64LIT(0x485065f439b1c99f), W64LIT(0x6b7e37fecd0e4f73), W64LIT(0xfbdefd0bbf71c050), + W64LIT(0xd391c4b1748ddad5), W64LIT(0xa021e4d20bd7682e), W64LIT(0xab408f623494f447), W64LIT(0x5bff19d9b4a6a87e), + W64LIT(0xb1e5dcdf133821d1), W64LIT(0x026b442095f8281e), W64LIT(0xdff641712da72a91), W64LIT(0x11c4380d18ef49ff), + W64LIT(0xae2d2532c705b074), W64LIT(0xc1859a8c3de6af3b), W64LIT(0x4b8003c46835f58e), W64LIT(0x92cb8ed5e787a73d), + W64LIT(0xcb5fd32cc6d9275d), W64LIT(0x8cb85528f7c62297), W64LIT(0x9bc1a1454d3c134a), W64LIT(0x056daa50f3914433), + W64LIT(0xf4691efbb7df0c05), W64LIT(0xd1fa8091e175f2cb), W64LIT(0x7c07c39377f47eae), W64LIT(0x14a9925deb7e0dcc), + W64LIT(0xcf895b6cf1347761), W64LIT(0x0fb7e3f008aecc55), W64LIT(0x8a05994855d35ab5), W64LIT(0xf104b4ab444e4836), + W64LIT(0x691573de58f6676d), W64LIT(0x4eeda9949ba4b1bd), W64LIT(0x2428bc7a92d6eac1), W64LIT(0xb75810bfb12d59f3), + W64LIT(0x63cf3a7ea3c9ef0b), W64LIT(0x6274186e67b5fb04), W64LIT(0x1512b04d2f0219c3), W64LIT(0xe87181263266a1b1), + W64LIT(0x1975358d7628e987), W64LIT(0x534e1459da610806), W64LIT(0x47e78604311f05ca), W64LIT(0xd4972ac112e4b6f8), + W64LIT(0x33514817282cdb1c), W64LIT(0x90a0caf5727f8f23), W64LIT(0x3e8defc7b57a3f57), W64LIT(0x3f36cdd771062b58), + W64LIT(0x796a69c384653a9d), W64LIT(0x465ca414f56311c5), W64LIT(0x5e92b3894737ec4d), W64LIT(0x9811c7751cb82f5b), + W64LIT(0xd041a2812509e6c4), W64LIT(0x49eb47e4fdcddd90), W64LIT(0x78d14bd340192e92), W64LIT(0xf9b5b92b2a89e84e), + W64LIT(0x61a47e5e3631c715), W64LIT(0x509e72698be53417), W64LIT(0xb533549f24d571ed), W64LIT(0x27f8da4ac352d6d0), + W64LIT(0x6572f61e01dc9729), W64LIT(0xde4d6361e9db3e9e), W64LIT(0x3457a6674e45b731), W64LIT(0xa54c4e82f8462c1d), + W64LIT(0xbd82591f4a12d195), W64LIT(0x830fb6d8ff68eec2), W64LIT(0x383023a7176f4775), W64LIT(0x7766a82348b7e2c7), + W64LIT(0x0c6785c0592af044), W64LIT(0xba84b76f2c7bbdb8), W64LIT(0xe0c08ca65ca101c9), W64LIT(0xeba1e71663e29da0), + W64LIT(0xd52c08d1d698a2f7), W64LIT(0xc4e830dcce77eb08), W64LIT(0xda9beb21de366ea2), W64LIT(0xa3f182e25a53543f), + W64LIT(0xac46611252fd986a), W64LIT(0xb38e98ff86c009cf), W64LIT(0xf36ff08bd1b66028), W64LIT(0xdb20c9311a4a7aad), + W64LIT(0xa19ac6c2cfab7c21), W64LIT(0x6ac515ee09725b7c), W64LIT(0x4c86edb40e5c99a3), W64LIT(0x363ce247dbbd9f2f), + W64LIT(0x8164f2f86a90c6dc), W64LIT(0x35ec84778a39a33e), W64LIT(0xb488768fe0a965e2), W64LIT(0x73b020637f5ab2fb), + W64LIT(0x232e520af4bf86ec), W64LIT(0x6fa8bfbefae31f4f), W64LIT(0xeca70966058bf18d), W64LIT(0x1da3bdcd41c5b9bb), + W64LIT(0x9cc74f352b557f67), W64LIT(0x4d3dcfa4ca208dac), W64LIT(0x2b9f5f8a9a782694), W64LIT(0xaafbad72f0e8e048), + W64LIT(0xc934970c53210f43), W64LIT(0xed1c2b76c1f7e582), W64LIT(0x01bb2210c47c140f), W64LIT(0x0ddca7d09d56e44b), + W64LIT(0x2d2293ea386d5eb6), W64LIT(0xf7b978cbe65b3014), W64LIT(0x6719b23e9424bf37), W64LIT(0x2295701a30c392e3) + }, + { + W64LIT(0x9f5f8a9a7826942b), W64LIT(0x34970c53210f43c9), W64LIT(0x9d0551b85f028fdd), W64LIT(0xb494c83b14facd82), + W64LIT(0x6edd68c02b72ab88), W64LIT(0xff19d9b4a6a87e5b), W64LIT(0xdb6443eaa29ae571), W64LIT(0x1be8e5b6039b2c91), + W64LIT(0x5fd32cc6d9275dcb), W64LIT(0x90e9526510c856a8), W64LIT(0xb27ab85d7d96e085), W64LIT(0xa47e5e3631c71561), + W64LIT(0xf3d8397874702455), W64LIT(0xfbad72f0e8e048aa), W64LIT(0x37e034609b39db44), W64LIT(0xfa8091e175f2cbd1), + W64LIT(0xcaa336f61ab5bee9), W64LIT(0xeff34fb98395a6b8), W64LIT(0x63316b1d64b872fd), W64LIT(0xba0ff3d5e1068c7a), + W64LIT(0xcd60a581eecb1095), W64LIT(0x35baef42bc1dc0b2), W64LIT(0x23be0929f04c3556), W64LIT(0x4b8d118fb252b3d9), + W64LIT(0xd8137bd918ac7dfc), W64LIT(0x0a2f90aabbb47709), W64LIT(0xc2d67d7e8625d216), W64LIT(0x7181263266a1b1e8), + W64LIT(0x3023a7176f477538), W64LIT(0x7642b54592df1f94), W64LIT(0xf2f5da69e962a72e), W64LIT(0xa70966058bf18dec), + W64LIT(0xc662d63ac86de4e7), W64LIT(0x939e6a56aafece25), W64LIT(0x86edb40e5c99a34c), W64LIT(0xf8da4ac352d6d027), + W64LIT(0x145e3d496b75ee12), W64LIT(0xce179db254fd8818), W64LIT(0xd23ceb73a3180af5), W64LIT(0x270aa26dbe0403a7), + W64LIT(0x5d89f7e4fe03463d), W64LIT(0x2ae6a1b0f1cedad2), W64LIT(0x1729057ad143769f), W64LIT(0xb10d806ec7a07808), + W64LIT(0x4f39bacbfc1a8528), W64LIT(0xeda9949ba4b1bd4e), W64LIT(0x5312cc0a0bff07c5), W64LIT(0xc4380d18ef49ff11), + W64LIT(0x95701a30c392e322), W64LIT(0xa0caf5727f8f2390), W64LIT(0x55fcbc6c62932ac2), W64LIT(0xcf3a7ea3c9ef0b63), + W64LIT(0x621c880cf9aaf186), W64LIT(0xfd430296818c65ad), W64LIT(0xbf96bb80325c39f0), W64LIT(0x6c87b3e20c56b07e), + W64LIT(0x299199834bf8425f), W64LIT(0x74186e67b5fb0462), W64LIT(0x4c4e82f8462c1da5), W64LIT(0x64f2f86a90c6dc81), + W64LIT(0x6b442095f8281e02), W64LIT(0x1d0695d06af70196), W64LIT(0xd5ff78045766a489), W64LIT(0x3856ec9ff3d719c7), + W64LIT(0xac0b15bead57799e), W64LIT(0xc3fb9e6f1b37516d), W64LIT(0x8e98ff86c009cfb3), W64LIT(0x49d7caad9576a82f), + W64LIT(0x859a8c3de6af3bc1), W64LIT(0x3dcfa4ca208dac4d), W64LIT(0x91c4b1748ddad5d3), W64LIT(0x8a2c54c28e41f942), + W64LIT(0x2bcb42a16cdc59a9), W64LIT(0x9e72698be5341750), W64LIT(0x1e71ade3d0c1991b), W64LIT(0xe6abe7208217493c), + W64LIT(0x3a0c37bdd4f30231), W64LIT(0x945df9215e806059), W64LIT(0xcc4d469073d993ee), W64LIT(0x0e9b3beef5fc41f8), + W64LIT(0x8b01b7d313537a39), W64LIT(0xf182e25a53543fa3), W64LIT(0x5810bfb12d59f3b7), W64LIT(0x8003c46835f58e4b), + W64LIT(0xbce183b3886aa17d), W64LIT(0x1604e66b4c51f5e4), W64LIT(0x2c08d1d698a2f7d5), W64LIT(0xc08ca65ca101c9e0), + W64LIT(0x7a8355894007459a), W64LIT(0xe21f4c64cc5f7fcd), W64LIT(0x88768fe0a965e2b4), W64LIT(0x82591f4a12d195bd), + W64LIT(0x4aa0f29e2f4030a2), W64LIT(0xdca7d09d56e44b0d), W64LIT(0x6daa50f391443305), W64LIT(0x92b3894737ec4d5e), + W64LIT(0xa8bfbefae31f4f6f), W64LIT(0xea6a07ec50cf1332), W64LIT(0x2293ea386d5eb62d), W64LIT(0x41a2812509e6c4d0), + W64LIT(0x8374fc5b8fc316c6), W64LIT(0x683318a6421e868f), W64LIT(0xb3575b4ce08463fe), W64LIT(0xe5dcdf133821d1b1), + W64LIT(0xd6884037ed503c04), W64LIT(0x05994855d35ab58a), W64LIT(0x5b678782976f6b3a), W64LIT(0x397b0f8e6ec59abc), + W64LIT(0xabc886c95929d7e2), W64LIT(0xe4f13c02a53352ca), W64LIT(0xb5b92b2a89e84ef9), W64LIT(0xaf7c2d8d1761e113), + W64LIT(0x75358d7628e98719), W64LIT(0x72f61e01dc972965), W64LIT(0x78d98eab67235e6c), W64LIT(0xc8f9edd43d91a51f), + W64LIT(0x0fb6d8ff68eec283), W64LIT(0x70acc523fbb33293), W64LIT(0x36cdd771062b583f), W64LIT(0xbdcc60a215782206), + W64LIT(0xa624851416e30e97), W64LIT(0x9607220379a47baf), W64LIT(0x1c2b76c1f7e582ed), W64LIT(0x6046532ede8eea70), + W64LIT(0xbebb5891af4eba8b), W64LIT(0x48fa29bc08642b54), W64LIT(0x19b23e9424bf3767), W64LIT(0x2627417c231680dc), + W64LIT(0x65df1b7b0dd45ffa), W64LIT(0xf536491e1d1c0952), W64LIT(0x54d15f7dff81a9b9), W64LIT(0x2550794f99201851), + W64LIT(0xdefd0bbf71c050fb), W64LIT(0x87c0571fc18b2037), W64LIT(0x10ea960d253dd8e3), W64LIT(0xe0459746eb7b643b), + W64LIT(0x12b04d2f0219c315), W64LIT(0xaae565d8c43b5499), W64LIT(0xe91d3fdfeaf98bbf), W64LIT(0xf76c923c3a3812a4), + W64LIT(0x1f5c4ef24dd31a60), W64LIT(0x812e2779a8e70d30), W64LIT(0xf41baa0f800e8a29), W64LIT(0xfc6ee1871c9ee6d6), + W64LIT(0x8fb51c975d1b4cc8), W64LIT(0x4e1459da61080653), W64LIT(0x310e4406f255f643), W64LIT(0x0cc1e0ccd2d85a0e), + W64LIT(0x0958a8990182ef84), W64LIT(0xa9925deb7e0dcc14), W64LIT(0x6a69c384653a9d79), W64LIT(0x04b4ab444e4836f1), + W64LIT(0x0dec03dd4fcad975), W64LIT(0xeb47e4fdcddd9049), W64LIT(0x7e37fecd0e4f736b), W64LIT(0x73dbfd104185aa1e), + W64LIT(0xc515ee09725b7c6a), W64LIT(0xae51ce9c8a736268), W64LIT(0xa3bdcd41c5b9bb1d), W64LIT(0x84b76f2c7bbdb8ba), + W64LIT(0x443bc970dabc715a), W64LIT(0xa1e71663e29da0eb), W64LIT(0x7f1a1ddc935df010), W64LIT(0x474cf143608ae9d7), + W64LIT(0x33549f24d571edb5), W64LIT(0xc9d40ec5a0832664), W64LIT(0x46611252fd986aac), W64LIT(0x5efecfd74435deb0), + W64LIT(0x0000000000000000), W64LIT(0x514817282cdb1c33), W64LIT(0x408f623494f447ab), W64LIT(0x57a6674e45b73134), + W64LIT(0x11c7751cb82f5b98), W64LIT(0x989c19ed8c583a57), W64LIT(0x7baeb698dd15c6e1), W64LIT(0x06ee7066696c2d07), + W64LIT(0xda49a0fb3f88660a), W64LIT(0x07c39377f47eae7c), W64LIT(0x2d2532c705b074ae), W64LIT(0x42d5b916b3d05c5d), + W64LIT(0xec84778a39a33e35), W64LIT(0x776f56540fcd9cef), W64LIT(0xa553bd27acd5961a), W64LIT(0xb978cbe65b3014f7), + W64LIT(0x895b6cf1347761cf), W64LIT(0xb85528f7c622978c), W64LIT(0x66a82348b7e2c777), W64LIT(0xe830dcce77eb08c4), + W64LIT(0x189fdd85b9adb41c), W64LIT(0x99b1fafc114ab92c), W64LIT(0x0b0273bb26a6f472), W64LIT(0xeedeaca81e8725c3), + W64LIT(0x6785c0592af0440c), W64LIT(0x247d9a5e04329b2a), W64LIT(0x21e4d20bd7682ea0), W64LIT(0xbb2210c47c140f01), + W64LIT(0x523f2f1b96ed84be), W64LIT(0xd4d29b15ca7427f2), W64LIT(0x45162a6147aef221), W64LIT(0xf641712da72a91df), + W64LIT(0xb020637f5ab2fb73), W64LIT(0xdd8a338ccbf6c876), W64LIT(0x5ca414f56311c546), W64LIT(0x3f957fe807a9b7bb), + W64LIT(0x8cc224a4e72dd445), W64LIT(0x012de3119d12837b), W64LIT(0xd0663051843c1103), W64LIT(0x5a4a64930a7de841), + W64LIT(0x28bc7a92d6eac124), W64LIT(0x08754b889c906cff), W64LIT(0xd7a5a3267042bf7f), W64LIT(0x3ce247dbbd9f2f36), + W64LIT(0x6ff08bd1b66028f3), W64LIT(0xd14bd340192e9278), W64LIT(0x139dae3e9f0b406e), W64LIT(0xe78604311f05ca47), + W64LIT(0xd93e98c885befe87), W64LIT(0x616bb03f439c690b), W64LIT(0x03773833ba36988d), W64LIT(0xcb8ed5e787a73d92), + W64LIT(0xb7e3f008aecc550f), W64LIT(0x9c28b2a9c2100ca6), W64LIT(0x3eb89cf99abb34c0), W64LIT(0x3b21d4ac49e1814a), + W64LIT(0xdfd0e8aeecd2d380), W64LIT(0x7c6d25ef296b689d), W64LIT(0xc1a1454d3c134a9b), W64LIT(0xf9f7a9d2cfc4535c), + W64LIT(0xc74f352b557f679c), W64LIT(0x7d40c6feb479ebe6), W64LIT(0x1573de58f6676d69), W64LIT(0x1ac506a79e89afea), + W64LIT(0x568b845fd8a5b24f), W64LIT(0x32797c3548636ece), W64LIT(0x691efbb7df0c05f4), W64LIT(0x972ac112e4b6f8d4), + W64LIT(0x79f46dbafa31dd17), W64LIT(0x2e520af4bf86ec23), W64LIT(0xd31108623e0a898e), W64LIT(0x8defc7b57a3f573e), + W64LIT(0x025adb2227241bf6), W64LIT(0xa2902e5058ab3866), W64LIT(0xfe343aa53bbafd20), W64LIT(0xad26f6af3045fae5), + W64LIT(0x43f85a072ec2df26), W64LIT(0x2f7fe9e522946f58), W64LIT(0x9beb21de366ea2da), W64LIT(0x20c9311a4a7aaddb), + W64LIT(0x5065f439b1c99f48), W64LIT(0x593d5ca0b04b70cc), W64LIT(0x9ac6c2cfab7c21a1), W64LIT(0xb6ce131933ded674), + W64LIT(0xf0af014bce46bcd8), W64LIT(0x4d6361e9db3e9ede), W64LIT(0xe16874577669e740), W64LIT(0xe332af75514dfcb6) + }, + { + W64LIT(0xbfbefae31f4f6fa8), W64LIT(0x85c0592af0440c67), W64LIT(0xbaef42bc1dc0b235), W64LIT(0x5528f7c622978cb8), + W64LIT(0xe6a1b0f1cedad22a), W64LIT(0x3ceb73a3180af5d2), W64LIT(0x7fe9e522946f582f), W64LIT(0xa7d09d56e44b0ddc), + W64LIT(0x754b889c906cff08), W64LIT(0xe247dbbd9f2f363c), W64LIT(0x81263266a1b1e871), W64LIT(0xdcdf133821d1b1e5), + W64LIT(0xf46dbafa31dd1779), W64LIT(0x3d5ca0b04b70cc59), W64LIT(0x56ec9ff3d719c738), W64LIT(0xdeaca81e8725c3ee), + W64LIT(0x549f24d571edb533), W64LIT(0x2de3119d12837b01), W64LIT(0xea960d253dd8e310), W64LIT(0xc886c95929d7e2ab), + W64LIT(0x2f90aabbb477090a), W64LIT(0x26f6af3045fae5ad), W64LIT(0x6ee1871c9ee6d6fc), W64LIT(0x3e98c885befe87d9), + W64LIT(0x24851416e30e97a6), W64LIT(0xda4ac352d6d027f8), W64LIT(0xe3f008aecc550fb7), W64LIT(0x994855d35ab58a05), + W64LIT(0x5df9215e80605994), W64LIT(0x58a8990182ef8409), W64LIT(0xb1fafc114ab92c99), W64LIT(0x442095f8281e026b), + W64LIT(0xf5da69e962a72ef2), W64LIT(0xc0571fc18b203787), W64LIT(0x37fecd0e4f736b7e), W64LIT(0x902e5058ab3866a2), + W64LIT(0xeb21de366ea2da9b), W64LIT(0x8f623494f447ab40), W64LIT(0xd98eab67235e6c78), W64LIT(0xa414f56311c5465c), + W64LIT(0x5c4ef24dd31a601f), W64LIT(0x08d1d698a2f7d52c), W64LIT(0xdbfd104185aa1e73), W64LIT(0xcb42a16cdc59a92b), + W64LIT(0x10bfb12d59f3b758), W64LIT(0xa82348b7e2c77766), W64LIT(0xbdcd41c5b9bb1da3), W64LIT(0x7ab85d7d96e085b2), + W64LIT(0xedb40e5c99a34c86), W64LIT(0xff78045766a489d5), W64LIT(0xf34fb98395a6b8ef), W64LIT(0x4f352b557f679cc7), + W64LIT(0x4a64930a7de8415a), W64LIT(0xe8e5b6039b2c911b), W64LIT(0xb4ab444e4836f104), W64LIT(0x4817282cdb1c3351), + W64LIT(0xaeb698dd15c6e17b), W64LIT(0x3f2f1b96ed84be52), W64LIT(0x21d4ac49e1814a3b), W64LIT(0x884037ed503c04d6), + W64LIT(0xbe0929f04c355623), W64LIT(0xe565d8c43b5499aa), W64LIT(0x1108623e0a898ed3), W64LIT(0x2532c705b074ae2d), + W64LIT(0x0551b85f028fdd9d), W64LIT(0x03c46835f58e4b80), W64LIT(0xf13c02a53352cae4), W64LIT(0xee7066696c2d0706), + W64LIT(0xc6c2cfab7c21a19a), W64LIT(0xb04d2f0219c31512), W64LIT(0x0273bb26a6f4720b), W64LIT(0x8604311f05ca47e7), + W64LIT(0xaf014bce46bcd8f0), W64LIT(0x3318a6421e868f68), W64LIT(0x96bb80325c39f0bf), W64LIT(0x40c6feb479ebe67d), + W64LIT(0x12cc0a0bff07c553), W64LIT(0x162a6147aef22145), W64LIT(0x71ade3d0c1991b1e), W64LIT(0xce131933ded674b6), + W64LIT(0xc9311a4a7aaddb20), W64LIT(0x32af75514dfcb6e3), W64LIT(0x62d63ac86de4e7c6), W64LIT(0xb23e9424bf376719), + W64LIT(0x8355894007459a7a), W64LIT(0x137bd918ac7dfcd8), W64LIT(0x42b54592df1f9476), W64LIT(0xabe7208217493ce6), + W64LIT(0x9b3beef5fc41f80e), W64LIT(0x2e2779a8e70d3081), W64LIT(0x4d469073d993eecc), W64LIT(0x768fe0a965e2b488), + W64LIT(0xd0e8aeecd2d380df), W64LIT(0xa2812509e6c4d041), W64LIT(0x0ff3d5e1068c7aba), W64LIT(0x04e66b4c51f5e416), + W64LIT(0x2c54c28e41f9428a), W64LIT(0x01b7d313537a398b), W64LIT(0xcc60a215782206bd), W64LIT(0xc506a79e89afea1a), + W64LIT(0x4cf143608ae9d747), W64LIT(0x8a338ccbf6c876dd), W64LIT(0x29057ad143769f17), W64LIT(0xcfa4ca208dac4d3d), + W64LIT(0xa6674e45b7313457), W64LIT(0x50794f9920185125), W64LIT(0xb89cf99abb34c03e), W64LIT(0x343aa53bbafd20fe), + W64LIT(0x89f7e4fe03463d5d), W64LIT(0xa5a3267042bf7fd7), W64LIT(0xefc7b57a3f573e8d), W64LIT(0x9fdd85b9adb41c18), + W64LIT(0xec03dd4fcad9750d), W64LIT(0x970c53210f43c934), W64LIT(0xc7751cb82f5b9811), W64LIT(0xc1e0ccd2d85a0e0c), + W64LIT(0xad72f0e8e048aafb), W64LIT(0x0966058bf18deca7), W64LIT(0x47e4fdcddd9049eb), W64LIT(0x19d9b4a6a87e5bff), + W64LIT(0x1a1ddc935df0107f), W64LIT(0x591f4a12d195bd82), W64LIT(0x1efbb7df0c05f469), W64LIT(0x575b4ce08463feb3), + W64LIT(0x0e4406f255f64331), W64LIT(0x2ac112e4b6f8d497), W64LIT(0xa0f29e2f4030a24a), W64LIT(0x179db254fd8818ce), + W64LIT(0x663051843c1103d0), W64LIT(0xe4d20bd7682ea021), W64LIT(0xd15f7dff81a9b954), W64LIT(0xd32cc6d9275dcb5f), + W64LIT(0x94c83b14facd82b4), W64LIT(0xaa50f3914433056d), W64LIT(0x358d7628e9871975), W64LIT(0xbc7a92d6eac12428), + W64LIT(0x39bacbfc1a85284f), W64LIT(0x9199834bf8425f29), W64LIT(0x73de58f6676d6915), W64LIT(0xd5b916b3d05c5d42), + W64LIT(0x46532ede8eea7060), W64LIT(0x186e67b5fb046274), W64LIT(0xa1454d3c134a9bc1), W64LIT(0x0b15bead57799eac), + W64LIT(0x5adb2227241bf602), W64LIT(0xdd68c02b72ab886e), W64LIT(0x6443eaa29ae571db), W64LIT(0xfd0bbf71c050fbde), + W64LIT(0x8b845fd8a5b24f56), W64LIT(0xb92b2a89e84ef9b5), W64LIT(0x678782976f6b3a5b), W64LIT(0xf2f86a90c6dc8164), + W64LIT(0xc39377f47eae7c07), W64LIT(0x93ea386d5eb62d22), W64LIT(0x430296818c65adfd), W64LIT(0xc224a4e72dd4458c), + W64LIT(0x9e6a56aafece2593), W64LIT(0x6f56540fcd9cef77), W64LIT(0x84778a39a33e35ec), W64LIT(0xf85a072ec2df2643), + W64LIT(0x3bc970dabc715a44), W64LIT(0x0d806ec7a07808b1), W64LIT(0x773833ba36988d03), W64LIT(0x27417c231680dc26), + W64LIT(0x60a581eecb1095cd), W64LIT(0xb76f2c7bbdb8ba84), W64LIT(0xd8397874702455f3), W64LIT(0xfecfd74435deb05e), + W64LIT(0xcaf5727f8f2390a0), W64LIT(0xa9949ba4b1bd4eed), W64LIT(0xe034609b39db4437), W64LIT(0x2b76c1f7e582ed1c), + W64LIT(0xf7a9d2cfc4535cf9), W64LIT(0x20637f5ab2fb73b0), W64LIT(0x9c19ed8c583a5798), W64LIT(0xd67d7e8625d216c2), + W64LIT(0x1459da610806534e), W64LIT(0x6d25ef296b689d7c), W64LIT(0x925deb7e0dcc14a9), W64LIT(0x65f439b1c99f4850), + W64LIT(0x957fe807a9b7bb3f), W64LIT(0x41712da72a91dff6), W64LIT(0x36491e1d1c0952f5), W64LIT(0x5e3d496b75ee1214), + W64LIT(0x1d3fdfeaf98bbfe9), W64LIT(0x701a30c392e32295), W64LIT(0x6361e9db3e9ede4d), W64LIT(0xd7caad9576a82f49), + W64LIT(0xe71663e29da0eba1), W64LIT(0x98ff86c009cfb38e), W64LIT(0x6bb03f439c690b61), W64LIT(0xc4b1748ddad5d391), + W64LIT(0x6c923c3a3812a4f7), W64LIT(0x1f4c64cc5f7fcde2), W64LIT(0xe183b3886aa17dbc), W64LIT(0xb6d8ff68eec2830f), + W64LIT(0x51ce9c8a736268ae), W64LIT(0x07220379a47baf96), W64LIT(0x82e25a53543fa3f1), W64LIT(0xbb5891af4eba8bbe), + W64LIT(0x4bd340192e9278d1), W64LIT(0x6874577669e740e1), W64LIT(0xfb9e6f1b37516dc3), W64LIT(0xacc523fbb3329370), + W64LIT(0x69c384653a9d796a), W64LIT(0x5b6cf1347761cf89), W64LIT(0x0000000000000000), W64LIT(0x49a0fb3f88660ada), + W64LIT(0xa336f61ab5bee9ca), W64LIT(0x15ee09725b7c6ac5), W64LIT(0x8d118fb252b3d94b), W64LIT(0x7d9a5e04329b2a24), + W64LIT(0x1baa0f800e8a29f4), W64LIT(0xfa29bc08642b5448), W64LIT(0x459746eb7b643be0), W64LIT(0xdf1b7b0dd45ffa65), + W64LIT(0x30dcce77eb08c4e8), W64LIT(0x8091e175f2cbd1fa), W64LIT(0x0c37bdd4f302313a), W64LIT(0xf9edd43d91a51fc8), + W64LIT(0x3a7ea3c9ef0b63cf), W64LIT(0x74fc5b8fc316c683), W64LIT(0x8ca65ca101c9e0c0), W64LIT(0x72698be53417509e), + W64LIT(0x23a7176f47753830), W64LIT(0x797c3548636ece32), W64LIT(0xb51c975d1b4cc88f), W64LIT(0x2210c47c140f01bb), + W64LIT(0xd29b15ca7427f2d4), W64LIT(0x8ed5e787a73d92cb), W64LIT(0x7e5e3631c71561a4), W64LIT(0x1c880cf9aaf18662), + W64LIT(0xf08bd1b66028f36f), W64LIT(0xf61e01dc97296572), W64LIT(0x7b0f8e6ec59abc39), W64LIT(0xb3894737ec4d5e92), + W64LIT(0x316b1d64b872fd63), W64LIT(0x9a8c3de6af3bc185), W64LIT(0x0aa26dbe0403a727), W64LIT(0x5f8a9a7826942b9f), + W64LIT(0x520af4bf86ec232e), W64LIT(0x380d18ef49ff11c4), W64LIT(0x0695d06af701961d), W64LIT(0x87b3e20c56b07e6c), + W64LIT(0x53bd27acd5961aa5), W64LIT(0x7c2d8d1761e113af), W64LIT(0x28b2a9c2100ca69c), W64LIT(0x6a07ec50cf1332ea), + W64LIT(0xe9526510c856a890), W64LIT(0xcdd771062b583f36), W64LIT(0xfcbc6c62932ac255), W64LIT(0x9dae3e9f0b406e13), + W64LIT(0xd40ec5a0832664c9), W64LIT(0x78cbe65b3014f7b9), W64LIT(0x4e82f8462c1da54c), W64LIT(0x611252fd986aac46) + }, + { + W64LIT(0x352b557f679cc74f), W64LIT(0x3e9424bf376719b2), W64LIT(0x5deb7e0dcc14a992), W64LIT(0xb3e20c56b07e6c87), + W64LIT(0x83b3886aa17dbce1), W64LIT(0x3d496b75ee12145e), W64LIT(0xae3e9f0b406e139d), W64LIT(0x8a9a7826942b9f5f), + W64LIT(0x845fd8a5b24f568b), W64LIT(0x5a072ec2df2643f8), W64LIT(0xf3d5e1068c7aba0f), W64LIT(0x7ea3c9ef0b63cf3a), + W64LIT(0x923c3a3812a4f76c), W64LIT(0x3fdfeaf98bbfe91d), W64LIT(0xd340192e9278d14b), W64LIT(0x04311f05ca47e786), + W64LIT(0xcc0a0bff07c55312), W64LIT(0xff86c009cfb38e98), W64LIT(0xade3d0c1991b1e71), W64LIT(0xfc5b8fc316c68374), + W64LIT(0xbb80325c39f0bf96), W64LIT(0xd5e787a73d92cb8e), W64LIT(0xa4ca208dac4d3dcf), W64LIT(0xf6af3045fae5ad26), + W64LIT(0x5b4ce08463feb357), W64LIT(0x8bd1b66028f36ff0), W64LIT(0xb698dd15c6e17bae), W64LIT(0x2f1b96ed84be523f), + W64LIT(0x4037ed503c04d688), W64LIT(0x6a56aafece25939e), W64LIT(0xb40e5c99a34c86ed), W64LIT(0xc6feb479ebe67d40), + W64LIT(0x9b15ca7427f2d4d2), W64LIT(0xde58f6676d691573), W64LIT(0xc523fbb3329370ac), W64LIT(0xe5b6039b2c911be8), + W64LIT(0x8d7628e987197535), W64LIT(0xf008aecc550fb7e3), W64LIT(0xd9b4a6a87e5bff19), W64LIT(0xc112e4b6f8d4972a), + W64LIT(0xdf133821d1b1e5dc), W64LIT(0xaf75514dfcb6e332), W64LIT(0x2095f8281e026b44), W64LIT(0xb54592df1f947642), + W64LIT(0x8eab67235e6c78d9), W64LIT(0x698be53417509e72), W64LIT(0xbc6c62932ac255fc), W64LIT(0x1f4a12d195bd8259), + W64LIT(0x15bead57799eac0b), W64LIT(0x1ddc935df0107f1a), W64LIT(0x131933ded674b6ce), W64LIT(0xe66b4c51f5e41604), + W64LIT(0x9db254fd8818ce17), W64LIT(0xa26dbe0403a7270a), W64LIT(0x17282cdb1c335148), W64LIT(0x47dbbd9f2f363ce2), + W64LIT(0xda69e962a72ef2f5), W64LIT(0x469073d993eecc4d), W64LIT(0xfafc114ab92c99b1), W64LIT(0x90aabbb477090a2f), + W64LIT(0xb2a9c2100ca69c28), W64LIT(0xa65ca101c9e0c08c), W64LIT(0xd09d56e44b0ddca7), W64LIT(0x3833ba36988d0377), + W64LIT(0x59da610806534e14), W64LIT(0x19ed8c583a57989c), W64LIT(0x491e1d1c0952f536), W64LIT(0xeb73a3180af5d23c), + W64LIT(0x2779a8e70d30812e), W64LIT(0x86c95929d7e2abc8), W64LIT(0xedd43d91a51fc8f9), W64LIT(0xb03f439c690b616b), + W64LIT(0x9e6f1b37516dc3fb), W64LIT(0x78045766a489d5ff), W64LIT(0x3c02a53352cae4f1), W64LIT(0x1c975d1b4cc88fb5), + W64LIT(0x55894007459a7a83), W64LIT(0xc384653a9d796a69), W64LIT(0x674e45b7313457a6), W64LIT(0x454d3c134a9bc1a1), + W64LIT(0xce9c8a736268ae51), W64LIT(0x98c885befe87d93e), W64LIT(0x0d18ef49ff11c438), W64LIT(0x66058bf18deca709), + W64LIT(0xcfd74435deb05efe), W64LIT(0x4ac352d6d027f8da), W64LIT(0x880cf9aaf186621c), W64LIT(0x0c53210f43c93497), + W64LIT(0x36f61ab5bee9caa3), W64LIT(0x526510c856a890e9), W64LIT(0x64930a7de8415a4a), W64LIT(0x1a30c392e3229570), + W64LIT(0x778a39a33e35ec84), W64LIT(0xbefae31f4f6fa8bf), W64LIT(0x2cc6d9275dcb5fd3), W64LIT(0xf439b1c99f485065), + W64LIT(0xa581eecb1095cd60), W64LIT(0x28f7c622978cb855), W64LIT(0x220379a47baf9607), W64LIT(0x7d7e8625d216c2d6), + W64LIT(0xd63ac86de4e7c662), W64LIT(0xea386d5eb62d2293), W64LIT(0xaa0f800e8a29f41b), W64LIT(0x1b7b0dd45ffa65df), + W64LIT(0x6cf1347761cf895b), W64LIT(0x4fb98395a6b8eff3), W64LIT(0xd4ac49e1814a3b21), W64LIT(0x311a4a7aaddb20c9), + W64LIT(0x32c705b074ae2d25), W64LIT(0xf29e2f4030a24aa0), W64LIT(0x712da72a91dff641), W64LIT(0xe4fdcddd9049eb47), + W64LIT(0xe7208217493ce6ab), W64LIT(0xab444e4836f104b4), W64LIT(0x2a6147aef2214516), W64LIT(0xb916b3d05c5d42d5), + W64LIT(0xd1d698a2f7d52c08), W64LIT(0xb7d313537a398b01), W64LIT(0x4b889c906cff0875), W64LIT(0xcbe65b3014f7b978), + W64LIT(0x812509e6c4d041a2), W64LIT(0xb85d7d96e085b27a), W64LIT(0xef42bc1dc0b235ba), W64LIT(0x18a6421e868f6833), + W64LIT(0x532ede8eea706046), W64LIT(0x2b2a89e84ef9b5b9), W64LIT(0xf86a90c6dc8164f2), W64LIT(0x397874702455f3d8), + W64LIT(0x65d8c43b5499aae5), W64LIT(0x42a16cdc59a92bcb), W64LIT(0x5f7dff81a9b954d1), W64LIT(0x9377f47eae7c07c3), + W64LIT(0x95d06af701961d06), W64LIT(0x34609b39db4437e0), W64LIT(0x8c3de6af3bc1859a), W64LIT(0xfd104185aa1e73db), + W64LIT(0x7bd918ac7dfcd813), W64LIT(0x417c231680dc2627), W64LIT(0x03dd4fcad9750dec), W64LIT(0x14f56311c5465ca4), + W64LIT(0x571fc18b203787c0), W64LIT(0xb1748ddad5d391c4), W64LIT(0xd8ff68eec2830fb6), W64LIT(0x014bce46bcd8f0af), + W64LIT(0x1663e29da0eba1e7), W64LIT(0x637f5ab2fb73b020), W64LIT(0xee09725b7c6ac515), W64LIT(0x0000000000000000), + W64LIT(0x338ccbf6c876dd8a), W64LIT(0x56540fcd9cef776f), W64LIT(0x623494f447ab408f), W64LIT(0x91e175f2cbd1fa80), + W64LIT(0x0f8e6ec59abc397b), W64LIT(0x4855d35ab58a0599), W64LIT(0x894737ec4d5e92b3), W64LIT(0xbd27acd5961aa553), + W64LIT(0x4d2f0219c31512b0), W64LIT(0xe1871c9ee6d6fc6e), W64LIT(0x8fe0a965e2b48876), W64LIT(0x118fb252b3d94b8d), + W64LIT(0xc0592af0440c6785), W64LIT(0xaca81e8725c3eede), W64LIT(0xd771062b583f36cd), W64LIT(0x7066696c2d0706ee), + W64LIT(0x99834bf8425f2991), W64LIT(0x3aa53bbafd20fe34), W64LIT(0x4406f255f643310e), W64LIT(0xa1b0f1cedad22ae6), + W64LIT(0x82f8462c1da54c4e), W64LIT(0x0929f04c355623be), W64LIT(0x057ad143769f1729), W64LIT(0x949ba4b1bd4eeda9), + W64LIT(0x960d253dd8e310ea), W64LIT(0xfecd0e4f736b7e37), W64LIT(0x0296818c65adfd43), W64LIT(0x6f2c7bbdb8ba84b7), + W64LIT(0x9a5e04329b2a247d), W64LIT(0x2348b7e2c77766a8), W64LIT(0xdcce77eb08c4e830), W64LIT(0x851416e30e97a624), + W64LIT(0x08623e0a898ed311), W64LIT(0x43eaa29ae571db64), W64LIT(0xc7b57a3f573e8def), W64LIT(0xc2cfab7c21a19ac6), + W64LIT(0x5ca0b04b70cc593d), W64LIT(0x0ec5a0832664c9d4), W64LIT(0x1e01dc97296572f6), W64LIT(0xbacbfc1a85284f39), + W64LIT(0xc970dabc715a443b), W64LIT(0xa8990182ef840958), W64LIT(0xc83b14facd82b494), W64LIT(0x72f0e8e048aafbad), + W64LIT(0xf143608ae9d7474c), W64LIT(0xf5727f8f2390a0ca), W64LIT(0x7fe807a9b7bb3f95), W64LIT(0x76c1f7e582ed1c2b), + W64LIT(0xcd41c5b9bb1da3bd), W64LIT(0x6b1d64b872fd6331), W64LIT(0x806ec7a07808b10d), W64LIT(0xe3119d12837b012d), + W64LIT(0x25ef296b689d7c6d), W64LIT(0x37bdd4f302313a0c), W64LIT(0x3051843c1103d066), W64LIT(0x68c02b72ab886edd), + W64LIT(0x8782976f6b3a5b67), W64LIT(0x2d8d1761e113af7c), W64LIT(0x1252fd986aac4661), W64LIT(0x0bbf71c050fbdefd), + W64LIT(0xd20bd7682ea021e4), W64LIT(0xe0ccd2d85a0e0cc1), W64LIT(0x9cf99abb34c03eb8), W64LIT(0xdd85b9adb41c189f), + W64LIT(0x61e9db3e9ede4d63), W64LIT(0x06a79e89afea1ac5), W64LIT(0xf7e4fe03463d5d89), W64LIT(0x794f992018512550), + W64LIT(0x3beef5fc41f80e9b), W64LIT(0xcaad9576a82f49d7), W64LIT(0x10c47c140f01bb22), W64LIT(0x0af4bf86ec232e52), + W64LIT(0xdb2227241bf6025a), W64LIT(0x21de366ea2da9beb), W64LIT(0x9f24d571edb53354), W64LIT(0x9746eb7b643be045), + W64LIT(0xa3267042bf7fd7a5), W64LIT(0x6e67b5fb04627418), W64LIT(0xc46835f58e4b8003), W64LIT(0x07ec50cf1332ea6a), + W64LIT(0xe8aeecd2d380dfd0), W64LIT(0xe9e522946f582f7f), W64LIT(0x54c28e41f9428a2c), W64LIT(0xe25a53543fa3f182), + W64LIT(0xa9d2cfc4535cf9f7), W64LIT(0xa0fb3f88660ada49), W64LIT(0x50f3914433056daa), W64LIT(0x51b85f028fdd9d05), + W64LIT(0xec9ff3d719c73856), W64LIT(0x263266a1b1e87181), W64LIT(0x5e3631c71561a47e), W64LIT(0x24a4e72dd4458cc2), + W64LIT(0x74577669e740e168), W64LIT(0x7a92d6eac12428bc), W64LIT(0x2e5058ab3866a290), W64LIT(0x4ef24dd31a601f5c), + W64LIT(0xf9215e806059945d), W64LIT(0xfbb7df0c05f4691e), W64LIT(0x751cb82f5b9811c7), W64LIT(0x29bc08642b5448fa), + W64LIT(0x5891af4eba8bbebb), W64LIT(0x73bb26a6f4720b02), W64LIT(0x6dbafa31dd1779f4), W64LIT(0x7c3548636ece3279), + W64LIT(0x4c64cc5f7fcde21f), W64LIT(0x60a215782206bdcc), W64LIT(0xa7176f4775383023), W64LIT(0xbfb12d59f3b75810) + }, + { + W64LIT(0x51843c1103d06630), W64LIT(0xdfeaf98bbfe91d3f), W64LIT(0xeef5fc41f80e9b3b), W64LIT(0xaf3045fae5ad26f6), + W64LIT(0x70dabc715a443bc9), W64LIT(0x119d12837b012de3), W64LIT(0x3b14facd82b494c8), W64LIT(0xdd4fcad9750dec03), + W64LIT(0xaabbb477090a2f90), W64LIT(0x75514dfcb6e332af), W64LIT(0x96818c65adfd4302), W64LIT(0x1d64b872fd63316b), + W64LIT(0xe4fe03463d5d89f7), W64LIT(0x43608ae9d7474cf1), W64LIT(0xe20c56b07e6c87b3), W64LIT(0xf24dd31a601f5c4e), + W64LIT(0x577669e740e16874), W64LIT(0x609b39db4437e034), W64LIT(0x3ac86de4e7c662d6), W64LIT(0x0379a47baf960722), + W64LIT(0xa79e89afea1ac506), W64LIT(0x4bce46bcd8f0af01), W64LIT(0x267042bf7fd7a5a3), W64LIT(0x7ad143769f172905), + W64LIT(0x85b9adb41c189fdd), W64LIT(0xc885befe87d93e98), W64LIT(0xed8c583a57989c19), W64LIT(0x3c3a3812a4f76c92), + W64LIT(0x5e04329b2a247d9a), W64LIT(0xf99abb34c03eb89c), W64LIT(0x2227241bf6025adb), W64LIT(0x6510c856a890e952), + W64LIT(0xa215782206bdcc60), W64LIT(0x9ff3d719c73856ec), W64LIT(0x02a53352cae4f13c), W64LIT(0x871c9ee6d6fc6ee1), + W64LIT(0x80325c39f0bf96bb), W64LIT(0x8d1761e113af7c2d), W64LIT(0x46eb7b643be04597), W64LIT(0xd8c43b5499aae565), + W64LIT(0x81eecb1095cd60a5), W64LIT(0x9c8a736268ae51ce), W64LIT(0x64cc5f7fcde21f4c), W64LIT(0x7c231680dc262741), + W64LIT(0xc28e41f9428a2c54), W64LIT(0x8ccbf6c876dd8a33), W64LIT(0xb98395a6b8eff34f), W64LIT(0xa9c2100ca69c28b2), + W64LIT(0x6ec7a07808b10d80), W64LIT(0x0a0bff07c55312cc), W64LIT(0xc02b72ab886edd68), W64LIT(0xb85f028fdd9d0551), + W64LIT(0x104185aa1e73dbfd), W64LIT(0xb6039b2c911be8e5), W64LIT(0x79a8e70d30812e27), W64LIT(0x82976f6b3a5b6787), + W64LIT(0xa53bbafd20fe343a), W64LIT(0x7dff81a9b954d15f), W64LIT(0x894007459a7a8355), W64LIT(0xd43d91a51fc8f9ed), + W64LIT(0xccd2d85a0e0cc1e0), W64LIT(0xe807a9b7bb3f957f), W64LIT(0xa81e8725c3eedeac), W64LIT(0x5058ab3866a2902e), + W64LIT(0x889c906cff08754b), W64LIT(0x4ce08463feb3575b), W64LIT(0xdc935df0107f1a1d), W64LIT(0x56aafece25939e6a), + W64LIT(0xa16cdc59a92bcb42), W64LIT(0xec50cf1332ea6a07), W64LIT(0x4592df1f947642b5), W64LIT(0xbafa31dd1779f46d), + W64LIT(0x29f04c355623be09), W64LIT(0x15ca7427f2d4d29b), W64LIT(0x215e806059945df9), W64LIT(0x23fbb3329370acc5), + W64LIT(0xd74435deb05efecf), W64LIT(0xeaa29ae571db6443), W64LIT(0xc95929d7e2abc886), W64LIT(0xa4e72dd4458cc224), + W64LIT(0x3548636ece32797c), W64LIT(0x27acd5961aa553bd), W64LIT(0xac49e1814a3b21d4), W64LIT(0xcbfc1a85284f39ba), + W64LIT(0x8fb252b3d94b8d11), W64LIT(0x42bc1dc0b235baef), W64LIT(0x072ec2df2643f85a), W64LIT(0x91af4eba8bbebb58), + W64LIT(0x045766a489d5ff78), W64LIT(0x9073d993eecc4d46), W64LIT(0x3f439c690b616bb0), W64LIT(0x6b4c51f5e41604e6), + W64LIT(0x7e8625d216c2d67d), W64LIT(0xab67235e6c78d98e), W64LIT(0xef296b689d7c6d25), W64LIT(0xc5a0832664c9d40e), + W64LIT(0x69e962a72ef2f5da), W64LIT(0x7b0dd45ffa65df1b), W64LIT(0x496b75ee12145e3d), W64LIT(0xd918ac7dfcd8137b), + W64LIT(0x1e1d1c0952f53649), W64LIT(0xfeb479ebe67d40c6), W64LIT(0x6147aef22145162a), W64LIT(0x0f800e8a29f41baa), + W64LIT(0x0000000000000000), W64LIT(0x990182ef840958a8), W64LIT(0x975d1b4cc88fb51c), W64LIT(0x5b8fc316c68374fc), + W64LIT(0x16b3d05c5d42d5b9), W64LIT(0xb3886aa17dbce183), W64LIT(0x4f99201851255079), W64LIT(0x98dd15c6e17baeb6), + W64LIT(0x06f255f643310e44), W64LIT(0x6f1b37516dc3fb9e), W64LIT(0x0cf9aaf186621c88), W64LIT(0x8e6ec59abc397b0f), + W64LIT(0x930a7de8415a4a64), W64LIT(0x37ed503c04d68840), W64LIT(0xf61ab5bee9caa336), W64LIT(0xfb3f88660ada49a0), + W64LIT(0x7874702455f3d839), W64LIT(0x208217493ce6abe7), W64LIT(0x73a3180af5d23ceb), W64LIT(0x9e2f4030a24aa0f2), + W64LIT(0xe522946f582f7fe9), W64LIT(0xd5e1068c7aba0ff3), W64LIT(0xbdd4f302313a0c37), W64LIT(0x1fc18b203787c057), + W64LIT(0xd2cfc4535cf9f7a9), W64LIT(0x1b96ed84be523f2f), W64LIT(0x5d7d96e085b27ab8), W64LIT(0x66696c2d0706ee70), + W64LIT(0xd06af701961d0695), W64LIT(0xe3d0c1991b1e71ad), W64LIT(0x6c62932ac255fcbc), W64LIT(0xd313537a398b01b7), + W64LIT(0xa0b04b70cc593d5c), W64LIT(0x834bf8425f299199), W64LIT(0xaeecd2d380dfd0e8), W64LIT(0xbead57799eac0b15), + W64LIT(0x540fcd9cef776f56), W64LIT(0xad9576a82f49d7ca), W64LIT(0xfc114ab92c99b1fa), W64LIT(0x33ba36988d037738), + W64LIT(0xbb26a6f4720b0273), W64LIT(0xb254fd8818ce179d), W64LIT(0xa6421e868f683318), W64LIT(0x5fd8a5b24f568b84), + W64LIT(0x623e0a898ed31108), W64LIT(0xb0f1cedad22ae6a1), W64LIT(0x1933ded674b6ce13), W64LIT(0x1416e30e97a62485), + W64LIT(0x3e9f0b406e139dae), W64LIT(0x6dbe0403a7270aa2), W64LIT(0xbc08642b5448fa29), W64LIT(0x0d253dd8e310ea96), + W64LIT(0x2ede8eea70604653), W64LIT(0x39b1c99f485065f4), W64LIT(0xcd0e4f736b7e37fe), W64LIT(0xbf71c050fbdefd0b), + W64LIT(0x748ddad5d391c4b1), W64LIT(0x0bd7682ea021e4d2), W64LIT(0x3494f447ab408f62), W64LIT(0xb4a6a87e5bff19d9), + W64LIT(0x133821d1b1e5dcdf), W64LIT(0x95f8281e026b4420), W64LIT(0x2da72a91dff64171), W64LIT(0x18ef49ff11c4380d), + W64LIT(0xc705b074ae2d2532), W64LIT(0x3de6af3bc1859a8c), W64LIT(0x6835f58e4b8003c4), W64LIT(0xe787a73d92cb8ed5), + W64LIT(0xc6d9275dcb5fd32c), W64LIT(0xf7c622978cb85528), W64LIT(0x4d3c134a9bc1a145), W64LIT(0xf3914433056daa50), + W64LIT(0xb7df0c05f4691efb), W64LIT(0xe175f2cbd1fa8091), W64LIT(0x77f47eae7c07c393), W64LIT(0xeb7e0dcc14a9925d), + W64LIT(0xf1347761cf895b6c), W64LIT(0x08aecc550fb7e3f0), W64LIT(0x55d35ab58a059948), W64LIT(0x444e4836f104b4ab), + W64LIT(0x58f6676d691573de), W64LIT(0x9ba4b1bd4eeda994), W64LIT(0x92d6eac12428bc7a), W64LIT(0xb12d59f3b75810bf), + W64LIT(0xa3c9ef0b63cf3a7e), W64LIT(0x67b5fb046274186e), W64LIT(0x2f0219c31512b04d), W64LIT(0x3266a1b1e8718126), + W64LIT(0x7628e9871975358d), W64LIT(0xda610806534e1459), W64LIT(0x311f05ca47e78604), W64LIT(0x12e4b6f8d4972ac1), + W64LIT(0x282cdb1c33514817), W64LIT(0x727f8f2390a0caf5), W64LIT(0xb57a3f573e8defc7), W64LIT(0x71062b583f36cdd7), + W64LIT(0x84653a9d796a69c3), W64LIT(0xf56311c5465ca414), W64LIT(0x4737ec4d5e92b389), W64LIT(0x1cb82f5b9811c775), + W64LIT(0x2509e6c4d041a281), W64LIT(0xfdcddd9049eb47e4), W64LIT(0x40192e9278d14bd3), W64LIT(0x2a89e84ef9b5b92b), + W64LIT(0x3631c71561a47e5e), W64LIT(0x8be53417509e7269), W64LIT(0x24d571edb533549f), W64LIT(0xc352d6d027f8da4a), + W64LIT(0x01dc97296572f61e), W64LIT(0xe9db3e9ede4d6361), W64LIT(0x4e45b7313457a667), W64LIT(0xf8462c1da54c4e82), + W64LIT(0x4a12d195bd82591f), W64LIT(0xff68eec2830fb6d8), W64LIT(0x176f4775383023a7), W64LIT(0x48b7e2c77766a823), + W64LIT(0x592af0440c6785c0), W64LIT(0x2c7bbdb8ba84b76f), W64LIT(0x5ca101c9e0c08ca6), W64LIT(0x63e29da0eba1e716), + W64LIT(0xd698a2f7d52c08d1), W64LIT(0xce77eb08c4e830dc), W64LIT(0xde366ea2da9beb21), W64LIT(0x5a53543fa3f182e2), + W64LIT(0x52fd986aac466112), W64LIT(0x86c009cfb38e98ff), W64LIT(0xd1b66028f36ff08b), W64LIT(0x1a4a7aaddb20c931), + W64LIT(0xcfab7c21a19ac6c2), W64LIT(0x09725b7c6ac515ee), W64LIT(0x0e5c99a34c86edb4), W64LIT(0xdbbd9f2f363ce247), + W64LIT(0x6a90c6dc8164f2f8), W64LIT(0x8a39a33e35ec8477), W64LIT(0xe0a965e2b488768f), W64LIT(0x7f5ab2fb73b02063), + W64LIT(0xf4bf86ec232e520a), W64LIT(0xfae31f4f6fa8bfbe), W64LIT(0x058bf18deca70966), W64LIT(0x41c5b9bb1da3bdcd), + W64LIT(0x2b557f679cc74f35), W64LIT(0xca208dac4d3dcfa4), W64LIT(0x9a7826942b9f5f8a), W64LIT(0xf0e8e048aafbad72), + W64LIT(0x53210f43c934970c), W64LIT(0xc1f7e582ed1c2b76), W64LIT(0xc47c140f01bb2210), W64LIT(0x9d56e44b0ddca7d0), + W64LIT(0x386d5eb62d2293ea), W64LIT(0xe65b3014f7b978cb), W64LIT(0x9424bf376719b23e), W64LIT(0x30c392e32295701a) + } +}; + +const byte S[4][256] = +{ + { + 0xA8, 0x43, 0x5F, 0x06, 0x6B, 0x75, 0x6C, 0x59, 0x71, 0xDF, 0x87, 0x95, 0x17, 0xF0, 0xD8, 0x09, + 0x6D, 0xF3, 0x1D, 0xCB, 0xC9, 0x4D, 0x2C, 0xAF, 0x79, 0xE0, 0x97, 0xFD, 0x6F, 0x4B, 0x45, 0x39, + 0x3E, 0xDD, 0xA3, 0x4F, 0xB4, 0xB6, 0x9A, 0x0E, 0x1F, 0xBF, 0x15, 0xE1, 0x49, 0xD2, 0x93, 0xC6, + 0x92, 0x72, 0x9E, 0x61, 0xD1, 0x63, 0xFA, 0xEE, 0xF4, 0x19, 0xD5, 0xAD, 0x58, 0xA4, 0xBB, 0xA1, + 0xDC, 0xF2, 0x83, 0x37, 0x42, 0xE4, 0x7A, 0x32, 0x9C, 0xCC, 0xAB, 0x4A, 0x8F, 0x6E, 0x04, 0x27, + 0x2E, 0xE7, 0xE2, 0x5A, 0x96, 0x16, 0x23, 0x2B, 0xC2, 0x65, 0x66, 0x0F, 0xBC, 0xA9, 0x47, 0x41, + 0x34, 0x48, 0xFC, 0xB7, 0x6A, 0x88, 0xA5, 0x53, 0x86, 0xF9, 0x5B, 0xDB, 0x38, 0x7B, 0xC3, 0x1E, + 0x22, 0x33, 0x24, 0x28, 0x36, 0xC7, 0xB2, 0x3B, 0x8E, 0x77, 0xBA, 0xF5, 0x14, 0x9F, 0x08, 0x55, + 0x9B, 0x4C, 0xFE, 0x60, 0x5C, 0xDA, 0x18, 0x46, 0xCD, 0x7D, 0x21, 0xB0, 0x3F, 0x1B, 0x89, 0xFF, + 0xEB, 0x84, 0x69, 0x3A, 0x9D, 0xD7, 0xD3, 0x70, 0x67, 0x40, 0xB5, 0xDE, 0x5D, 0x30, 0x91, 0xB1, + 0x78, 0x11, 0x01, 0xE5, 0x00, 0x68, 0x98, 0xA0, 0xC5, 0x02, 0xA6, 0x74, 0x2D, 0x0B, 0xA2, 0x76, + 0xB3, 0xBE, 0xCE, 0xBD, 0xAE, 0xE9, 0x8A, 0x31, 0x1C, 0xEC, 0xF1, 0x99, 0x94, 0xAA, 0xF6, 0x26, + 0x2F, 0xEF, 0xE8, 0x8C, 0x35, 0x03, 0xD4, 0x7F, 0xFB, 0x05, 0xC1, 0x5E, 0x90, 0x20, 0x3D, 0x82, + 0xF7, 0xEA, 0x0A, 0x0D, 0x7E, 0xF8, 0x50, 0x1A, 0xC4, 0x07, 0x57, 0xB8, 0x3C, 0x62, 0xE3, 0xC8, + 0xAC, 0x52, 0x64, 0x10, 0xD0, 0xD9, 0x13, 0x0C, 0x12, 0x29, 0x51, 0xB9, 0xCF, 0xD6, 0x73, 0x8D, + 0x81, 0x54, 0xC0, 0xED, 0x4E, 0x44, 0xA7, 0x2A, 0x85, 0x25, 0xE6, 0xCA, 0x7C, 0x8B, 0x56, 0x80 + }, + { + 0xCE, 0xBB, 0xEB, 0x92, 0xEA, 0xCB, 0x13, 0xC1, 0xE9, 0x3A, 0xD6, 0xB2, 0xD2, 0x90, 0x17, 0xF8, + 0x42, 0x15, 0x56, 0xB4, 0x65, 0x1C, 0x88, 0x43, 0xC5, 0x5C, 0x36, 0xBA, 0xF5, 0x57, 0x67, 0x8D, + 0x31, 0xF6, 0x64, 0x58, 0x9E, 0xF4, 0x22, 0xAA, 0x75, 0x0F, 0x02, 0xB1, 0xDF, 0x6D, 0x73, 0x4D, + 0x7C, 0x26, 0x2E, 0xF7, 0x08, 0x5D, 0x44, 0x3E, 0x9F, 0x14, 0xC8, 0xAE, 0x54, 0x10, 0xD8, 0xBC, + 0x1A, 0x6B, 0x69, 0xF3, 0xBD, 0x33, 0xAB, 0xFA, 0xD1, 0x9B, 0x68, 0x4E, 0x16, 0x95, 0x91, 0xEE, + 0x4C, 0x63, 0x8E, 0x5B, 0xCC, 0x3C, 0x19, 0xA1, 0x81, 0x49, 0x7B, 0xD9, 0x6F, 0x37, 0x60, 0xCA, + 0xE7, 0x2B, 0x48, 0xFD, 0x96, 0x45, 0xFC, 0x41, 0x12, 0x0D, 0x79, 0xE5, 0x89, 0x8C, 0xE3, 0x20, + 0x30, 0xDC, 0xB7, 0x6C, 0x4A, 0xB5, 0x3F, 0x97, 0xD4, 0x62, 0x2D, 0x06, 0xA4, 0xA5, 0x83, 0x5F, + 0x2A, 0xDA, 0xC9, 0x00, 0x7E, 0xA2, 0x55, 0xBF, 0x11, 0xD5, 0x9C, 0xCF, 0x0E, 0x0A, 0x3D, 0x51, + 0x7D, 0x93, 0x1B, 0xFE, 0xC4, 0x47, 0x09, 0x86, 0x0B, 0x8F, 0x9D, 0x6A, 0x07, 0xB9, 0xB0, 0x98, + 0x18, 0x32, 0x71, 0x4B, 0xEF, 0x3B, 0x70, 0xA0, 0xE4, 0x40, 0xFF, 0xC3, 0xA9, 0xE6, 0x78, 0xF9, + 0x8B, 0x46, 0x80, 0x1E, 0x38, 0xE1, 0xB8, 0xA8, 0xE0, 0x0C, 0x23, 0x76, 0x1D, 0x25, 0x24, 0x05, + 0xF1, 0x6E, 0x94, 0x28, 0x9A, 0x84, 0xE8, 0xA3, 0x4F, 0x77, 0xD3, 0x85, 0xE2, 0x52, 0xF2, 0x82, + 0x50, 0x7A, 0x2F, 0x74, 0x53, 0xB3, 0x61, 0xAF, 0x39, 0x35, 0xDE, 0xCD, 0x1F, 0x99, 0xAC, 0xAD, + 0x72, 0x2C, 0xDD, 0xD0, 0x87, 0xBE, 0x5E, 0xA6, 0xEC, 0x04, 0xC6, 0x03, 0x34, 0xFB, 0xDB, 0x59, + 0xB6, 0xC2, 0x01, 0xF0, 0x5A, 0xED, 0xA7, 0x66, 0x21, 0x7F, 0x8A, 0x27, 0xC7, 0xC0, 0x29, 0xD7 + }, + { + 0x93, 0xD9, 0x9A, 0xB5, 0x98, 0x22, 0x45, 0xFC, 0xBA, 0x6A, 0xDF, 0x02, 0x9F, 0xDC, 0x51, 0x59, + 0x4A, 0x17, 0x2B, 0xC2, 0x94, 0xF4, 0xBB, 0xA3, 0x62, 0xE4, 0x71, 0xD4, 0xCD, 0x70, 0x16, 0xE1, + 0x49, 0x3C, 0xC0, 0xD8, 0x5C, 0x9B, 0xAD, 0x85, 0x53, 0xA1, 0x7A, 0xC8, 0x2D, 0xE0, 0xD1, 0x72, + 0xA6, 0x2C, 0xC4, 0xE3, 0x76, 0x78, 0xB7, 0xB4, 0x09, 0x3B, 0x0E, 0x41, 0x4C, 0xDE, 0xB2, 0x90, + 0x25, 0xA5, 0xD7, 0x03, 0x11, 0x00, 0xC3, 0x2E, 0x92, 0xEF, 0x4E, 0x12, 0x9D, 0x7D, 0xCB, 0x35, + 0x10, 0xD5, 0x4F, 0x9E, 0x4D, 0xA9, 0x55, 0xC6, 0xD0, 0x7B, 0x18, 0x97, 0xD3, 0x36, 0xE6, 0x48, + 0x56, 0x81, 0x8F, 0x77, 0xCC, 0x9C, 0xB9, 0xE2, 0xAC, 0xB8, 0x2F, 0x15, 0xA4, 0x7C, 0xDA, 0x38, + 0x1E, 0x0B, 0x05, 0xD6, 0x14, 0x6E, 0x6C, 0x7E, 0x66, 0xFD, 0xB1, 0xE5, 0x60, 0xAF, 0x5E, 0x33, + 0x87, 0xC9, 0xF0, 0x5D, 0x6D, 0x3F, 0x88, 0x8D, 0xC7, 0xF7, 0x1D, 0xE9, 0xEC, 0xED, 0x80, 0x29, + 0x27, 0xCF, 0x99, 0xA8, 0x50, 0x0F, 0x37, 0x24, 0x28, 0x30, 0x95, 0xD2, 0x3E, 0x5B, 0x40, 0x83, + 0xB3, 0x69, 0x57, 0x1F, 0x07, 0x1C, 0x8A, 0xBC, 0x20, 0xEB, 0xCE, 0x8E, 0xAB, 0xEE, 0x31, 0xA2, + 0x73, 0xF9, 0xCA, 0x3A, 0x1A, 0xFB, 0x0D, 0xC1, 0xFE, 0xFA, 0xF2, 0x6F, 0xBD, 0x96, 0xDD, 0x43, + 0x52, 0xB6, 0x08, 0xF3, 0xAE, 0xBE, 0x19, 0x89, 0x32, 0x26, 0xB0, 0xEA, 0x4B, 0x64, 0x84, 0x82, + 0x6B, 0xF5, 0x79, 0xBF, 0x01, 0x5F, 0x75, 0x63, 0x1B, 0x23, 0x3D, 0x68, 0x2A, 0x65, 0xE8, 0x91, + 0xF6, 0xFF, 0x13, 0x58, 0xF1, 0x47, 0x0A, 0x7F, 0xC5, 0xA7, 0xE7, 0x61, 0x5A, 0x06, 0x46, 0x44, + 0x42, 0x04, 0xA0, 0xDB, 0x39, 0x86, 0x54, 0xAA, 0x8C, 0x34, 0x21, 0x8B, 0xF8, 0x0C, 0x74, 0x67 + }, + { + 0x68, 0x8D, 0xCA, 0x4D, 0x73, 0x4B, 0x4E, 0x2A, 0xD4, 0x52, 0x26, 0xB3, 0x54, 0x1E, 0x19, 0x1F, + 0x22, 0x03, 0x46, 0x3D, 0x2D, 0x4A, 0x53, 0x83, 0x13, 0x8A, 0xB7, 0xD5, 0x25, 0x79, 0xF5, 0xBD, + 0x58, 0x2F, 0x0D, 0x02, 0xED, 0x51, 0x9E, 0x11, 0xF2, 0x3E, 0x55, 0x5E, 0xD1, 0x16, 0x3C, 0x66, + 0x70, 0x5D, 0xF3, 0x45, 0x40, 0xCC, 0xE8, 0x94, 0x56, 0x08, 0xCE, 0x1A, 0x3A, 0xD2, 0xE1, 0xDF, + 0xB5, 0x38, 0x6E, 0x0E, 0xE5, 0xF4, 0xF9, 0x86, 0xE9, 0x4F, 0xD6, 0x85, 0x23, 0xCF, 0x32, 0x99, + 0x31, 0x14, 0xAE, 0xEE, 0xC8, 0x48, 0xD3, 0x30, 0xA1, 0x92, 0x41, 0xB1, 0x18, 0xC4, 0x2C, 0x71, + 0x72, 0x44, 0x15, 0xFD, 0x37, 0xBE, 0x5F, 0xAA, 0x9B, 0x88, 0xD8, 0xAB, 0x89, 0x9C, 0xFA, 0x60, + 0xEA, 0xBC, 0x62, 0x0C, 0x24, 0xA6, 0xA8, 0xEC, 0x67, 0x20, 0xDB, 0x7C, 0x28, 0xDD, 0xAC, 0x5B, + 0x34, 0x7E, 0x10, 0xF1, 0x7B, 0x8F, 0x63, 0xA0, 0x05, 0x9A, 0x43, 0x77, 0x21, 0xBF, 0x27, 0x09, + 0xC3, 0x9F, 0xB6, 0xD7, 0x29, 0xC2, 0xEB, 0xC0, 0xA4, 0x8B, 0x8C, 0x1D, 0xFB, 0xFF, 0xC1, 0xB2, + 0x97, 0x2E, 0xF8, 0x65, 0xF6, 0x75, 0x07, 0x04, 0x49, 0x33, 0xE4, 0xD9, 0xB9, 0xD0, 0x42, 0xC7, + 0x6C, 0x90, 0x00, 0x8E, 0x6F, 0x50, 0x01, 0xC5, 0xDA, 0x47, 0x3F, 0xCD, 0x69, 0xA2, 0xE2, 0x7A, + 0xA7, 0xC6, 0x93, 0x0F, 0x0A, 0x06, 0xE6, 0x2B, 0x96, 0xA3, 0x1C, 0xAF, 0x6A, 0x12, 0x84, 0x39, + 0xE7, 0xB0, 0x82, 0xF7, 0xFE, 0x9D, 0x87, 0x5C, 0x81, 0x35, 0xDE, 0xB4, 0xA5, 0xFC, 0x80, 0xEF, + 0xCB, 0xBB, 0x6B, 0x76, 0xBA, 0x5A, 0x7D, 0x78, 0x0B, 0x95, 0xE3, 0xAD, 0x74, 0x98, 0x3B, 0x36, + 0x64, 0x6D, 0xDC, 0xF0, 0x59, 0xA9, 0x4C, 0x17, 0x7F, 0x91, 0xB8, 0xC9, 0x57, 0x1B, 0xE0, 0x61 + } +}; + +const byte IS[4][256] = +{ + { + 0xA4, 0xA2, 0xA9, 0xC5, 0x4E, 0xC9, 0x03, 0xD9, 0x7E, 0x0F, 0xD2, 0xAD, 0xE7, 0xD3, 0x27, 0x5B, + 0xE3, 0xA1, 0xE8, 0xE6, 0x7C, 0x2A, 0x55, 0x0C, 0x86, 0x39, 0xD7, 0x8D, 0xB8, 0x12, 0x6F, 0x28, + 0xCD, 0x8A, 0x70, 0x56, 0x72, 0xF9, 0xBF, 0x4F, 0x73, 0xE9, 0xF7, 0x57, 0x16, 0xAC, 0x50, 0xC0, + 0x9D, 0xB7, 0x47, 0x71, 0x60, 0xC4, 0x74, 0x43, 0x6C, 0x1F, 0x93, 0x77, 0xDC, 0xCE, 0x20, 0x8C, + 0x99, 0x5F, 0x44, 0x01, 0xF5, 0x1E, 0x87, 0x5E, 0x61, 0x2C, 0x4B, 0x1D, 0x81, 0x15, 0xF4, 0x23, + 0xD6, 0xEA, 0xE1, 0x67, 0xF1, 0x7F, 0xFE, 0xDA, 0x3C, 0x07, 0x53, 0x6A, 0x84, 0x9C, 0xCB, 0x02, + 0x83, 0x33, 0xDD, 0x35, 0xE2, 0x59, 0x5A, 0x98, 0xA5, 0x92, 0x64, 0x04, 0x06, 0x10, 0x4D, 0x1C, + 0x97, 0x08, 0x31, 0xEE, 0xAB, 0x05, 0xAF, 0x79, 0xA0, 0x18, 0x46, 0x6D, 0xFC, 0x89, 0xD4, 0xC7, + 0xFF, 0xF0, 0xCF, 0x42, 0x91, 0xF8, 0x68, 0x0A, 0x65, 0x8E, 0xB6, 0xFD, 0xC3, 0xEF, 0x78, 0x4C, + 0xCC, 0x9E, 0x30, 0x2E, 0xBC, 0x0B, 0x54, 0x1A, 0xA6, 0xBB, 0x26, 0x80, 0x48, 0x94, 0x32, 0x7D, + 0xA7, 0x3F, 0xAE, 0x22, 0x3D, 0x66, 0xAA, 0xF6, 0x00, 0x5D, 0xBD, 0x4A, 0xE0, 0x3B, 0xB4, 0x17, + 0x8B, 0x9F, 0x76, 0xB0, 0x24, 0x9A, 0x25, 0x63, 0xDB, 0xEB, 0x7A, 0x3E, 0x5C, 0xB3, 0xB1, 0x29, + 0xF2, 0xCA, 0x58, 0x6E, 0xD8, 0xA8, 0x2F, 0x75, 0xDF, 0x14, 0xFB, 0x13, 0x49, 0x88, 0xB2, 0xEC, + 0xE4, 0x34, 0x2D, 0x96, 0xC6, 0x3A, 0xED, 0x95, 0x0E, 0xE5, 0x85, 0x6B, 0x40, 0x21, 0x9B, 0x09, + 0x19, 0x2B, 0x52, 0xDE, 0x45, 0xA3, 0xFA, 0x51, 0xC2, 0xB5, 0xD1, 0x90, 0xB9, 0xF3, 0x37, 0xC1, + 0x0D, 0xBA, 0x41, 0x11, 0x38, 0x7B, 0xBE, 0xD0, 0xD5, 0x69, 0x36, 0xC8, 0x62, 0x1B, 0x82, 0x8F + }, + { + 0x83, 0xF2, 0x2A, 0xEB, 0xE9, 0xBF, 0x7B, 0x9C, 0x34, 0x96, 0x8D, 0x98, 0xB9, 0x69, 0x8C, 0x29, + 0x3D, 0x88, 0x68, 0x06, 0x39, 0x11, 0x4C, 0x0E, 0xA0, 0x56, 0x40, 0x92, 0x15, 0xBC, 0xB3, 0xDC, + 0x6F, 0xF8, 0x26, 0xBA, 0xBE, 0xBD, 0x31, 0xFB, 0xC3, 0xFE, 0x80, 0x61, 0xE1, 0x7A, 0x32, 0xD2, + 0x70, 0x20, 0xA1, 0x45, 0xEC, 0xD9, 0x1A, 0x5D, 0xB4, 0xD8, 0x09, 0xA5, 0x55, 0x8E, 0x37, 0x76, + 0xA9, 0x67, 0x10, 0x17, 0x36, 0x65, 0xB1, 0x95, 0x62, 0x59, 0x74, 0xA3, 0x50, 0x2F, 0x4B, 0xC8, + 0xD0, 0x8F, 0xCD, 0xD4, 0x3C, 0x86, 0x12, 0x1D, 0x23, 0xEF, 0xF4, 0x53, 0x19, 0x35, 0xE6, 0x7F, + 0x5E, 0xD6, 0x79, 0x51, 0x22, 0x14, 0xF7, 0x1E, 0x4A, 0x42, 0x9B, 0x41, 0x73, 0x2D, 0xC1, 0x5C, + 0xA6, 0xA2, 0xE0, 0x2E, 0xD3, 0x28, 0xBB, 0xC9, 0xAE, 0x6A, 0xD1, 0x5A, 0x30, 0x90, 0x84, 0xF9, + 0xB2, 0x58, 0xCF, 0x7E, 0xC5, 0xCB, 0x97, 0xE4, 0x16, 0x6C, 0xFA, 0xB0, 0x6D, 0x1F, 0x52, 0x99, + 0x0D, 0x4E, 0x03, 0x91, 0xC2, 0x4D, 0x64, 0x77, 0x9F, 0xDD, 0xC4, 0x49, 0x8A, 0x9A, 0x24, 0x38, + 0xA7, 0x57, 0x85, 0xC7, 0x7C, 0x7D, 0xE7, 0xF6, 0xB7, 0xAC, 0x27, 0x46, 0xDE, 0xDF, 0x3B, 0xD7, + 0x9E, 0x2B, 0x0B, 0xD5, 0x13, 0x75, 0xF0, 0x72, 0xB6, 0x9D, 0x1B, 0x01, 0x3F, 0x44, 0xE5, 0x87, + 0xFD, 0x07, 0xF1, 0xAB, 0x94, 0x18, 0xEA, 0xFC, 0x3A, 0x82, 0x5F, 0x05, 0x54, 0xDB, 0x00, 0x8B, + 0xE3, 0x48, 0x0C, 0xCA, 0x78, 0x89, 0x0A, 0xFF, 0x3E, 0x5B, 0x81, 0xEE, 0x71, 0xE2, 0xDA, 0x2C, + 0xB8, 0xB5, 0xCC, 0x6E, 0xA8, 0x6B, 0xAD, 0x60, 0xC6, 0x08, 0x04, 0x02, 0xE8, 0xF5, 0x4F, 0xA4, + 0xF3, 0xC0, 0xCE, 0x43, 0x25, 0x1C, 0x21, 0x33, 0x0F, 0xAF, 0x47, 0xED, 0x66, 0x63, 0x93, 0xAA + }, + { + 0x45, 0xD4, 0x0B, 0x43, 0xF1, 0x72, 0xED, 0xA4, 0xC2, 0x38, 0xE6, 0x71, 0xFD, 0xB6, 0x3A, 0x95, + 0x50, 0x44, 0x4B, 0xE2, 0x74, 0x6B, 0x1E, 0x11, 0x5A, 0xC6, 0xB4, 0xD8, 0xA5, 0x8A, 0x70, 0xA3, + 0xA8, 0xFA, 0x05, 0xD9, 0x97, 0x40, 0xC9, 0x90, 0x98, 0x8F, 0xDC, 0x12, 0x31, 0x2C, 0x47, 0x6A, + 0x99, 0xAE, 0xC8, 0x7F, 0xF9, 0x4F, 0x5D, 0x96, 0x6F, 0xF4, 0xB3, 0x39, 0x21, 0xDA, 0x9C, 0x85, + 0x9E, 0x3B, 0xF0, 0xBF, 0xEF, 0x06, 0xEE, 0xE5, 0x5F, 0x20, 0x10, 0xCC, 0x3C, 0x54, 0x4A, 0x52, + 0x94, 0x0E, 0xC0, 0x28, 0xF6, 0x56, 0x60, 0xA2, 0xE3, 0x0F, 0xEC, 0x9D, 0x24, 0x83, 0x7E, 0xD5, + 0x7C, 0xEB, 0x18, 0xD7, 0xCD, 0xDD, 0x78, 0xFF, 0xDB, 0xA1, 0x09, 0xD0, 0x76, 0x84, 0x75, 0xBB, + 0x1D, 0x1A, 0x2F, 0xB0, 0xFE, 0xD6, 0x34, 0x63, 0x35, 0xD2, 0x2A, 0x59, 0x6D, 0x4D, 0x77, 0xE7, + 0x8E, 0x61, 0xCF, 0x9F, 0xCE, 0x27, 0xF5, 0x80, 0x86, 0xC7, 0xA6, 0xFB, 0xF8, 0x87, 0xAB, 0x62, + 0x3F, 0xDF, 0x48, 0x00, 0x14, 0x9A, 0xBD, 0x5B, 0x04, 0x92, 0x02, 0x25, 0x65, 0x4C, 0x53, 0x0C, + 0xF2, 0x29, 0xAF, 0x17, 0x6C, 0x41, 0x30, 0xE9, 0x93, 0x55, 0xF7, 0xAC, 0x68, 0x26, 0xC4, 0x7D, + 0xCA, 0x7A, 0x3E, 0xA0, 0x37, 0x03, 0xC1, 0x36, 0x69, 0x66, 0x08, 0x16, 0xA7, 0xBC, 0xC5, 0xD3, + 0x22, 0xB7, 0x13, 0x46, 0x32, 0xE8, 0x57, 0x88, 0x2B, 0x81, 0xB2, 0x4E, 0x64, 0x1C, 0xAA, 0x91, + 0x58, 0x2E, 0x9B, 0x5C, 0x1B, 0x51, 0x73, 0x42, 0x23, 0x01, 0x6E, 0xF3, 0x0D, 0xBE, 0x3D, 0x0A, + 0x2D, 0x1F, 0x67, 0x33, 0x19, 0x7B, 0x5E, 0xEA, 0xDE, 0x8B, 0xCB, 0xA9, 0x8C, 0x8D, 0xAD, 0x49, + 0x82, 0xE4, 0xBA, 0xC3, 0x15, 0xD1, 0xE0, 0x89, 0xFC, 0xB1, 0xB9, 0xB5, 0x07, 0x79, 0xB8, 0xE1 + }, + { + 0xB2, 0xB6, 0x23, 0x11, 0xA7, 0x88, 0xC5, 0xA6, 0x39, 0x8F, 0xC4, 0xE8, 0x73, 0x22, 0x43, 0xC3, + 0x82, 0x27, 0xCD, 0x18, 0x51, 0x62, 0x2D, 0xF7, 0x5C, 0x0E, 0x3B, 0xFD, 0xCA, 0x9B, 0x0D, 0x0F, + 0x79, 0x8C, 0x10, 0x4C, 0x74, 0x1C, 0x0A, 0x8E, 0x7C, 0x94, 0x07, 0xC7, 0x5E, 0x14, 0xA1, 0x21, + 0x57, 0x50, 0x4E, 0xA9, 0x80, 0xD9, 0xEF, 0x64, 0x41, 0xCF, 0x3C, 0xEE, 0x2E, 0x13, 0x29, 0xBA, + 0x34, 0x5A, 0xAE, 0x8A, 0x61, 0x33, 0x12, 0xB9, 0x55, 0xA8, 0x15, 0x05, 0xF6, 0x03, 0x06, 0x49, + 0xB5, 0x25, 0x09, 0x16, 0x0C, 0x2A, 0x38, 0xFC, 0x20, 0xF4, 0xE5, 0x7F, 0xD7, 0x31, 0x2B, 0x66, + 0x6F, 0xFF, 0x72, 0x86, 0xF0, 0xA3, 0x2F, 0x78, 0x00, 0xBC, 0xCC, 0xE2, 0xB0, 0xF1, 0x42, 0xB4, + 0x30, 0x5F, 0x60, 0x04, 0xEC, 0xA5, 0xE3, 0x8B, 0xE7, 0x1D, 0xBF, 0x84, 0x7B, 0xE6, 0x81, 0xF8, + 0xDE, 0xD8, 0xD2, 0x17, 0xCE, 0x4B, 0x47, 0xD6, 0x69, 0x6C, 0x19, 0x99, 0x9A, 0x01, 0xB3, 0x85, + 0xB1, 0xF9, 0x59, 0xC2, 0x37, 0xE9, 0xC8, 0xA0, 0xED, 0x4F, 0x89, 0x68, 0x6D, 0xD5, 0x26, 0x91, + 0x87, 0x58, 0xBD, 0xC9, 0x98, 0xDC, 0x75, 0xC0, 0x76, 0xF5, 0x67, 0x6B, 0x7E, 0xEB, 0x52, 0xCB, + 0xD1, 0x5B, 0x9F, 0x0B, 0xDB, 0x40, 0x92, 0x1A, 0xFA, 0xAC, 0xE4, 0xE1, 0x71, 0x1F, 0x65, 0x8D, + 0x97, 0x9E, 0x95, 0x90, 0x5D, 0xB7, 0xC1, 0xAF, 0x54, 0xFB, 0x02, 0xE0, 0x35, 0xBB, 0x3A, 0x4D, + 0xAD, 0x2C, 0x3D, 0x56, 0x08, 0x1B, 0x4A, 0x93, 0x6A, 0xAB, 0xB8, 0x7A, 0xF2, 0x7D, 0xDA, 0x3F, + 0xFE, 0x3E, 0xBE, 0xEA, 0xAA, 0x44, 0xC6, 0xD0, 0x36, 0x48, 0x70, 0x96, 0x77, 0x24, 0x53, 0xDF, + 0xF3, 0x83, 0x28, 0x32, 0x45, 0x1E, 0xA4, 0xD3, 0xA2, 0x46, 0x6E, 0x9C, 0xDD, 0x63, 0xD4, 0x9D + } +}; + +NAMESPACE_END +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/keccak.cpp b/external/ours/library/crypto/src/shared/original/keccak.cpp new file mode 100755 index 000000000..ed69590e6 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/keccak.cpp @@ -0,0 +1,67 @@ +// keccak.cpp - modified by Wei Dai from Ronny Van Keer's public domain +// sha3-simple.c. All modifications here are placed in the +// public domain by Wei Dai. +// Keccack core function moved to keccakc.cpp in AUG 2018 +// by Jeffrey Walton. Separating the core file allows both +// SHA3 and Keccack to share the core implementation. + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michael Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by Ronny Van Keer, hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include "pch.h" +#include "keccak.h" + +NAMESPACE_BEGIN(CryptoPP) + +// The Keccak core function +extern void KeccakF1600(word64 *state); + +void Keccak::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT(!(input == NULLPTR && length != 0)); + if (length == 0) { return; } + + size_t spaceLeft; + while (length >= (spaceLeft = r() - m_counter)) + { + if (spaceLeft) + xorbuf(m_state.BytePtr() + m_counter, input, spaceLeft); + KeccakF1600(m_state); + input += spaceLeft; + length -= spaceLeft; + m_counter = 0; + } + + if (length) + xorbuf(m_state.BytePtr() + m_counter, input, length); + m_counter += (unsigned int)length; +} + +void Keccak::Restart() +{ + memset(m_state, 0, m_state.SizeInBytes()); + m_counter = 0; +} + +void Keccak::TruncatedFinal(byte *hash, size_t size) +{ + CRYPTOPP_ASSERT(hash != NULLPTR); + ThrowIfInvalidTruncatedSize(size); + + m_state.BytePtr()[m_counter] ^= 0x01; + m_state.BytePtr()[r()-1] ^= 0x80; + KeccakF1600(m_state); + std::memcpy(hash, m_state, size); + Restart(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/keccak.h b/external/ours/library/crypto/src/shared/original/keccak.h new file mode 100755 index 000000000..f40cec5e2 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 vaue 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/external/ours/library/crypto/src/shared/original/keccak_core.cpp b/external/ours/library/crypto/src/shared/original/keccak_core.cpp new file mode 100755 index 000000000..6a8a91bf4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/keccak_core.cpp @@ -0,0 +1,261 @@ +// keccakc.cpp - Keccak core functions shared between SHA3 and Keccak. +// written and placed in the public domain by JW. + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michael Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by Ronny Van Keer, hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include "pch.h" +#include "keccak.h" + +NAMESPACE_BEGIN(CryptoPP) + +// The Keccak core function +extern void KeccakF1600(word64 *state); +// The F1600 round constants +extern const word64 KeccakF1600Constants[24]; + +NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_ALIGN_DATA(8) +const word64 KeccakF1600Constants[24] = +{ + W64LIT(0x0000000000000001), W64LIT(0x0000000000008082), + W64LIT(0x800000000000808a), W64LIT(0x8000000080008000), + W64LIT(0x000000000000808b), W64LIT(0x0000000080000001), + W64LIT(0x8000000080008081), W64LIT(0x8000000000008009), + W64LIT(0x000000000000008a), W64LIT(0x0000000000000088), + W64LIT(0x0000000080008009), W64LIT(0x000000008000000a), + W64LIT(0x000000008000808b), W64LIT(0x800000000000008b), + W64LIT(0x8000000000008089), W64LIT(0x8000000000008003), + W64LIT(0x8000000000008002), W64LIT(0x8000000000000080), + W64LIT(0x000000000000800a), W64LIT(0x800000008000000a), + W64LIT(0x8000000080008081), W64LIT(0x8000000000008080), + W64LIT(0x0000000080000001), W64LIT(0x8000000080008008) +}; + +void KeccakF1600(word64 *state) +{ + word64 Aba, Abe, Abi, Abo, Abu; + word64 Aga, Age, Agi, Ago, Agu; + word64 Aka, Ake, Aki, Ako, Aku; + word64 Ama, Ame, Ami, Amo, Amu; + word64 Asa, Ase, Asi, Aso, Asu; + word64 BCa, BCe, BCi, BCo, BCu; + word64 Da, De, Di, Do, Du; + word64 Eba, Ebe, Ebi, Ebo, Ebu; + word64 Ega, Ege, Egi, Ego, Egu; + word64 Eka, Eke, Eki, Eko, Eku; + word64 Ema, Eme, Emi, Emo, Emu; + word64 Esa, Ese, Esi, Eso, Esu; + + typedef BlockGetAndPut Block; + Block::Get(state)(Aba)(Abe)(Abi)(Abo)(Abu)(Aga)(Age)(Agi)(Ago)(Agu)(Aka)(Ake)(Aki)(Ako)(Aku)(Ama)(Ame)(Ami)(Amo)(Amu)(Asa)(Ase)(Asi)(Aso)(Asu); + + for( unsigned int round = 0; round < 24; round += 2 ) + { + // prepareTheta + BCa = Aba^Aga^Aka^Ama^Asa; + BCe = Abe^Age^Ake^Ame^Ase; + BCi = Abi^Agi^Aki^Ami^Asi; + BCo = Abo^Ago^Ako^Amo^Aso; + BCu = Abu^Agu^Aku^Amu^Asu; + + //thetaRhoPiChiIotaPrepareTheta(round , A, E) + Da = BCu^rotlConstant<1>(BCe); + De = BCa^rotlConstant<1>(BCi); + Di = BCe^rotlConstant<1>(BCo); + Do = BCi^rotlConstant<1>(BCu); + Du = BCo^rotlConstant<1>(BCa); + + Aba ^= Da; + BCa = Aba; + Age ^= De; + BCe = rotlConstant<44>(Age); + Aki ^= Di; + BCi = rotlConstant<43>(Aki); + Amo ^= Do; + BCo = rotlConstant<21>(Amo); + Asu ^= Du; + BCu = rotlConstant<14>(Asu); + Eba = BCa ^((~BCe)& BCi ); + Eba ^= KeccakF1600Constants[round]; + Ebe = BCe ^((~BCi)& BCo ); + Ebi = BCi ^((~BCo)& BCu ); + Ebo = BCo ^((~BCu)& BCa ); + Ebu = BCu ^((~BCa)& BCe ); + + Abo ^= Do; + BCa = rotlConstant<28>(Abo); + Agu ^= Du; + BCe = rotlConstant<20>(Agu); + Aka ^= Da; + BCi = rotlConstant<3>(Aka); + Ame ^= De; + BCo = rotlConstant<45>(Ame); + Asi ^= Di; + BCu = rotlConstant<61>(Asi); + Ega = BCa ^((~BCe)& BCi ); + Ege = BCe ^((~BCi)& BCo ); + Egi = BCi ^((~BCo)& BCu ); + Ego = BCo ^((~BCu)& BCa ); + Egu = BCu ^((~BCa)& BCe ); + + Abe ^= De; + BCa = rotlConstant<1>(Abe); + Agi ^= Di; + BCe = rotlConstant<6>(Agi); + Ako ^= Do; + BCi = rotlConstant<25>(Ako); + Amu ^= Du; + BCo = rotlConstant<8>(Amu); + Asa ^= Da; + BCu = rotlConstant<18>(Asa); + Eka = BCa ^((~BCe)& BCi ); + Eke = BCe ^((~BCi)& BCo ); + Eki = BCi ^((~BCo)& BCu ); + Eko = BCo ^((~BCu)& BCa ); + Eku = BCu ^((~BCa)& BCe ); + + Abu ^= Du; + BCa = rotlConstant<27>(Abu); + Aga ^= Da; + BCe = rotlConstant<36>(Aga); + Ake ^= De; + BCi = rotlConstant<10>(Ake); + Ami ^= Di; + BCo = rotlConstant<15>(Ami); + Aso ^= Do; + BCu = rotlConstant<56>(Aso); + Ema = BCa ^((~BCe)& BCi ); + Eme = BCe ^((~BCi)& BCo ); + Emi = BCi ^((~BCo)& BCu ); + Emo = BCo ^((~BCu)& BCa ); + Emu = BCu ^((~BCa)& BCe ); + + Abi ^= Di; + BCa = rotlConstant<62>(Abi); + Ago ^= Do; + BCe = rotlConstant<55>(Ago); + Aku ^= Du; + BCi = rotlConstant<39>(Aku); + Ama ^= Da; + BCo = rotlConstant<41>(Ama); + Ase ^= De; + BCu = rotlConstant<2>(Ase); + Esa = BCa ^((~BCe)& BCi ); + Ese = BCe ^((~BCi)& BCo ); + Esi = BCi ^((~BCo)& BCu ); + Eso = BCo ^((~BCu)& BCa ); + Esu = BCu ^((~BCa)& BCe ); + + // prepareTheta + BCa = Eba^Ega^Eka^Ema^Esa; + BCe = Ebe^Ege^Eke^Eme^Ese; + BCi = Ebi^Egi^Eki^Emi^Esi; + BCo = Ebo^Ego^Eko^Emo^Eso; + BCu = Ebu^Egu^Eku^Emu^Esu; + + //thetaRhoPiChiIotaPrepareTheta(round+1, E, A) + Da = BCu^rotlConstant<1>(BCe); + De = BCa^rotlConstant<1>(BCi); + Di = BCe^rotlConstant<1>(BCo); + Do = BCi^rotlConstant<1>(BCu); + Du = BCo^rotlConstant<1>(BCa); + + Eba ^= Da; + BCa = Eba; + Ege ^= De; + BCe = rotlConstant<44>(Ege); + Eki ^= Di; + BCi = rotlConstant<43>(Eki); + Emo ^= Do; + BCo = rotlConstant<21>(Emo); + Esu ^= Du; + BCu = rotlConstant<14>(Esu); + Aba = BCa ^((~BCe)& BCi ); + Aba ^= KeccakF1600Constants[round+1]; + Abe = BCe ^((~BCi)& BCo ); + Abi = BCi ^((~BCo)& BCu ); + Abo = BCo ^((~BCu)& BCa ); + Abu = BCu ^((~BCa)& BCe ); + + Ebo ^= Do; + BCa = rotlConstant<28>(Ebo); + Egu ^= Du; + BCe = rotlConstant<20>(Egu); + Eka ^= Da; + BCi = rotlConstant<3>(Eka); + Eme ^= De; + BCo = rotlConstant<45>(Eme); + Esi ^= Di; + BCu = rotlConstant<61>(Esi); + Aga = BCa ^((~BCe)& BCi ); + Age = BCe ^((~BCi)& BCo ); + Agi = BCi ^((~BCo)& BCu ); + Ago = BCo ^((~BCu)& BCa ); + Agu = BCu ^((~BCa)& BCe ); + + Ebe ^= De; + BCa = rotlConstant<1>(Ebe); + Egi ^= Di; + BCe = rotlConstant<6>(Egi); + Eko ^= Do; + BCi = rotlConstant<25>(Eko); + Emu ^= Du; + BCo = rotlConstant<8>(Emu); + Esa ^= Da; + BCu = rotlConstant<18>(Esa); + Aka = BCa ^((~BCe)& BCi ); + Ake = BCe ^((~BCi)& BCo ); + Aki = BCi ^((~BCo)& BCu ); + Ako = BCo ^((~BCu)& BCa ); + Aku = BCu ^((~BCa)& BCe ); + + Ebu ^= Du; + BCa = rotlConstant<27>(Ebu); + Ega ^= Da; + BCe = rotlConstant<36>(Ega); + Eke ^= De; + BCi = rotlConstant<10>(Eke); + Emi ^= Di; + BCo = rotlConstant<15>(Emi); + Eso ^= Do; + BCu = rotlConstant<56>(Eso); + Ama = BCa ^((~BCe)& BCi ); + Ame = BCe ^((~BCi)& BCo ); + Ami = BCi ^((~BCo)& BCu ); + Amo = BCo ^((~BCu)& BCa ); + Amu = BCu ^((~BCa)& BCe ); + + Ebi ^= Di; + BCa = rotlConstant<62>(Ebi); + Ego ^= Do; + BCe = rotlConstant<55>(Ego); + Eku ^= Du; + BCi = rotlConstant<39>(Eku); + Ema ^= Da; + BCo = rotlConstant<41>(Ema); + Ese ^= De; + BCu = rotlConstant<2>(Ese); + Asa = BCa ^((~BCe)& BCi ); + Ase = BCe ^((~BCi)& BCo ); + Asi = BCi ^((~BCo)& BCu ); + Aso = BCo ^((~BCu)& BCa ); + Asu = BCu ^((~BCa)& BCe ); + } + + Block::Put(NULLPTR, state)(Aba)(Abe)(Abi)(Abo)(Abu)(Aga)(Age)(Agi)(Ago)(Agu)(Aka)(Ake)(Aki)(Ako)(Aku)(Ama)(Ame)(Ami)(Amo)(Amu)(Asa)(Ase)(Asi)(Aso)(Asu); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/keccak_simd.cpp b/external/ours/library/crypto/src/shared/original/keccak_simd.cpp new file mode 100755 index 000000000..5a534a99b --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/keccak_simd.cpp @@ -0,0 +1,2681 @@ +// keccak_simd.cpp - written and placed in the public domain by Jeffrey Walton. +// +// This source file uses intrinsics to gain access to SSE and +// NEON instructions. A separate source file is needed because +// additional CXXFLAGS are required to enable the appropriate +// instructions sets in some build configurations. + +// The XKCP package is provided by Guido Bertoni, Joan Daemen, Seth Hoffert, +// Michael Peeters, Gilles Van Assche, and Ronny Van Keer. The code was +// placed public domain by the authors. + +// KeccakF1600x2_SSE is ParallelHash128. The SSE2 ParallelHash128 +// implementation was extracted from XKCP using the following command. +// +// gcc -I lib/common -I lib/low/KeccakP-1600/Optimized +// -I lib/low/KeccakP-1600-times2/SIMD128/SSE2ufull +// lib/low/KeccakP-1600-times2/SIMD128/KeccakP-1600-times2-SIMD128.c -E + +#include "pch.h" +#include "config.h" +#include "keccak.h" +#include "misc.h" + +#if (CRYPTOPP_SSSE3_AVAILABLE) +# include +# include +#endif + +#if defined(__XOP__) +# include +# if defined(__GNUC__) +# include +# endif +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char KECCAK_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +#if (CRYPTOPP_SSSE3_AVAILABLE) + +// The Keccak ParallelHash128 core function +extern void KeccakF1600x2_SSE(word64 *state); + +// The F1600 round constants +extern const word64 KeccakF1600Constants[24]; + +CRYPTOPP_ALIGN_DATA(16) +const word64 +rho8[2] = {W64LIT(0x0605040302010007), W64LIT(0x0E0D0C0B0A09080F)}; + +CRYPTOPP_ALIGN_DATA(16) +const word64 +rho56[2] = {W64LIT(0x0007060504030201), W64LIT(0x080F0E0D0C0B0A09)}; + +#if defined(__XOP__) +# define ROL64in128(a, o) _mm_roti_epi64((a), (o)) +# define ROL64in128_8(a) ROL64in128((a), 8) +# define ROL64in128_56(a) ROL64in128((a), 56) +#else +# define ROL64in128(a, o) _mm_or_si128(_mm_slli_epi64((a), (o)), _mm_srli_epi64(a, 64-(o))) +# define ROL64in128_8(a) _mm_shuffle_epi8((a), _mm_load_si128(CONST_M128_CAST(rho8))) +# define ROL64in128_56(a) _mm_shuffle_epi8((a), _mm_load_si128(CONST_M128_CAST(rho56))) +#endif + +// Damn Visual Studio is missing too many intrinsics... +inline __m128i SPLAT64(const word64 a) +{ +#if defined(_MSC_VER) + double x; std::memcpy(&x, &a, 8); + return _mm_castpd_si128(_mm_loaddup_pd(&x)); +#else + return _mm_set1_epi64x(a); +#endif +} + +// The Keccak ParallelHash128 core function +void KeccakF1600x2_SSE(word64 *state) +{ + __m128i Aba, Abe, Abi, Abo, Abu; + __m128i Aga, Age, Agi, Ago, Agu; + __m128i Aka, Ake, Aki, Ako, Aku; + __m128i Ama, Ame, Ami, Amo, Amu; + __m128i Asa, Ase, Asi, Aso, Asu; + __m128i Bba, Bbe, Bbi, Bbo, Bbu; + __m128i Bga, Bge, Bgi, Bgo, Bgu; + __m128i Bka, Bke, Bki, Bko, Bku; + __m128i Bma, Bme, Bmi, Bmo, Bmu; + __m128i Bsa, Bse, Bsi, Bso, Bsu; + __m128i Ca, Ce, Ci, Co, Cu; + __m128i Da, De, Di, Do, Du; + __m128i Eba, Ebe, Ebi, Ebo, Ebu; + __m128i Ega, Ege, Egi, Ego, Egu; + __m128i Eka, Eke, Eki, Eko, Eku; + __m128i Ema, Eme, Emi, Emo, Emu; + __m128i Esa, Ese, Esi, Eso, Esu; + + __m128i* lanes = reinterpret_cast<__m128i*>(state); + Aba = _mm_loadu_si128(CONST_M128_CAST(lanes+ 0)); + Abe = _mm_loadu_si128(CONST_M128_CAST(lanes+ 1)); + Abi = _mm_loadu_si128(CONST_M128_CAST(lanes+ 2)); + Abo = _mm_loadu_si128(CONST_M128_CAST(lanes+ 3)); + Abu = _mm_loadu_si128(CONST_M128_CAST(lanes+ 4)); + Aga = _mm_loadu_si128(CONST_M128_CAST(lanes+ 5)); + Age = _mm_loadu_si128(CONST_M128_CAST(lanes+ 6)); + Agi = _mm_loadu_si128(CONST_M128_CAST(lanes+ 7)); + Ago = _mm_loadu_si128(CONST_M128_CAST(lanes+ 8)); + Agu = _mm_loadu_si128(CONST_M128_CAST(lanes+ 9)); + Aka = _mm_loadu_si128(CONST_M128_CAST(lanes+10)); + Ake = _mm_loadu_si128(CONST_M128_CAST(lanes+11)); + Aki = _mm_loadu_si128(CONST_M128_CAST(lanes+12)); + Ako = _mm_loadu_si128(CONST_M128_CAST(lanes+13)); + Aku = _mm_loadu_si128(CONST_M128_CAST(lanes+14)); + Ama = _mm_loadu_si128(CONST_M128_CAST(lanes+15)); + Ame = _mm_loadu_si128(CONST_M128_CAST(lanes+16)); + Ami = _mm_loadu_si128(CONST_M128_CAST(lanes+17)); + Amo = _mm_loadu_si128(CONST_M128_CAST(lanes+18)); + Amu = _mm_loadu_si128(CONST_M128_CAST(lanes+19)); + Asa = _mm_loadu_si128(CONST_M128_CAST(lanes+20)); + Ase = _mm_loadu_si128(CONST_M128_CAST(lanes+21)); + Asi = _mm_loadu_si128(CONST_M128_CAST(lanes+22)); + Aso = _mm_loadu_si128(CONST_M128_CAST(lanes+23)); + Asu = _mm_loadu_si128(CONST_M128_CAST(lanes+24)); + + Ca = _mm_xor_si128(Aba, _mm_xor_si128(Aga, _mm_xor_si128(Aka, _mm_xor_si128(Ama, Asa)))); + Ce = _mm_xor_si128(Abe, _mm_xor_si128(Age, _mm_xor_si128(Ake, _mm_xor_si128(Ame, Ase)))); + Ci = _mm_xor_si128(Abi, _mm_xor_si128(Agi, _mm_xor_si128(Aki, _mm_xor_si128(Ami, Asi)))); + Co = _mm_xor_si128(Abo, _mm_xor_si128(Ago, _mm_xor_si128(Ako, _mm_xor_si128(Amo, Aso)))); + Cu = _mm_xor_si128(Abu, _mm_xor_si128(Agu, _mm_xor_si128(Aku, _mm_xor_si128(Amu, Asu)))); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[0])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[1])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[2])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[3])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[4])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[5])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[6])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[7])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[8])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[9])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[10])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[11])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[12])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[13])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[14])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[15])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[16])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[17])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[18])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[19])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[20])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[21])); + Ca = Aba; + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Abe; + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Abi; + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Abo; + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Abu; + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Aga); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Age); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Agi); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ago); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Agu); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Aka); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Ake); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Aki); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Ako); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Aku); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ama); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Ame); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Ami); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Amo); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Amu); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Asa); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ase); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Asi); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Aso); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Asu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Aba = _mm_xor_si128(Aba, Da); + Bba = Aba; + Age = _mm_xor_si128(Age, De); + Bbe = ROL64in128(Age, 44); + Aki = _mm_xor_si128(Aki, Di); + Bbi = ROL64in128(Aki, 43); + Eba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Eba = _mm_xor_si128(Eba, SPLAT64(KeccakF1600Constants[22])); + Ca = Eba; + Amo = _mm_xor_si128(Amo, Do); + Bbo = ROL64in128(Amo, 21); + Ebe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Ce = Ebe; + Asu = _mm_xor_si128(Asu, Du); + Bbu = ROL64in128(Asu, 14); + Ebi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Ci = Ebi; + Ebo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Co = Ebo; + Ebu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Cu = Ebu; + Abo = _mm_xor_si128(Abo, Do); + Bga = ROL64in128(Abo, 28); + Agu = _mm_xor_si128(Agu, Du); + Bge = ROL64in128(Agu, 20); + Aka = _mm_xor_si128(Aka, Da); + Bgi = ROL64in128(Aka, 3); + Ega = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Ca = _mm_xor_si128(Ca, Ega); + Ame = _mm_xor_si128(Ame, De); + Bgo = ROL64in128(Ame, 45); + Ege = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Ce = _mm_xor_si128(Ce, Ege); + Asi = _mm_xor_si128(Asi, Di); + Bgu = ROL64in128(Asi, 61); + Egi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ci = _mm_xor_si128(Ci, Egi); + Ego = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Co = _mm_xor_si128(Co, Ego); + Egu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Cu = _mm_xor_si128(Cu, Egu); + Abe = _mm_xor_si128(Abe, De); + Bka = ROL64in128(Abe, 1); + Agi = _mm_xor_si128(Agi, Di); + Bke = ROL64in128(Agi, 6); + Ako = _mm_xor_si128(Ako, Do); + Bki = ROL64in128(Ako, 25); + Eka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Ca = _mm_xor_si128(Ca, Eka); + Amu = _mm_xor_si128(Amu, Du); + Bko = ROL64in128_8(Amu); + Eke = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Ce = _mm_xor_si128(Ce, Eke); + Asa = _mm_xor_si128(Asa, Da); + Bku = ROL64in128(Asa, 18); + Eki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ci = _mm_xor_si128(Ci, Eki); + Eko = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Co = _mm_xor_si128(Co, Eko); + Eku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Cu = _mm_xor_si128(Cu, Eku); + Abu = _mm_xor_si128(Abu, Du); + Bma = ROL64in128(Abu, 27); + Aga = _mm_xor_si128(Aga, Da); + Bme = ROL64in128(Aga, 36); + Ake = _mm_xor_si128(Ake, De); + Bmi = ROL64in128(Ake, 10); + Ema = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Ca = _mm_xor_si128(Ca, Ema); + Ami = _mm_xor_si128(Ami, Di); + Bmo = ROL64in128(Ami, 15); + Eme = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Ce = _mm_xor_si128(Ce, Eme); + Aso = _mm_xor_si128(Aso, Do); + Bmu = ROL64in128_56(Aso); + Emi = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Ci = _mm_xor_si128(Ci, Emi); + Emo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Co = _mm_xor_si128(Co, Emo); + Emu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Cu = _mm_xor_si128(Cu, Emu); + Abi = _mm_xor_si128(Abi, Di); + Bsa = ROL64in128(Abi, 62); + Ago = _mm_xor_si128(Ago, Do); + Bse = ROL64in128(Ago, 55); + Aku = _mm_xor_si128(Aku, Du); + Bsi = ROL64in128(Aku, 39); + Esa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ca = _mm_xor_si128(Ca, Esa); + Ama = _mm_xor_si128(Ama, Da); + Bso = ROL64in128(Ama, 41); + Ese = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ce = _mm_xor_si128(Ce, Ese); + Ase = _mm_xor_si128(Ase, De); + Bsu = ROL64in128(Ase, 2); + Esi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Ci = _mm_xor_si128(Ci, Esi); + Eso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Co = _mm_xor_si128(Co, Eso); + Esu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + Cu = _mm_xor_si128(Cu, Esu); + Da = _mm_xor_si128(Cu, ROL64in128(Ce, 1)); + De = _mm_xor_si128(Ca, ROL64in128(Ci, 1)); + Di = _mm_xor_si128(Ce, ROL64in128(Co, 1)); + Do = _mm_xor_si128(Ci, ROL64in128(Cu, 1)); + Du = _mm_xor_si128(Co, ROL64in128(Ca, 1)); + Eba = _mm_xor_si128(Eba, Da); + Bba = Eba; + Ege = _mm_xor_si128(Ege, De); + Bbe = ROL64in128(Ege, 44); + Eki = _mm_xor_si128(Eki, Di); + Bbi = ROL64in128(Eki, 43); + Aba = _mm_xor_si128(Bba, _mm_andnot_si128(Bbe, Bbi)); + Aba = _mm_xor_si128(Aba, SPLAT64(KeccakF1600Constants[23])); + Emo = _mm_xor_si128(Emo, Do); + Bbo = ROL64in128(Emo, 21); + Abe = _mm_xor_si128(Bbe, _mm_andnot_si128(Bbi, Bbo)); + Esu = _mm_xor_si128(Esu, Du); + Bbu = ROL64in128(Esu, 14); + Abi = _mm_xor_si128(Bbi, _mm_andnot_si128(Bbo, Bbu)); + Abo = _mm_xor_si128(Bbo, _mm_andnot_si128(Bbu, Bba)); + Abu = _mm_xor_si128(Bbu, _mm_andnot_si128(Bba, Bbe)); + Ebo = _mm_xor_si128(Ebo, Do); + Bga = ROL64in128(Ebo, 28); + Egu = _mm_xor_si128(Egu, Du); + Bge = ROL64in128(Egu, 20); + Eka = _mm_xor_si128(Eka, Da); + Bgi = ROL64in128(Eka, 3); + Aga = _mm_xor_si128(Bga, _mm_andnot_si128(Bge, Bgi)); + Eme = _mm_xor_si128(Eme, De); + Bgo = ROL64in128(Eme, 45); + Age = _mm_xor_si128(Bge, _mm_andnot_si128(Bgi, Bgo)); + Esi = _mm_xor_si128(Esi, Di); + Bgu = ROL64in128(Esi, 61); + Agi = _mm_xor_si128(Bgi, _mm_andnot_si128(Bgo, Bgu)); + Ago = _mm_xor_si128(Bgo, _mm_andnot_si128(Bgu, Bga)); + Agu = _mm_xor_si128(Bgu, _mm_andnot_si128(Bga, Bge)); + Ebe = _mm_xor_si128(Ebe, De); + Bka = ROL64in128(Ebe, 1); + Egi = _mm_xor_si128(Egi, Di); + Bke = ROL64in128(Egi, 6); + Eko = _mm_xor_si128(Eko, Do); + Bki = ROL64in128(Eko, 25); + Aka = _mm_xor_si128(Bka, _mm_andnot_si128(Bke, Bki)); + Emu = _mm_xor_si128(Emu, Du); + Bko = ROL64in128_8(Emu); + Ake = _mm_xor_si128(Bke, _mm_andnot_si128(Bki, Bko)); + Esa = _mm_xor_si128(Esa, Da); + Bku = ROL64in128(Esa, 18); + Aki = _mm_xor_si128(Bki, _mm_andnot_si128(Bko, Bku)); + Ako = _mm_xor_si128(Bko, _mm_andnot_si128(Bku, Bka)); + Aku = _mm_xor_si128(Bku, _mm_andnot_si128(Bka, Bke)); + Ebu = _mm_xor_si128(Ebu, Du); + Bma = ROL64in128(Ebu, 27); + Ega = _mm_xor_si128(Ega, Da); + Bme = ROL64in128(Ega, 36); + Eke = _mm_xor_si128(Eke, De); + Bmi = ROL64in128(Eke, 10); + Ama = _mm_xor_si128(Bma, _mm_andnot_si128(Bme, Bmi)); + Emi = _mm_xor_si128(Emi, Di); + Bmo = ROL64in128(Emi, 15); + Ame = _mm_xor_si128(Bme, _mm_andnot_si128(Bmi, Bmo)); + Eso = _mm_xor_si128(Eso, Do); + Bmu = ROL64in128_56(Eso); + Ami = _mm_xor_si128(Bmi, _mm_andnot_si128(Bmo, Bmu)); + Amo = _mm_xor_si128(Bmo, _mm_andnot_si128(Bmu, Bma)); + Amu = _mm_xor_si128(Bmu, _mm_andnot_si128(Bma, Bme)); + Ebi = _mm_xor_si128(Ebi, Di); + Bsa = ROL64in128(Ebi, 62); + Ego = _mm_xor_si128(Ego, Do); + Bse = ROL64in128(Ego, 55); + Eku = _mm_xor_si128(Eku, Du); + Bsi = ROL64in128(Eku, 39); + Asa = _mm_xor_si128(Bsa, _mm_andnot_si128(Bse, Bsi)); + Ema = _mm_xor_si128(Ema, Da); + Bso = ROL64in128(Ema, 41); + Ase = _mm_xor_si128(Bse, _mm_andnot_si128(Bsi, Bso)); + Ese = _mm_xor_si128(Ese, De); + Bsu = ROL64in128(Ese, 2); + Asi = _mm_xor_si128(Bsi, _mm_andnot_si128(Bso, Bsu)); + Aso = _mm_xor_si128(Bso, _mm_andnot_si128(Bsu, Bsa)); + Asu = _mm_xor_si128(Bsu, _mm_andnot_si128(Bsa, Bse)); + + _mm_storeu_si128(M128_CAST(lanes+ 0), Aba); + _mm_storeu_si128(M128_CAST(lanes+ 1), Abe); + _mm_storeu_si128(M128_CAST(lanes+ 2), Abi); + _mm_storeu_si128(M128_CAST(lanes+ 3), Abo); + _mm_storeu_si128(M128_CAST(lanes+ 4), Abu); + _mm_storeu_si128(M128_CAST(lanes+ 5), Aga); + _mm_storeu_si128(M128_CAST(lanes+ 6), Age); + _mm_storeu_si128(M128_CAST(lanes+ 7), Agi); + _mm_storeu_si128(M128_CAST(lanes+ 8), Ago); + _mm_storeu_si128(M128_CAST(lanes+ 9), Agu); + _mm_storeu_si128(M128_CAST(lanes+10), Aka); + _mm_storeu_si128(M128_CAST(lanes+11), Ake); + _mm_storeu_si128(M128_CAST(lanes+12), Aki); + _mm_storeu_si128(M128_CAST(lanes+13), Ako); + _mm_storeu_si128(M128_CAST(lanes+14), Aku); + _mm_storeu_si128(M128_CAST(lanes+15), Ama); + _mm_storeu_si128(M128_CAST(lanes+16), Ame); + _mm_storeu_si128(M128_CAST(lanes+17), Ami); + _mm_storeu_si128(M128_CAST(lanes+18), Amo); + _mm_storeu_si128(M128_CAST(lanes+19), Amu); + _mm_storeu_si128(M128_CAST(lanes+20), Asa); + _mm_storeu_si128(M128_CAST(lanes+21), Ase); + _mm_storeu_si128(M128_CAST(lanes+22), Asi); + _mm_storeu_si128(M128_CAST(lanes+23), Aso); + _mm_storeu_si128(M128_CAST(lanes+24), Asu); +} + +#endif + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/lea.cpp b/external/ours/library/crypto/src/shared/original/lea.cpp new file mode 100755 index 000000000..4361d5139 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/lea.cpp @@ -0,0 +1,899 @@ +// lea.cpp - 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. +// +// This implementation is based on source files found in a zip file at the +// Korea Internet and Security Agency (https://www.kisa.or.kr/eng/main.jsp). +// The zip files was downloaded from the Korean language area of the site so we +// don't have a url or english zip filename to cite. The source filename from +// the zip is lea_core.c. +// +// The LEA team appears to have applied optimizations to functions in lea_core.c. +// The implementation does not exactly follow the aglorithmic description from +// the LEA paper. + +#include "pch.h" +#include "config.h" + +#include "lea.h" +#include "misc.h" +#include "cpu.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; +using CryptoPP::rotlConstant; + +ANONYMOUS_NAMESPACE_END + +const word32 delta[8][36] = { + {0xc3efe9db, 0x87dfd3b7, 0x0fbfa76f, 0x1f7f4ede, 0x3efe9dbc, 0x7dfd3b78, 0xfbfa76f0, 0xf7f4ede1, + 0xefe9dbc3, 0xdfd3b787, 0xbfa76f0f, 0x7f4ede1f, 0xfe9dbc3e, 0xfd3b787d, 0xfa76f0fb, 0xf4ede1f7, + 0xe9dbc3ef, 0xd3b787df, 0xa76f0fbf, 0x4ede1f7f, 0x9dbc3efe, 0x3b787dfd, 0x76f0fbfa, 0xede1f7f4, + 0xdbc3efe9, 0xb787dfd3, 0x6f0fbfa7, 0xde1f7f4e, 0xbc3efe9d, 0x787dfd3b, 0xf0fbfa76, 0xe1f7f4eD, + 0xc3efe9db, 0x87dfd3b7, 0x0fbfa76f, 0x1f7f4ede}, + {0x44626b02, 0x88c4d604, 0x1189ac09, 0x23135812, 0x4626b024, 0x8c4d6048, 0x189ac091, 0x31358122, + 0x626b0244, 0xc4d60488, 0x89ac0911, 0x13581223, 0x26b02446, 0x4d60488c, 0x9ac09118, 0x35812231, + 0x6b024462, 0xd60488c4, 0xac091189, 0x58122313, 0xb0244626, 0x60488c4d, 0xc091189a, 0x81223135, + 0x0244626b, 0x0488c4d6, 0x091189ac, 0x12231358, 0x244626b0, 0x488c4d60, 0x91189ac0, 0x22313581, + 0x44626b02, 0x88c4d604, 0x1189ac09, 0x23135812}, + {0x79e27c8a, 0xf3c4f914, 0xe789f229, 0xcf13e453, 0x9e27c8a7, 0x3c4f914f, 0x789f229e, 0xf13e453c, + 0xe27c8a79, 0xc4f914f3, 0x89f229e7, 0x13e453cf, 0x27c8a79e, 0x4f914f3c, 0x9f229e78, 0x3e453cf1, + 0x7c8a79e2, 0xf914f3c4, 0xf229e789, 0xe453cf13, 0xc8a79e27, 0x914f3c4f, 0x229e789f, 0x453cf13e, + 0x8a79e27c, 0x14f3c4f9, 0x29e789f2, 0x53cf13e4, 0xa79e27c8, 0x4f3c4f91, 0x9e789f22, 0x3cf13e45, + 0x79e27c8a, 0xf3c4f914, 0xe789f229, 0xcf13e453}, + {0x78df30ec, 0xf1be61d8, 0xe37cc3b1, 0xc6f98763, 0x8df30ec7, 0x1be61d8f, 0x37cc3b1e, 0x6f98763c, + 0xdf30ec78, 0xbe61d8f1, 0x7cc3b1e3, 0xf98763c6, 0xf30ec78d, 0xe61d8f1b, 0xcc3b1e37, 0x98763c6f, + 0x30ec78df, 0x61d8f1be, 0xc3b1e37c, 0x8763c6f9, 0x0ec78df3, 0x1d8f1be6, 0x3b1e37cc, 0x763c6f98, + 0xec78df30, 0xd8f1be61, 0xb1e37cc3, 0x63c6f987, 0xc78df30e, 0x8f1be61d, 0x1e37cc3b, 0x3c6f9876, + 0x78df30ec, 0xf1be61d8, 0xe37cc3b1, 0xc6f98763}, + {0x715ea49e, 0xe2bd493c, 0xc57a9279, 0x8af524f3, 0x15ea49e7, 0x2bd493ce, 0x57a9279c, 0xaf524f38, + 0x5ea49e71, 0xbd493ce2, 0x7a9279c5, 0xf524f38a, 0xea49e715, 0xd493ce2b, 0xa9279c57, 0x524f38af, + 0xa49e715e, 0x493ce2bd, 0x9279c57a, 0x24f38af5, 0x49e715ea, 0x93ce2bd4, 0x279c57a9, 0x4f38af52, + 0x9e715ea4, 0x3ce2bd49, 0x79c57a92, 0xf38af524, 0xe715ea49, 0xce2bd493, 0x9c57a927, 0x38af524f, + 0x715ea49e, 0xe2bd493c, 0xc57a9279, 0x8af524f3}, + {0xc785da0a, 0x8f0bb415, 0x1e17682b, 0x3c2ed056, 0x785da0ac, 0xf0bb4158, 0xe17682b1, 0xc2ed0563, + 0x85da0ac7, 0x0bb4158f, 0x17682b1e, 0x2ed0563c, 0x5da0ac78, 0xbb4158f0, 0x7682b1e1, 0xed0563c2, + 0xda0ac785, 0xb4158f0b, 0x682b1e17, 0xd0563c2e, 0xa0ac785d, 0x4158f0bb, 0x82b1e176, 0x0563c2ed, + 0x0ac785da, 0x158f0bb4, 0x2b1e1768, 0x563c2ed0, 0xac785da0, 0x58f0bb41, 0xb1e17682, 0x63c2ed05, + 0xc785da0a, 0x8f0bb415, 0x1e17682b, 0x3c2ed056}, + {0xe04ef22a, 0xc09de455, 0x813bc8ab, 0x02779157, 0x04ef22ae, 0x09de455c, 0x13bc8ab8, 0x27791570, + 0x4ef22ae0, 0x9de455c0, 0x3bc8ab81, 0x77915702, 0xef22ae04, 0xde455c09, 0xbc8ab813, 0x79157027, + 0xf22ae04e, 0xe455c09d, 0xc8ab813b, 0x91570277, 0x22ae04ef, 0x455c09de, 0x8ab813bc, 0x15702779, + 0x2ae04ef2, 0x55c09de4, 0xab813bc8, 0x57027791, 0xae04ef22, 0x5c09de45, 0xb813bc8a, 0x70277915, + 0xe04ef22a, 0xc09de455, 0x813bc8ab, 0x02779157}, + {0xe5c40957, 0xcb8812af, 0x9710255f, 0x2e204abf, 0x5c40957e, 0xb8812afc, 0x710255f9, 0xe204abf2, + 0xc40957e5, 0x8812afcb, 0x10255f97, 0x204abf2e, 0x40957e5c, 0x812afcb8, 0x0255f971, 0x04abf2e2, + 0x0957e5c4, 0x12afcb88, 0x255f9710, 0x4abf2e20, 0x957e5c40, 0x2afcb881, 0x55f97102, 0xabf2e204, + 0x57e5c409, 0xafcb8812, 0x5f971025, 0xbf2e204a, 0x7e5c4095, 0xfcb8812a, 0xf9710255, 0xf2e204ab, + 0xe5c40957, 0xcb8812af, 0x9710255f, 0x2e204abf} +}; + +inline void SetKey128(word32 rkey[144], const word32 key[4]) +{ + rkey[ 0] = rotlConstant<1>( key[ 0] + delta[0][ 0]); + rkey[ 6] = rotlConstant<1>(rkey[ 0] + delta[1][ 1]); + rkey[ 12] = rotlConstant<1>(rkey[ 6] + delta[2][ 2]); + rkey[ 18] = rotlConstant<1>(rkey[ 12] + delta[3][ 3]); + rkey[ 24] = rotlConstant<1>(rkey[ 18] + delta[0][ 4]); + rkey[ 30] = rotlConstant<1>(rkey[ 24] + delta[1][ 5]); + rkey[ 36] = rotlConstant<1>(rkey[ 30] + delta[2][ 6]); + rkey[ 42] = rotlConstant<1>(rkey[ 36] + delta[3][ 7]); + rkey[ 48] = rotlConstant<1>(rkey[ 42] + delta[0][ 8]); + rkey[ 54] = rotlConstant<1>(rkey[ 48] + delta[1][ 9]); + rkey[ 60] = rotlConstant<1>(rkey[ 54] + delta[2][10]); + rkey[ 66] = rotlConstant<1>(rkey[ 60] + delta[3][11]); + rkey[ 72] = rotlConstant<1>(rkey[ 66] + delta[0][12]); + rkey[ 78] = rotlConstant<1>(rkey[ 72] + delta[1][13]); + rkey[ 84] = rotlConstant<1>(rkey[ 78] + delta[2][14]); + rkey[ 90] = rotlConstant<1>(rkey[ 84] + delta[3][15]); + rkey[ 96] = rotlConstant<1>(rkey[ 90] + delta[0][16]); + rkey[102] = rotlConstant<1>(rkey[ 96] + delta[1][17]); + rkey[108] = rotlConstant<1>(rkey[102] + delta[2][18]); + rkey[114] = rotlConstant<1>(rkey[108] + delta[3][19]); + rkey[120] = rotlConstant<1>(rkey[114] + delta[0][20]); + rkey[126] = rotlConstant<1>(rkey[120] + delta[1][21]); + rkey[132] = rotlConstant<1>(rkey[126] + delta[2][22]); + rkey[138] = rotlConstant<1>(rkey[132] + delta[3][23]); + + rkey[ 1] = rkey[ 3] = rkey[ 5] = rotlConstant<3>( key[ 1] + delta[0][ 1]); + rkey[ 7] = rkey[ 9] = rkey[ 11] = rotlConstant<3>(rkey[ 1] + delta[1][ 2]); + rkey[ 13] = rkey[ 15] = rkey[ 17] = rotlConstant<3>(rkey[ 7] + delta[2][ 3]); + rkey[ 19] = rkey[ 21] = rkey[ 23] = rotlConstant<3>(rkey[ 13] + delta[3][ 4]); + rkey[ 25] = rkey[ 27] = rkey[ 29] = rotlConstant<3>(rkey[ 19] + delta[0][ 5]); + rkey[ 31] = rkey[ 33] = rkey[ 35] = rotlConstant<3>(rkey[ 25] + delta[1][ 6]); + rkey[ 37] = rkey[ 39] = rkey[ 41] = rotlConstant<3>(rkey[ 31] + delta[2][ 7]); + rkey[ 43] = rkey[ 45] = rkey[ 47] = rotlConstant<3>(rkey[ 37] + delta[3][ 8]); + rkey[ 49] = rkey[ 51] = rkey[ 53] = rotlConstant<3>(rkey[ 43] + delta[0][ 9]); + rkey[ 55] = rkey[ 57] = rkey[ 59] = rotlConstant<3>(rkey[ 49] + delta[1][10]); + rkey[ 61] = rkey[ 63] = rkey[ 65] = rotlConstant<3>(rkey[ 55] + delta[2][11]); + rkey[ 67] = rkey[ 69] = rkey[ 71] = rotlConstant<3>(rkey[ 61] + delta[3][12]); + rkey[ 73] = rkey[ 75] = rkey[ 77] = rotlConstant<3>(rkey[ 67] + delta[0][13]); + rkey[ 79] = rkey[ 81] = rkey[ 83] = rotlConstant<3>(rkey[ 73] + delta[1][14]); + rkey[ 85] = rkey[ 87] = rkey[ 89] = rotlConstant<3>(rkey[ 79] + delta[2][15]); + rkey[ 91] = rkey[ 93] = rkey[ 95] = rotlConstant<3>(rkey[ 85] + delta[3][16]); + rkey[ 97] = rkey[ 99] = rkey[101] = rotlConstant<3>(rkey[ 91] + delta[0][17]); + rkey[103] = rkey[105] = rkey[107] = rotlConstant<3>(rkey[ 97] + delta[1][18]); + rkey[109] = rkey[111] = rkey[113] = rotlConstant<3>(rkey[103] + delta[2][19]); + rkey[115] = rkey[117] = rkey[119] = rotlConstant<3>(rkey[109] + delta[3][20]); + rkey[121] = rkey[123] = rkey[125] = rotlConstant<3>(rkey[115] + delta[0][21]); + rkey[127] = rkey[129] = rkey[131] = rotlConstant<3>(rkey[121] + delta[1][22]); + rkey[133] = rkey[135] = rkey[137] = rotlConstant<3>(rkey[127] + delta[2][23]); + rkey[139] = rkey[141] = rkey[143] = rotlConstant<3>(rkey[133] + delta[3][24]); + + rkey[ 2] = rotlConstant<6>( key[ 2] + delta[0][ 2]); + rkey[ 8] = rotlConstant<6>(rkey[ 2] + delta[1][ 3]); + rkey[ 14] = rotlConstant<6>(rkey[ 8] + delta[2][ 4]); + rkey[ 20] = rotlConstant<6>(rkey[ 14] + delta[3][ 5]); + rkey[ 26] = rotlConstant<6>(rkey[ 20] + delta[0][ 6]); + rkey[ 32] = rotlConstant<6>(rkey[ 26] + delta[1][ 7]); + rkey[ 38] = rotlConstant<6>(rkey[ 32] + delta[2][ 8]); + rkey[ 44] = rotlConstant<6>(rkey[ 38] + delta[3][ 9]); + rkey[ 50] = rotlConstant<6>(rkey[ 44] + delta[0][10]); + rkey[ 56] = rotlConstant<6>(rkey[ 50] + delta[1][11]); + rkey[ 62] = rotlConstant<6>(rkey[ 56] + delta[2][12]); + rkey[ 68] = rotlConstant<6>(rkey[ 62] + delta[3][13]); + rkey[ 74] = rotlConstant<6>(rkey[ 68] + delta[0][14]); + rkey[ 80] = rotlConstant<6>(rkey[ 74] + delta[1][15]); + rkey[ 86] = rotlConstant<6>(rkey[ 80] + delta[2][16]); + rkey[ 92] = rotlConstant<6>(rkey[ 86] + delta[3][17]); + rkey[ 98] = rotlConstant<6>(rkey[ 92] + delta[0][18]); + rkey[104] = rotlConstant<6>(rkey[ 98] + delta[1][19]); + rkey[110] = rotlConstant<6>(rkey[104] + delta[2][20]); + rkey[116] = rotlConstant<6>(rkey[110] + delta[3][21]); + rkey[122] = rotlConstant<6>(rkey[116] + delta[0][22]); + rkey[128] = rotlConstant<6>(rkey[122] + delta[1][23]); + rkey[134] = rotlConstant<6>(rkey[128] + delta[2][24]); + rkey[140] = rotlConstant<6>(rkey[134] + delta[3][25]); + + rkey[ 4] = rotlConstant<11>( key[ 3] + delta[0][ 3]); + rkey[ 10] = rotlConstant<11>(rkey[ 4] + delta[1][ 4]); + rkey[ 16] = rotlConstant<11>(rkey[ 10] + delta[2][ 5]); + rkey[ 22] = rotlConstant<11>(rkey[ 16] + delta[3][ 6]); + rkey[ 28] = rotlConstant<11>(rkey[ 22] + delta[0][ 7]); + rkey[ 34] = rotlConstant<11>(rkey[ 28] + delta[1][ 8]); + rkey[ 40] = rotlConstant<11>(rkey[ 34] + delta[2][ 9]); + rkey[ 46] = rotlConstant<11>(rkey[ 40] + delta[3][10]); + rkey[ 52] = rotlConstant<11>(rkey[ 46] + delta[0][11]); + rkey[ 58] = rotlConstant<11>(rkey[ 52] + delta[1][12]); + rkey[ 64] = rotlConstant<11>(rkey[ 58] + delta[2][13]); + rkey[ 70] = rotlConstant<11>(rkey[ 64] + delta[3][14]); + rkey[ 76] = rotlConstant<11>(rkey[ 70] + delta[0][15]); + rkey[ 82] = rotlConstant<11>(rkey[ 76] + delta[1][16]); + rkey[ 88] = rotlConstant<11>(rkey[ 82] + delta[2][17]); + rkey[ 94] = rotlConstant<11>(rkey[ 88] + delta[3][18]); + rkey[100] = rotlConstant<11>(rkey[ 94] + delta[0][19]); + rkey[106] = rotlConstant<11>(rkey[100] + delta[1][20]); + rkey[112] = rotlConstant<11>(rkey[106] + delta[2][21]); + rkey[118] = rotlConstant<11>(rkey[112] + delta[3][22]); + rkey[124] = rotlConstant<11>(rkey[118] + delta[0][23]); + rkey[130] = rotlConstant<11>(rkey[124] + delta[1][24]); + rkey[136] = rotlConstant<11>(rkey[130] + delta[2][25]); + rkey[142] = rotlConstant<11>(rkey[136] + delta[3][26]); +} + +inline void SetKey192(word32 rkey[168], const word32 key[6]) +{ + rkey[ 0] = rotlConstant<1>( key[ 0] + delta[0][ 0]); + rkey[ 6] = rotlConstant<1>(rkey[ 0] + delta[1][ 1]); + rkey[ 12] = rotlConstant<1>(rkey[ 6] + delta[2][ 2]); + rkey[ 18] = rotlConstant<1>(rkey[ 12] + delta[3][ 3]); + rkey[ 24] = rotlConstant<1>(rkey[ 18] + delta[4][ 4]); + rkey[ 30] = rotlConstant<1>(rkey[ 24] + delta[5][ 5]); + rkey[ 36] = rotlConstant<1>(rkey[ 30] + delta[0][ 6]); + rkey[ 42] = rotlConstant<1>(rkey[ 36] + delta[1][ 7]); + rkey[ 48] = rotlConstant<1>(rkey[ 42] + delta[2][ 8]); + rkey[ 54] = rotlConstant<1>(rkey[ 48] + delta[3][ 9]); + rkey[ 60] = rotlConstant<1>(rkey[ 54] + delta[4][10]); + rkey[ 66] = rotlConstant<1>(rkey[ 60] + delta[5][11]); + rkey[ 72] = rotlConstant<1>(rkey[ 66] + delta[0][12]); + rkey[ 78] = rotlConstant<1>(rkey[ 72] + delta[1][13]); + rkey[ 84] = rotlConstant<1>(rkey[ 78] + delta[2][14]); + rkey[ 90] = rotlConstant<1>(rkey[ 84] + delta[3][15]); + rkey[ 96] = rotlConstant<1>(rkey[ 90] + delta[4][16]); + rkey[102] = rotlConstant<1>(rkey[ 96] + delta[5][17]); + rkey[108] = rotlConstant<1>(rkey[102] + delta[0][18]); + rkey[114] = rotlConstant<1>(rkey[108] + delta[1][19]); + rkey[120] = rotlConstant<1>(rkey[114] + delta[2][20]); + rkey[126] = rotlConstant<1>(rkey[120] + delta[3][21]); + rkey[132] = rotlConstant<1>(rkey[126] + delta[4][22]); + rkey[138] = rotlConstant<1>(rkey[132] + delta[5][23]); + rkey[144] = rotlConstant<1>(rkey[138] + delta[0][24]); + rkey[150] = rotlConstant<1>(rkey[144] + delta[1][25]); + rkey[156] = rotlConstant<1>(rkey[150] + delta[2][26]); + rkey[162] = rotlConstant<1>(rkey[156] + delta[3][27]); + + rkey[ 1] = rotlConstant<3>( key[ 1] + delta[0][ 1]); + rkey[ 7] = rotlConstant<3>(rkey[ 1] + delta[1][ 2]); + rkey[ 13] = rotlConstant<3>(rkey[ 7] + delta[2][ 3]); + rkey[ 19] = rotlConstant<3>(rkey[ 13] + delta[3][ 4]); + rkey[ 25] = rotlConstant<3>(rkey[ 19] + delta[4][ 5]); + rkey[ 31] = rotlConstant<3>(rkey[ 25] + delta[5][ 6]); + rkey[ 37] = rotlConstant<3>(rkey[ 31] + delta[0][ 7]); + rkey[ 43] = rotlConstant<3>(rkey[ 37] + delta[1][ 8]); + rkey[ 49] = rotlConstant<3>(rkey[ 43] + delta[2][ 9]); + rkey[ 55] = rotlConstant<3>(rkey[ 49] + delta[3][10]); + rkey[ 61] = rotlConstant<3>(rkey[ 55] + delta[4][11]); + rkey[ 67] = rotlConstant<3>(rkey[ 61] + delta[5][12]); + rkey[ 73] = rotlConstant<3>(rkey[ 67] + delta[0][13]); + rkey[ 79] = rotlConstant<3>(rkey[ 73] + delta[1][14]); + rkey[ 85] = rotlConstant<3>(rkey[ 79] + delta[2][15]); + rkey[ 91] = rotlConstant<3>(rkey[ 85] + delta[3][16]); + rkey[ 97] = rotlConstant<3>(rkey[ 91] + delta[4][17]); + rkey[103] = rotlConstant<3>(rkey[ 97] + delta[5][18]); + rkey[109] = rotlConstant<3>(rkey[103] + delta[0][19]); + rkey[115] = rotlConstant<3>(rkey[109] + delta[1][20]); + rkey[121] = rotlConstant<3>(rkey[115] + delta[2][21]); + rkey[127] = rotlConstant<3>(rkey[121] + delta[3][22]); + rkey[133] = rotlConstant<3>(rkey[127] + delta[4][23]); + rkey[139] = rotlConstant<3>(rkey[133] + delta[5][24]); + rkey[145] = rotlConstant<3>(rkey[139] + delta[0][25]); + rkey[151] = rotlConstant<3>(rkey[145] + delta[1][26]); + rkey[157] = rotlConstant<3>(rkey[151] + delta[2][27]); + rkey[163] = rotlConstant<3>(rkey[157] + delta[3][28]); + + rkey[ 2] = rotlConstant<6>( key[ 2] + delta[0][ 2]); + rkey[ 8] = rotlConstant<6>(rkey[ 2] + delta[1][ 3]); + rkey[ 14] = rotlConstant<6>(rkey[ 8] + delta[2][ 4]); + rkey[ 20] = rotlConstant<6>(rkey[ 14] + delta[3][ 5]); + rkey[ 26] = rotlConstant<6>(rkey[ 20] + delta[4][ 6]); + rkey[ 32] = rotlConstant<6>(rkey[ 26] + delta[5][ 7]); + rkey[ 38] = rotlConstant<6>(rkey[ 32] + delta[0][ 8]); + rkey[ 44] = rotlConstant<6>(rkey[ 38] + delta[1][ 9]); + rkey[ 50] = rotlConstant<6>(rkey[ 44] + delta[2][10]); + rkey[ 56] = rotlConstant<6>(rkey[ 50] + delta[3][11]); + rkey[ 62] = rotlConstant<6>(rkey[ 56] + delta[4][12]); + rkey[ 68] = rotlConstant<6>(rkey[ 62] + delta[5][13]); + rkey[ 74] = rotlConstant<6>(rkey[ 68] + delta[0][14]); + rkey[ 80] = rotlConstant<6>(rkey[ 74] + delta[1][15]); + rkey[ 86] = rotlConstant<6>(rkey[ 80] + delta[2][16]); + rkey[ 92] = rotlConstant<6>(rkey[ 86] + delta[3][17]); + rkey[ 98] = rotlConstant<6>(rkey[ 92] + delta[4][18]); + rkey[104] = rotlConstant<6>(rkey[ 98] + delta[5][19]); + rkey[110] = rotlConstant<6>(rkey[104] + delta[0][20]); + rkey[116] = rotlConstant<6>(rkey[110] + delta[1][21]); + rkey[122] = rotlConstant<6>(rkey[116] + delta[2][22]); + rkey[128] = rotlConstant<6>(rkey[122] + delta[3][23]); + rkey[134] = rotlConstant<6>(rkey[128] + delta[4][24]); + rkey[140] = rotlConstant<6>(rkey[134] + delta[5][25]); + rkey[146] = rotlConstant<6>(rkey[140] + delta[0][26]); + rkey[152] = rotlConstant<6>(rkey[146] + delta[1][27]); + rkey[158] = rotlConstant<6>(rkey[152] + delta[2][28]); + rkey[164] = rotlConstant<6>(rkey[158] + delta[3][29]); + + rkey[ 3] = rotlConstant<11>( key[ 3] + delta[0][ 3]); + rkey[ 9] = rotlConstant<11>(rkey[ 3] + delta[1][ 4]); + rkey[ 15] = rotlConstant<11>(rkey[ 9] + delta[2][ 5]); + rkey[ 21] = rotlConstant<11>(rkey[ 15] + delta[3][ 6]); + rkey[ 27] = rotlConstant<11>(rkey[ 21] + delta[4][ 7]); + rkey[ 33] = rotlConstant<11>(rkey[ 27] + delta[5][ 8]); + rkey[ 39] = rotlConstant<11>(rkey[ 33] + delta[0][ 9]); + rkey[ 45] = rotlConstant<11>(rkey[ 39] + delta[1][10]); + rkey[ 51] = rotlConstant<11>(rkey[ 45] + delta[2][11]); + rkey[ 57] = rotlConstant<11>(rkey[ 51] + delta[3][12]); + rkey[ 63] = rotlConstant<11>(rkey[ 57] + delta[4][13]); + rkey[ 69] = rotlConstant<11>(rkey[ 63] + delta[5][14]); + rkey[ 75] = rotlConstant<11>(rkey[ 69] + delta[0][15]); + rkey[ 81] = rotlConstant<11>(rkey[ 75] + delta[1][16]); + rkey[ 87] = rotlConstant<11>(rkey[ 81] + delta[2][17]); + rkey[ 93] = rotlConstant<11>(rkey[ 87] + delta[3][18]); + rkey[ 99] = rotlConstant<11>(rkey[ 93] + delta[4][19]); + rkey[105] = rotlConstant<11>(rkey[ 99] + delta[5][20]); + rkey[111] = rotlConstant<11>(rkey[105] + delta[0][21]); + rkey[117] = rotlConstant<11>(rkey[111] + delta[1][22]); + rkey[123] = rotlConstant<11>(rkey[117] + delta[2][23]); + rkey[129] = rotlConstant<11>(rkey[123] + delta[3][24]); + rkey[135] = rotlConstant<11>(rkey[129] + delta[4][25]); + rkey[141] = rotlConstant<11>(rkey[135] + delta[5][26]); + rkey[147] = rotlConstant<11>(rkey[141] + delta[0][27]); + rkey[153] = rotlConstant<11>(rkey[147] + delta[1][28]); + rkey[159] = rotlConstant<11>(rkey[153] + delta[2][29]); + rkey[165] = rotlConstant<11>(rkey[159] + delta[3][30]); + + rkey[ 4] = rotlConstant<13>( key[ 4] + delta[0][ 4]); + rkey[ 10] = rotlConstant<13>(rkey[ 4] + delta[1][ 5]); + rkey[ 16] = rotlConstant<13>(rkey[ 10] + delta[2][ 6]); + rkey[ 22] = rotlConstant<13>(rkey[ 16] + delta[3][ 7]); + rkey[ 28] = rotlConstant<13>(rkey[ 22] + delta[4][ 8]); + rkey[ 34] = rotlConstant<13>(rkey[ 28] + delta[5][ 9]); + rkey[ 40] = rotlConstant<13>(rkey[ 34] + delta[0][10]); + rkey[ 46] = rotlConstant<13>(rkey[ 40] + delta[1][11]); + rkey[ 52] = rotlConstant<13>(rkey[ 46] + delta[2][12]); + rkey[ 58] = rotlConstant<13>(rkey[ 52] + delta[3][13]); + rkey[ 64] = rotlConstant<13>(rkey[ 58] + delta[4][14]); + rkey[ 70] = rotlConstant<13>(rkey[ 64] + delta[5][15]); + rkey[ 76] = rotlConstant<13>(rkey[ 70] + delta[0][16]); + rkey[ 82] = rotlConstant<13>(rkey[ 76] + delta[1][17]); + rkey[ 88] = rotlConstant<13>(rkey[ 82] + delta[2][18]); + rkey[ 94] = rotlConstant<13>(rkey[ 88] + delta[3][19]); + rkey[100] = rotlConstant<13>(rkey[ 94] + delta[4][20]); + rkey[106] = rotlConstant<13>(rkey[100] + delta[5][21]); + rkey[112] = rotlConstant<13>(rkey[106] + delta[0][22]); + rkey[118] = rotlConstant<13>(rkey[112] + delta[1][23]); + rkey[124] = rotlConstant<13>(rkey[118] + delta[2][24]); + rkey[130] = rotlConstant<13>(rkey[124] + delta[3][25]); + rkey[136] = rotlConstant<13>(rkey[130] + delta[4][26]); + rkey[142] = rotlConstant<13>(rkey[136] + delta[5][27]); + rkey[148] = rotlConstant<13>(rkey[142] + delta[0][28]); + rkey[154] = rotlConstant<13>(rkey[148] + delta[1][29]); + rkey[160] = rotlConstant<13>(rkey[154] + delta[2][30]); + rkey[166] = rotlConstant<13>(rkey[160] + delta[3][31]); + + rkey[ 5] = rotlConstant<17>( key[ 5] + delta[0][ 5]); + rkey[ 11] = rotlConstant<17>(rkey[ 5] + delta[1][ 6]); + rkey[ 17] = rotlConstant<17>(rkey[ 11] + delta[2][ 7]); + rkey[ 23] = rotlConstant<17>(rkey[ 17] + delta[3][ 8]); + rkey[ 29] = rotlConstant<17>(rkey[ 23] + delta[4][ 9]); + rkey[ 35] = rotlConstant<17>(rkey[ 29] + delta[5][10]); + rkey[ 41] = rotlConstant<17>(rkey[ 35] + delta[0][11]); + rkey[ 47] = rotlConstant<17>(rkey[ 41] + delta[1][12]); + rkey[ 53] = rotlConstant<17>(rkey[ 47] + delta[2][13]); + rkey[ 59] = rotlConstant<17>(rkey[ 53] + delta[3][14]); + rkey[ 65] = rotlConstant<17>(rkey[ 59] + delta[4][15]); + rkey[ 71] = rotlConstant<17>(rkey[ 65] + delta[5][16]); + rkey[ 77] = rotlConstant<17>(rkey[ 71] + delta[0][17]); + rkey[ 83] = rotlConstant<17>(rkey[ 77] + delta[1][18]); + rkey[ 89] = rotlConstant<17>(rkey[ 83] + delta[2][19]); + rkey[ 95] = rotlConstant<17>(rkey[ 89] + delta[3][20]); + rkey[101] = rotlConstant<17>(rkey[ 95] + delta[4][21]); + rkey[107] = rotlConstant<17>(rkey[101] + delta[5][22]); + rkey[113] = rotlConstant<17>(rkey[107] + delta[0][23]); + rkey[119] = rotlConstant<17>(rkey[113] + delta[1][24]); + rkey[125] = rotlConstant<17>(rkey[119] + delta[2][25]); + rkey[131] = rotlConstant<17>(rkey[125] + delta[3][26]); + rkey[137] = rotlConstant<17>(rkey[131] + delta[4][27]); + rkey[143] = rotlConstant<17>(rkey[137] + delta[5][28]); + rkey[149] = rotlConstant<17>(rkey[143] + delta[0][29]); + rkey[155] = rotlConstant<17>(rkey[149] + delta[1][30]); + rkey[161] = rotlConstant<17>(rkey[155] + delta[2][31]); + rkey[167] = rotlConstant<17>(rkey[161] + delta[3][ 0]); +} + +inline void SetKey256(word32 rkey[192], const word32 key[8]) +{ + rkey[ 0] = rotlConstant< 1>( key[ 0] + delta[0][ 0]); + rkey[ 8] = rotlConstant< 6>(rkey[ 0] + delta[1][ 3]); + rkey[ 16] = rotlConstant<13>(rkey[ 8] + delta[2][ 6]); + rkey[ 24] = rotlConstant< 1>(rkey[ 16] + delta[4][ 4]); + rkey[ 32] = rotlConstant< 6>(rkey[ 24] + delta[5][ 7]); + rkey[ 40] = rotlConstant<13>(rkey[ 32] + delta[6][10]); + rkey[ 48] = rotlConstant< 1>(rkey[ 40] + delta[0][ 8]); + rkey[ 56] = rotlConstant< 6>(rkey[ 48] + delta[1][11]); + rkey[ 64] = rotlConstant<13>(rkey[ 56] + delta[2][14]); + rkey[ 72] = rotlConstant< 1>(rkey[ 64] + delta[4][12]); + rkey[ 80] = rotlConstant< 6>(rkey[ 72] + delta[5][15]); + rkey[ 88] = rotlConstant<13>(rkey[ 80] + delta[6][18]); + rkey[ 96] = rotlConstant< 1>(rkey[ 88] + delta[0][16]); + rkey[104] = rotlConstant< 6>(rkey[ 96] + delta[1][19]); + rkey[112] = rotlConstant<13>(rkey[104] + delta[2][22]); + rkey[120] = rotlConstant< 1>(rkey[112] + delta[4][20]); + rkey[128] = rotlConstant< 6>(rkey[120] + delta[5][23]); + rkey[136] = rotlConstant<13>(rkey[128] + delta[6][26]); + rkey[144] = rotlConstant< 1>(rkey[136] + delta[0][24]); + rkey[152] = rotlConstant< 6>(rkey[144] + delta[1][27]); + rkey[160] = rotlConstant<13>(rkey[152] + delta[2][30]); + rkey[168] = rotlConstant< 1>(rkey[160] + delta[4][28]); + rkey[176] = rotlConstant< 6>(rkey[168] + delta[5][31]); + rkey[184] = rotlConstant<13>(rkey[176] + delta[6][ 2]); + + rkey[ 1] = rotlConstant< 3>( key[ 1] + delta[0][ 1]); + rkey[ 9] = rotlConstant<11>(rkey[ 1] + delta[1][ 4]); + rkey[ 17] = rotlConstant<17>(rkey[ 9] + delta[2][ 7]); + rkey[ 25] = rotlConstant< 3>(rkey[ 17] + delta[4][ 5]); + rkey[ 33] = rotlConstant<11>(rkey[ 25] + delta[5][ 8]); + rkey[ 41] = rotlConstant<17>(rkey[ 33] + delta[6][11]); + rkey[ 49] = rotlConstant< 3>(rkey[ 41] + delta[0][ 9]); + rkey[ 57] = rotlConstant<11>(rkey[ 49] + delta[1][12]); + rkey[ 65] = rotlConstant<17>(rkey[ 57] + delta[2][15]); + rkey[ 73] = rotlConstant< 3>(rkey[ 65] + delta[4][13]); + rkey[ 81] = rotlConstant<11>(rkey[ 73] + delta[5][16]); + rkey[ 89] = rotlConstant<17>(rkey[ 81] + delta[6][19]); + rkey[ 97] = rotlConstant< 3>(rkey[ 89] + delta[0][17]); + rkey[105] = rotlConstant<11>(rkey[ 97] + delta[1][20]); + rkey[113] = rotlConstant<17>(rkey[105] + delta[2][23]); + rkey[121] = rotlConstant< 3>(rkey[113] + delta[4][21]); + rkey[129] = rotlConstant<11>(rkey[121] + delta[5][24]); + rkey[137] = rotlConstant<17>(rkey[129] + delta[6][27]); + rkey[145] = rotlConstant< 3>(rkey[137] + delta[0][25]); + rkey[153] = rotlConstant<11>(rkey[145] + delta[1][28]); + rkey[161] = rotlConstant<17>(rkey[153] + delta[2][31]); + rkey[169] = rotlConstant< 3>(rkey[161] + delta[4][29]); + rkey[177] = rotlConstant<11>(rkey[169] + delta[5][ 0]); + rkey[185] = rotlConstant<17>(rkey[177] + delta[6][ 3]); + + rkey[ 2] = rotlConstant< 6>( key[ 2] + delta[0][ 2]); + rkey[ 10] = rotlConstant<13>(rkey[ 2] + delta[1][ 5]); + rkey[ 18] = rotlConstant< 1>(rkey[ 10] + delta[3][ 3]); + rkey[ 26] = rotlConstant< 6>(rkey[ 18] + delta[4][ 6]); + rkey[ 34] = rotlConstant<13>(rkey[ 26] + delta[5][ 9]); + rkey[ 42] = rotlConstant< 1>(rkey[ 34] + delta[7][ 7]); + rkey[ 50] = rotlConstant< 6>(rkey[ 42] + delta[0][10]); + rkey[ 58] = rotlConstant<13>(rkey[ 50] + delta[1][13]); + rkey[ 66] = rotlConstant< 1>(rkey[ 58] + delta[3][11]); + rkey[ 74] = rotlConstant< 6>(rkey[ 66] + delta[4][14]); + rkey[ 82] = rotlConstant<13>(rkey[ 74] + delta[5][17]); + rkey[ 90] = rotlConstant< 1>(rkey[ 82] + delta[7][15]); + rkey[ 98] = rotlConstant< 6>(rkey[ 90] + delta[0][18]); + rkey[106] = rotlConstant<13>(rkey[ 98] + delta[1][21]); + rkey[114] = rotlConstant< 1>(rkey[106] + delta[3][19]); + rkey[122] = rotlConstant< 6>(rkey[114] + delta[4][22]); + rkey[130] = rotlConstant<13>(rkey[122] + delta[5][25]); + rkey[138] = rotlConstant< 1>(rkey[130] + delta[7][23]); + rkey[146] = rotlConstant< 6>(rkey[138] + delta[0][26]); + rkey[154] = rotlConstant<13>(rkey[146] + delta[1][29]); + rkey[162] = rotlConstant< 1>(rkey[154] + delta[3][27]); + rkey[170] = rotlConstant< 6>(rkey[162] + delta[4][30]); + rkey[178] = rotlConstant<13>(rkey[170] + delta[5][ 1]); + rkey[186] = rotlConstant< 1>(rkey[178] + delta[7][31]); + + rkey[ 3] = rotlConstant<11>( key[ 3] + delta[0][ 3]); + rkey[ 11] = rotlConstant<17>(rkey[ 3] + delta[1][ 6]); + rkey[ 19] = rotlConstant< 3>(rkey[ 11] + delta[3][ 4]); + rkey[ 27] = rotlConstant<11>(rkey[ 19] + delta[4][ 7]); + rkey[ 35] = rotlConstant<17>(rkey[ 27] + delta[5][10]); + rkey[ 43] = rotlConstant< 3>(rkey[ 35] + delta[7][ 8]); + rkey[ 51] = rotlConstant<11>(rkey[ 43] + delta[0][11]); + rkey[ 59] = rotlConstant<17>(rkey[ 51] + delta[1][14]); + rkey[ 67] = rotlConstant< 3>(rkey[ 59] + delta[3][12]); + rkey[ 75] = rotlConstant<11>(rkey[ 67] + delta[4][15]); + rkey[ 83] = rotlConstant<17>(rkey[ 75] + delta[5][18]); + rkey[ 91] = rotlConstant< 3>(rkey[ 83] + delta[7][16]); + rkey[ 99] = rotlConstant<11>(rkey[ 91] + delta[0][19]); + rkey[107] = rotlConstant<17>(rkey[ 99] + delta[1][22]); + rkey[115] = rotlConstant< 3>(rkey[107] + delta[3][20]); + rkey[123] = rotlConstant<11>(rkey[115] + delta[4][23]); + rkey[131] = rotlConstant<17>(rkey[123] + delta[5][26]); + rkey[139] = rotlConstant< 3>(rkey[131] + delta[7][24]); + rkey[147] = rotlConstant<11>(rkey[139] + delta[0][27]); + rkey[155] = rotlConstant<17>(rkey[147] + delta[1][30]); + rkey[163] = rotlConstant< 3>(rkey[155] + delta[3][28]); + rkey[171] = rotlConstant<11>(rkey[163] + delta[4][31]); + rkey[179] = rotlConstant<17>(rkey[171] + delta[5][ 2]); + rkey[187] = rotlConstant< 3>(rkey[179] + delta[7][ 0]); + + rkey[ 4] = rotlConstant<13>( key[ 4] + delta[0][ 4]); + rkey[ 12] = rotlConstant< 1>(rkey[ 4] + delta[2][ 2]); + rkey[ 20] = rotlConstant< 6>(rkey[ 12] + delta[3][ 5]); + rkey[ 28] = rotlConstant<13>(rkey[ 20] + delta[4][ 8]); + rkey[ 36] = rotlConstant< 1>(rkey[ 28] + delta[6][ 6]); + rkey[ 44] = rotlConstant< 6>(rkey[ 36] + delta[7][ 9]); + rkey[ 52] = rotlConstant<13>(rkey[ 44] + delta[0][12]); + rkey[ 60] = rotlConstant< 1>(rkey[ 52] + delta[2][10]); + rkey[ 68] = rotlConstant< 6>(rkey[ 60] + delta[3][13]); + rkey[ 76] = rotlConstant<13>(rkey[ 68] + delta[4][16]); + rkey[ 84] = rotlConstant< 1>(rkey[ 76] + delta[6][14]); + rkey[ 92] = rotlConstant< 6>(rkey[ 84] + delta[7][17]); + rkey[100] = rotlConstant<13>(rkey[ 92] + delta[0][20]); + rkey[108] = rotlConstant< 1>(rkey[100] + delta[2][18]); + rkey[116] = rotlConstant< 6>(rkey[108] + delta[3][21]); + rkey[124] = rotlConstant<13>(rkey[116] + delta[4][24]); + rkey[132] = rotlConstant< 1>(rkey[124] + delta[6][22]); + rkey[140] = rotlConstant< 6>(rkey[132] + delta[7][25]); + rkey[148] = rotlConstant<13>(rkey[140] + delta[0][28]); + rkey[156] = rotlConstant< 1>(rkey[148] + delta[2][26]); + rkey[164] = rotlConstant< 6>(rkey[156] + delta[3][29]); + rkey[172] = rotlConstant<13>(rkey[164] + delta[4][ 0]); + rkey[180] = rotlConstant< 1>(rkey[172] + delta[6][30]); + rkey[188] = rotlConstant< 6>(rkey[180] + delta[7][ 1]); + + rkey[ 5] = rotlConstant<17>( key[ 5] + delta[0][ 5]); + rkey[ 13] = rotlConstant< 3>(rkey[ 5] + delta[2][ 3]); + rkey[ 21] = rotlConstant<11>(rkey[ 13] + delta[3][ 6]); + rkey[ 29] = rotlConstant<17>(rkey[ 21] + delta[4][ 9]); + rkey[ 37] = rotlConstant< 3>(rkey[ 29] + delta[6][ 7]); + rkey[ 45] = rotlConstant<11>(rkey[ 37] + delta[7][10]); + rkey[ 53] = rotlConstant<17>(rkey[ 45] + delta[0][13]); + rkey[ 61] = rotlConstant< 3>(rkey[ 53] + delta[2][11]); + rkey[ 69] = rotlConstant<11>(rkey[ 61] + delta[3][14]); + rkey[ 77] = rotlConstant<17>(rkey[ 69] + delta[4][17]); + rkey[ 85] = rotlConstant< 3>(rkey[ 77] + delta[6][15]); + rkey[ 93] = rotlConstant<11>(rkey[ 85] + delta[7][18]); + rkey[101] = rotlConstant<17>(rkey[ 93] + delta[0][21]); + rkey[109] = rotlConstant< 3>(rkey[101] + delta[2][19]); + rkey[117] = rotlConstant<11>(rkey[109] + delta[3][22]); + rkey[125] = rotlConstant<17>(rkey[117] + delta[4][25]); + rkey[133] = rotlConstant< 3>(rkey[125] + delta[6][23]); + rkey[141] = rotlConstant<11>(rkey[133] + delta[7][26]); + rkey[149] = rotlConstant<17>(rkey[141] + delta[0][29]); + rkey[157] = rotlConstant< 3>(rkey[149] + delta[2][27]); + rkey[165] = rotlConstant<11>(rkey[157] + delta[3][30]); + rkey[173] = rotlConstant<17>(rkey[165] + delta[4][ 1]); + rkey[181] = rotlConstant< 3>(rkey[173] + delta[6][31]); + rkey[189] = rotlConstant<11>(rkey[181] + delta[7][ 2]); + + rkey[ 6] = rotlConstant< 1>( key[ 6] + delta[1][ 1]); + rkey[ 14] = rotlConstant< 6>(rkey[ 6] + delta[2][ 4]); + rkey[ 22] = rotlConstant<13>(rkey[ 14] + delta[3][ 7]); + rkey[ 30] = rotlConstant< 1>(rkey[ 22] + delta[5][ 5]); + rkey[ 38] = rotlConstant< 6>(rkey[ 30] + delta[6][ 8]); + rkey[ 46] = rotlConstant<13>(rkey[ 38] + delta[7][11]); + rkey[ 54] = rotlConstant< 1>(rkey[ 46] + delta[1][ 9]); + rkey[ 62] = rotlConstant< 6>(rkey[ 54] + delta[2][12]); + rkey[ 70] = rotlConstant<13>(rkey[ 62] + delta[3][15]); + rkey[ 78] = rotlConstant< 1>(rkey[ 70] + delta[5][13]); + rkey[ 86] = rotlConstant< 6>(rkey[ 78] + delta[6][16]); + rkey[ 94] = rotlConstant<13>(rkey[ 86] + delta[7][19]); + rkey[102] = rotlConstant< 1>(rkey[ 94] + delta[1][17]); + rkey[110] = rotlConstant< 6>(rkey[102] + delta[2][20]); + rkey[118] = rotlConstant<13>(rkey[110] + delta[3][23]); + rkey[126] = rotlConstant< 1>(rkey[118] + delta[5][21]); + rkey[134] = rotlConstant< 6>(rkey[126] + delta[6][24]); + rkey[142] = rotlConstant<13>(rkey[134] + delta[7][27]); + rkey[150] = rotlConstant< 1>(rkey[142] + delta[1][25]); + rkey[158] = rotlConstant< 6>(rkey[150] + delta[2][28]); + rkey[166] = rotlConstant<13>(rkey[158] + delta[3][31]); + rkey[174] = rotlConstant< 1>(rkey[166] + delta[5][29]); + rkey[182] = rotlConstant< 6>(rkey[174] + delta[6][ 0]); + rkey[190] = rotlConstant<13>(rkey[182] + delta[7][ 3]); + + rkey[ 7] = rotlConstant< 3>( key[ 7] + delta[1][ 2]); + rkey[ 15] = rotlConstant<11>(rkey[ 7] + delta[2][ 5]); + rkey[ 23] = rotlConstant<17>(rkey[ 15] + delta[3][ 8]); + rkey[ 31] = rotlConstant< 3>(rkey[ 23] + delta[5][ 6]); + rkey[ 39] = rotlConstant<11>(rkey[ 31] + delta[6][ 9]); + rkey[ 47] = rotlConstant<17>(rkey[ 39] + delta[7][12]); + rkey[ 55] = rotlConstant< 3>(rkey[ 47] + delta[1][10]); + rkey[ 63] = rotlConstant<11>(rkey[ 55] + delta[2][13]); + rkey[ 71] = rotlConstant<17>(rkey[ 63] + delta[3][16]); + rkey[ 79] = rotlConstant< 3>(rkey[ 71] + delta[5][14]); + rkey[ 87] = rotlConstant<11>(rkey[ 79] + delta[6][17]); + rkey[ 95] = rotlConstant<17>(rkey[ 87] + delta[7][20]); + rkey[103] = rotlConstant< 3>(rkey[ 95] + delta[1][18]); + rkey[111] = rotlConstant<11>(rkey[103] + delta[2][21]); + rkey[119] = rotlConstant<17>(rkey[111] + delta[3][24]); + rkey[127] = rotlConstant< 3>(rkey[119] + delta[5][22]); + rkey[135] = rotlConstant<11>(rkey[127] + delta[6][25]); + rkey[143] = rotlConstant<17>(rkey[135] + delta[7][28]); + rkey[151] = rotlConstant< 3>(rkey[143] + delta[1][26]); + rkey[159] = rotlConstant<11>(rkey[151] + delta[2][29]); + rkey[167] = rotlConstant<17>(rkey[159] + delta[3][ 0]); + rkey[175] = rotlConstant< 3>(rkey[167] + delta[5][30]); + rkey[183] = rotlConstant<11>(rkey[175] + delta[6][ 1]); + rkey[191] = rotlConstant<17>(rkey[183] + delta[7][ 4]); +} + +NAMESPACE_BEGIN(CryptoPP) + +#if CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS +# if defined(CRYPTOPP_SSSE3_AVAILABLE) +extern size_t LEA_Enc_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t LEA_Dec_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +# endif + +# if (CRYPTOPP_ARM_NEON_AVAILABLE) +extern size_t LEA_Enc_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t LEA_Dec_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +# endif +#endif + +std::string LEA::Base::AlgorithmProvider() const +{ +#if (CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS) +# if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return "SSSE3"; +# endif +# if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return "NEON"; +# endif +#endif + return "C++"; +} + +void LEA::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + + switch(keyLength) + { + case 16: // 128-bit key + { + m_rkey.New(144); m_temp.New(4); m_rounds = 24; + GetUserKey(LITTLE_ENDIAN_ORDER, m_temp.begin(), 4, userKey, 16); + SetKey128(m_rkey, m_temp); + break; + } + case 24: // 192-bit key + { + m_rkey.New(168); m_temp.New(6); m_rounds = 28; + GetUserKey(LITTLE_ENDIAN_ORDER, m_temp.begin(), 6, userKey, 24); + SetKey192(m_rkey, m_temp); + break; + } + case 32: // 256-bit key + { + m_rkey.New(192); m_temp.New(8); m_rounds = 32; + GetUserKey(LITTLE_ENDIAN_ORDER, m_temp.begin(), 8, userKey, 32); + SetKey256(m_rkey, m_temp); + break; + } + default: + CRYPTOPP_ASSERT(0); + } +} + +void LEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_temp[0])(m_temp[1])(m_temp[2])(m_temp[3]); + + m_temp[3] = rotrConstant<3>((m_temp[2] ^ m_rkey[ 4]) + (m_temp[3] ^ m_rkey[ 5])); + m_temp[2] = rotrConstant<5>((m_temp[1] ^ m_rkey[ 2]) + (m_temp[2] ^ m_rkey[ 3])); + m_temp[1] = rotlConstant<9>((m_temp[0] ^ m_rkey[ 0]) + (m_temp[1] ^ m_rkey[ 1])); + m_temp[0] = rotrConstant<3>((m_temp[3] ^ m_rkey[ 10]) + (m_temp[0] ^ m_rkey[ 11])); + m_temp[3] = rotrConstant<5>((m_temp[2] ^ m_rkey[ 8]) + (m_temp[3] ^ m_rkey[ 9])); + m_temp[2] = rotlConstant<9>((m_temp[1] ^ m_rkey[ 6]) + (m_temp[2] ^ m_rkey[ 7])); + m_temp[1] = rotrConstant<3>((m_temp[0] ^ m_rkey[ 16]) + (m_temp[1] ^ m_rkey[ 17])); + m_temp[0] = rotrConstant<5>((m_temp[3] ^ m_rkey[ 14]) + (m_temp[0] ^ m_rkey[ 15])); + m_temp[3] = rotlConstant<9>((m_temp[2] ^ m_rkey[ 12]) + (m_temp[3] ^ m_rkey[ 13])); + m_temp[2] = rotrConstant<3>((m_temp[1] ^ m_rkey[ 22]) + (m_temp[2] ^ m_rkey[ 23])); + m_temp[1] = rotrConstant<5>((m_temp[0] ^ m_rkey[ 20]) + (m_temp[1] ^ m_rkey[ 21])); + m_temp[0] = rotlConstant<9>((m_temp[3] ^ m_rkey[ 18]) + (m_temp[0] ^ m_rkey[ 19])); + + m_temp[3] = rotrConstant<3>((m_temp[2] ^ m_rkey[ 28]) + (m_temp[3] ^ m_rkey[ 29])); + m_temp[2] = rotrConstant<5>((m_temp[1] ^ m_rkey[ 26]) + (m_temp[2] ^ m_rkey[ 27])); + m_temp[1] = rotlConstant<9>((m_temp[0] ^ m_rkey[ 24]) + (m_temp[1] ^ m_rkey[ 25])); + m_temp[0] = rotrConstant<3>((m_temp[3] ^ m_rkey[ 34]) + (m_temp[0] ^ m_rkey[ 35])); + m_temp[3] = rotrConstant<5>((m_temp[2] ^ m_rkey[ 32]) + (m_temp[3] ^ m_rkey[ 33])); + m_temp[2] = rotlConstant<9>((m_temp[1] ^ m_rkey[ 30]) + (m_temp[2] ^ m_rkey[ 31])); + m_temp[1] = rotrConstant<3>((m_temp[0] ^ m_rkey[ 40]) + (m_temp[1] ^ m_rkey[ 41])); + m_temp[0] = rotrConstant<5>((m_temp[3] ^ m_rkey[ 38]) + (m_temp[0] ^ m_rkey[ 39])); + m_temp[3] = rotlConstant<9>((m_temp[2] ^ m_rkey[ 36]) + (m_temp[3] ^ m_rkey[ 37])); + m_temp[2] = rotrConstant<3>((m_temp[1] ^ m_rkey[ 46]) + (m_temp[2] ^ m_rkey[ 47])); + m_temp[1] = rotrConstant<5>((m_temp[0] ^ m_rkey[ 44]) + (m_temp[1] ^ m_rkey[ 45])); + m_temp[0] = rotlConstant<9>((m_temp[3] ^ m_rkey[ 42]) + (m_temp[0] ^ m_rkey[ 43])); + + m_temp[3] = rotrConstant<3>((m_temp[2] ^ m_rkey[ 52]) + (m_temp[3] ^ m_rkey[ 53])); + m_temp[2] = rotrConstant<5>((m_temp[1] ^ m_rkey[ 50]) + (m_temp[2] ^ m_rkey[ 51])); + m_temp[1] = rotlConstant<9>((m_temp[0] ^ m_rkey[ 48]) + (m_temp[1] ^ m_rkey[ 49])); + m_temp[0] = rotrConstant<3>((m_temp[3] ^ m_rkey[ 58]) + (m_temp[0] ^ m_rkey[ 59])); + m_temp[3] = rotrConstant<5>((m_temp[2] ^ m_rkey[ 56]) + (m_temp[3] ^ m_rkey[ 57])); + m_temp[2] = rotlConstant<9>((m_temp[1] ^ m_rkey[ 54]) + (m_temp[2] ^ m_rkey[ 55])); + m_temp[1] = rotrConstant<3>((m_temp[0] ^ m_rkey[ 64]) + (m_temp[1] ^ m_rkey[ 65])); + m_temp[0] = rotrConstant<5>((m_temp[3] ^ m_rkey[ 62]) + (m_temp[0] ^ m_rkey[ 63])); + m_temp[3] = rotlConstant<9>((m_temp[2] ^ m_rkey[ 60]) + (m_temp[3] ^ m_rkey[ 61])); + m_temp[2] = rotrConstant<3>((m_temp[1] ^ m_rkey[ 70]) + (m_temp[2] ^ m_rkey[ 71])); + m_temp[1] = rotrConstant<5>((m_temp[0] ^ m_rkey[ 68]) + (m_temp[1] ^ m_rkey[ 69])); + m_temp[0] = rotlConstant<9>((m_temp[3] ^ m_rkey[ 66]) + (m_temp[0] ^ m_rkey[ 67])); + + m_temp[3] = rotrConstant<3>((m_temp[2] ^ m_rkey[ 76]) + (m_temp[3] ^ m_rkey[ 77])); + m_temp[2] = rotrConstant<5>((m_temp[1] ^ m_rkey[ 74]) + (m_temp[2] ^ m_rkey[ 75])); + m_temp[1] = rotlConstant<9>((m_temp[0] ^ m_rkey[ 72]) + (m_temp[1] ^ m_rkey[ 73])); + m_temp[0] = rotrConstant<3>((m_temp[3] ^ m_rkey[ 82]) + (m_temp[0] ^ m_rkey[ 83])); + m_temp[3] = rotrConstant<5>((m_temp[2] ^ m_rkey[ 80]) + (m_temp[3] ^ m_rkey[ 81])); + m_temp[2] = rotlConstant<9>((m_temp[1] ^ m_rkey[ 78]) + (m_temp[2] ^ m_rkey[ 79])); + m_temp[1] = rotrConstant<3>((m_temp[0] ^ m_rkey[ 88]) + (m_temp[1] ^ m_rkey[ 89])); + m_temp[0] = rotrConstant<5>((m_temp[3] ^ m_rkey[ 86]) + (m_temp[0] ^ m_rkey[ 87])); + m_temp[3] = rotlConstant<9>((m_temp[2] ^ m_rkey[ 84]) + (m_temp[3] ^ m_rkey[ 85])); + m_temp[2] = rotrConstant<3>((m_temp[1] ^ m_rkey[ 94]) + (m_temp[2] ^ m_rkey[ 95])); + m_temp[1] = rotrConstant<5>((m_temp[0] ^ m_rkey[ 92]) + (m_temp[1] ^ m_rkey[ 93])); + m_temp[0] = rotlConstant<9>((m_temp[3] ^ m_rkey[ 90]) + (m_temp[0] ^ m_rkey[ 91])); + + m_temp[3] = rotrConstant<3>((m_temp[2] ^ m_rkey[100]) + (m_temp[3] ^ m_rkey[101])); + m_temp[2] = rotrConstant<5>((m_temp[1] ^ m_rkey[ 98]) + (m_temp[2] ^ m_rkey[ 99])); + m_temp[1] = rotlConstant<9>((m_temp[0] ^ m_rkey[ 96]) + (m_temp[1] ^ m_rkey[ 97])); + m_temp[0] = rotrConstant<3>((m_temp[3] ^ m_rkey[106]) + (m_temp[0] ^ m_rkey[107])); + m_temp[3] = rotrConstant<5>((m_temp[2] ^ m_rkey[104]) + (m_temp[3] ^ m_rkey[105])); + m_temp[2] = rotlConstant<9>((m_temp[1] ^ m_rkey[102]) + (m_temp[2] ^ m_rkey[103])); + m_temp[1] = rotrConstant<3>((m_temp[0] ^ m_rkey[112]) + (m_temp[1] ^ m_rkey[113])); + m_temp[0] = rotrConstant<5>((m_temp[3] ^ m_rkey[110]) + (m_temp[0] ^ m_rkey[111])); + m_temp[3] = rotlConstant<9>((m_temp[2] ^ m_rkey[108]) + (m_temp[3] ^ m_rkey[109])); + m_temp[2] = rotrConstant<3>((m_temp[1] ^ m_rkey[118]) + (m_temp[2] ^ m_rkey[119])); + m_temp[1] = rotrConstant<5>((m_temp[0] ^ m_rkey[116]) + (m_temp[1] ^ m_rkey[117])); + m_temp[0] = rotlConstant<9>((m_temp[3] ^ m_rkey[114]) + (m_temp[0] ^ m_rkey[115])); + + m_temp[3] = rotrConstant<3>((m_temp[2] ^ m_rkey[124]) + (m_temp[3] ^ m_rkey[125])); + m_temp[2] = rotrConstant<5>((m_temp[1] ^ m_rkey[122]) + (m_temp[2] ^ m_rkey[123])); + m_temp[1] = rotlConstant<9>((m_temp[0] ^ m_rkey[120]) + (m_temp[1] ^ m_rkey[121])); + m_temp[0] = rotrConstant<3>((m_temp[3] ^ m_rkey[130]) + (m_temp[0] ^ m_rkey[131])); + m_temp[3] = rotrConstant<5>((m_temp[2] ^ m_rkey[128]) + (m_temp[3] ^ m_rkey[129])); + m_temp[2] = rotlConstant<9>((m_temp[1] ^ m_rkey[126]) + (m_temp[2] ^ m_rkey[127])); + m_temp[1] = rotrConstant<3>((m_temp[0] ^ m_rkey[136]) + (m_temp[1] ^ m_rkey[137])); + m_temp[0] = rotrConstant<5>((m_temp[3] ^ m_rkey[134]) + (m_temp[0] ^ m_rkey[135])); + m_temp[3] = rotlConstant<9>((m_temp[2] ^ m_rkey[132]) + (m_temp[3] ^ m_rkey[133])); + m_temp[2] = rotrConstant<3>((m_temp[1] ^ m_rkey[142]) + (m_temp[2] ^ m_rkey[143])); + m_temp[1] = rotrConstant<5>((m_temp[0] ^ m_rkey[140]) + (m_temp[1] ^ m_rkey[141])); + m_temp[0] = rotlConstant<9>((m_temp[3] ^ m_rkey[138]) + (m_temp[0] ^ m_rkey[139])); + + if(m_rounds > 24) + { + m_temp[3] = rotrConstant<3>((m_temp[2] ^ m_rkey[148]) + (m_temp[3] ^ m_rkey[149])); + m_temp[2] = rotrConstant<5>((m_temp[1] ^ m_rkey[146]) + (m_temp[2] ^ m_rkey[147])); + m_temp[1] = rotlConstant<9>((m_temp[0] ^ m_rkey[144]) + (m_temp[1] ^ m_rkey[145])); + m_temp[0] = rotrConstant<3>((m_temp[3] ^ m_rkey[154]) + (m_temp[0] ^ m_rkey[155])); + m_temp[3] = rotrConstant<5>((m_temp[2] ^ m_rkey[152]) + (m_temp[3] ^ m_rkey[153])); + m_temp[2] = rotlConstant<9>((m_temp[1] ^ m_rkey[150]) + (m_temp[2] ^ m_rkey[151])); + m_temp[1] = rotrConstant<3>((m_temp[0] ^ m_rkey[160]) + (m_temp[1] ^ m_rkey[161])); + m_temp[0] = rotrConstant<5>((m_temp[3] ^ m_rkey[158]) + (m_temp[0] ^ m_rkey[159])); + m_temp[3] = rotlConstant<9>((m_temp[2] ^ m_rkey[156]) + (m_temp[3] ^ m_rkey[157])); + m_temp[2] = rotrConstant<3>((m_temp[1] ^ m_rkey[166]) + (m_temp[2] ^ m_rkey[167])); + m_temp[1] = rotrConstant<5>((m_temp[0] ^ m_rkey[164]) + (m_temp[1] ^ m_rkey[165])); + m_temp[0] = rotlConstant<9>((m_temp[3] ^ m_rkey[162]) + (m_temp[0] ^ m_rkey[163])); + } + + if(m_rounds > 28) + { + m_temp[3] = rotrConstant<3>((m_temp[2] ^ m_rkey[172]) + (m_temp[3] ^ m_rkey[173])); + m_temp[2] = rotrConstant<5>((m_temp[1] ^ m_rkey[170]) + (m_temp[2] ^ m_rkey[171])); + m_temp[1] = rotlConstant<9>((m_temp[0] ^ m_rkey[168]) + (m_temp[1] ^ m_rkey[169])); + m_temp[0] = rotrConstant<3>((m_temp[3] ^ m_rkey[178]) + (m_temp[0] ^ m_rkey[179])); + m_temp[3] = rotrConstant<5>((m_temp[2] ^ m_rkey[176]) + (m_temp[3] ^ m_rkey[177])); + m_temp[2] = rotlConstant<9>((m_temp[1] ^ m_rkey[174]) + (m_temp[2] ^ m_rkey[175])); + m_temp[1] = rotrConstant<3>((m_temp[0] ^ m_rkey[184]) + (m_temp[1] ^ m_rkey[185])); + m_temp[0] = rotrConstant<5>((m_temp[3] ^ m_rkey[182]) + (m_temp[0] ^ m_rkey[183])); + m_temp[3] = rotlConstant<9>((m_temp[2] ^ m_rkey[180]) + (m_temp[3] ^ m_rkey[181])); + m_temp[2] = rotrConstant<3>((m_temp[1] ^ m_rkey[190]) + (m_temp[2] ^ m_rkey[191])); + m_temp[1] = rotrConstant<5>((m_temp[0] ^ m_rkey[188]) + (m_temp[1] ^ m_rkey[189])); + m_temp[0] = rotlConstant<9>((m_temp[3] ^ m_rkey[186]) + (m_temp[0] ^ m_rkey[187])); + } + + PutBlock oblock(xorBlock, outBlock); + oblock(m_temp[0])(m_temp[1])(m_temp[2])(m_temp[3]); +} + +void LEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_temp[0])(m_temp[1])(m_temp[2])(m_temp[3]); + + if(m_rounds > 28) + { + m_temp[0] = (rotrConstant<9>(m_temp[0]) - (m_temp[3] ^ m_rkey[186])) ^ m_rkey[187]; + m_temp[1] = (rotlConstant<5>(m_temp[1]) - (m_temp[0] ^ m_rkey[188])) ^ m_rkey[189]; + m_temp[2] = (rotlConstant<3>(m_temp[2]) - (m_temp[1] ^ m_rkey[190])) ^ m_rkey[191]; + m_temp[3] = (rotrConstant<9>(m_temp[3]) - (m_temp[2] ^ m_rkey[180])) ^ m_rkey[181]; + m_temp[0] = (rotlConstant<5>(m_temp[0]) - (m_temp[3] ^ m_rkey[182])) ^ m_rkey[183]; + m_temp[1] = (rotlConstant<3>(m_temp[1]) - (m_temp[0] ^ m_rkey[184])) ^ m_rkey[185]; + m_temp[2] = (rotrConstant<9>(m_temp[2]) - (m_temp[1] ^ m_rkey[174])) ^ m_rkey[175]; + m_temp[3] = (rotlConstant<5>(m_temp[3]) - (m_temp[2] ^ m_rkey[176])) ^ m_rkey[177]; + m_temp[0] = (rotlConstant<3>(m_temp[0]) - (m_temp[3] ^ m_rkey[178])) ^ m_rkey[179]; + m_temp[1] = (rotrConstant<9>(m_temp[1]) - (m_temp[0] ^ m_rkey[168])) ^ m_rkey[169]; + m_temp[2] = (rotlConstant<5>(m_temp[2]) - (m_temp[1] ^ m_rkey[170])) ^ m_rkey[171]; + m_temp[3] = (rotlConstant<3>(m_temp[3]) - (m_temp[2] ^ m_rkey[172])) ^ m_rkey[173]; + } + + if(m_rounds > 24) + { + m_temp[0] = (rotrConstant<9>(m_temp[0]) - (m_temp[3] ^ m_rkey[162])) ^ m_rkey[163]; + m_temp[1] = (rotlConstant<5>(m_temp[1]) - (m_temp[0] ^ m_rkey[164])) ^ m_rkey[165]; + m_temp[2] = (rotlConstant<3>(m_temp[2]) - (m_temp[1] ^ m_rkey[166])) ^ m_rkey[167]; + m_temp[3] = (rotrConstant<9>(m_temp[3]) - (m_temp[2] ^ m_rkey[156])) ^ m_rkey[157]; + m_temp[0] = (rotlConstant<5>(m_temp[0]) - (m_temp[3] ^ m_rkey[158])) ^ m_rkey[159]; + m_temp[1] = (rotlConstant<3>(m_temp[1]) - (m_temp[0] ^ m_rkey[160])) ^ m_rkey[161]; + m_temp[2] = (rotrConstant<9>(m_temp[2]) - (m_temp[1] ^ m_rkey[150])) ^ m_rkey[151]; + m_temp[3] = (rotlConstant<5>(m_temp[3]) - (m_temp[2] ^ m_rkey[152])) ^ m_rkey[153]; + m_temp[0] = (rotlConstant<3>(m_temp[0]) - (m_temp[3] ^ m_rkey[154])) ^ m_rkey[155]; + m_temp[1] = (rotrConstant<9>(m_temp[1]) - (m_temp[0] ^ m_rkey[144])) ^ m_rkey[145]; + m_temp[2] = (rotlConstant<5>(m_temp[2]) - (m_temp[1] ^ m_rkey[146])) ^ m_rkey[147]; + m_temp[3] = (rotlConstant<3>(m_temp[3]) - (m_temp[2] ^ m_rkey[148])) ^ m_rkey[149]; + } + + m_temp[0] = (rotrConstant<9>(m_temp[0]) - (m_temp[3] ^ m_rkey[138])) ^ m_rkey[139]; + m_temp[1] = (rotlConstant<5>(m_temp[1]) - (m_temp[0] ^ m_rkey[140])) ^ m_rkey[141]; + m_temp[2] = (rotlConstant<3>(m_temp[2]) - (m_temp[1] ^ m_rkey[142])) ^ m_rkey[143]; + m_temp[3] = (rotrConstant<9>(m_temp[3]) - (m_temp[2] ^ m_rkey[132])) ^ m_rkey[133]; + m_temp[0] = (rotlConstant<5>(m_temp[0]) - (m_temp[3] ^ m_rkey[134])) ^ m_rkey[135]; + m_temp[1] = (rotlConstant<3>(m_temp[1]) - (m_temp[0] ^ m_rkey[136])) ^ m_rkey[137]; + m_temp[2] = (rotrConstant<9>(m_temp[2]) - (m_temp[1] ^ m_rkey[126])) ^ m_rkey[127]; + m_temp[3] = (rotlConstant<5>(m_temp[3]) - (m_temp[2] ^ m_rkey[128])) ^ m_rkey[129]; + m_temp[0] = (rotlConstant<3>(m_temp[0]) - (m_temp[3] ^ m_rkey[130])) ^ m_rkey[131]; + m_temp[1] = (rotrConstant<9>(m_temp[1]) - (m_temp[0] ^ m_rkey[120])) ^ m_rkey[121]; + m_temp[2] = (rotlConstant<5>(m_temp[2]) - (m_temp[1] ^ m_rkey[122])) ^ m_rkey[123]; + m_temp[3] = (rotlConstant<3>(m_temp[3]) - (m_temp[2] ^ m_rkey[124])) ^ m_rkey[125]; + + m_temp[0] = (rotrConstant<9>(m_temp[0]) - (m_temp[3] ^ m_rkey[114])) ^ m_rkey[115]; + m_temp[1] = (rotlConstant<5>(m_temp[1]) - (m_temp[0] ^ m_rkey[116])) ^ m_rkey[117]; + m_temp[2] = (rotlConstant<3>(m_temp[2]) - (m_temp[1] ^ m_rkey[118])) ^ m_rkey[119]; + m_temp[3] = (rotrConstant<9>(m_temp[3]) - (m_temp[2] ^ m_rkey[108])) ^ m_rkey[109]; + m_temp[0] = (rotlConstant<5>(m_temp[0]) - (m_temp[3] ^ m_rkey[110])) ^ m_rkey[111]; + m_temp[1] = (rotlConstant<3>(m_temp[1]) - (m_temp[0] ^ m_rkey[112])) ^ m_rkey[113]; + m_temp[2] = (rotrConstant<9>(m_temp[2]) - (m_temp[1] ^ m_rkey[102])) ^ m_rkey[103]; + m_temp[3] = (rotlConstant<5>(m_temp[3]) - (m_temp[2] ^ m_rkey[104])) ^ m_rkey[105]; + m_temp[0] = (rotlConstant<3>(m_temp[0]) - (m_temp[3] ^ m_rkey[106])) ^ m_rkey[107]; + m_temp[1] = (rotrConstant<9>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 96])) ^ m_rkey[ 97]; + m_temp[2] = (rotlConstant<5>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 98])) ^ m_rkey[ 99]; + m_temp[3] = (rotlConstant<3>(m_temp[3]) - (m_temp[2] ^ m_rkey[100])) ^ m_rkey[101]; + + m_temp[0] = (rotrConstant<9>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 90])) ^ m_rkey[ 91]; + m_temp[1] = (rotlConstant<5>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 92])) ^ m_rkey[ 93]; + m_temp[2] = (rotlConstant<3>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 94])) ^ m_rkey[ 95]; + m_temp[3] = (rotrConstant<9>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 84])) ^ m_rkey[ 85]; + m_temp[0] = (rotlConstant<5>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 86])) ^ m_rkey[ 87]; + m_temp[1] = (rotlConstant<3>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 88])) ^ m_rkey[ 89]; + m_temp[2] = (rotrConstant<9>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 78])) ^ m_rkey[ 79]; + m_temp[3] = (rotlConstant<5>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 80])) ^ m_rkey[ 81]; + m_temp[0] = (rotlConstant<3>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 82])) ^ m_rkey[ 83]; + m_temp[1] = (rotrConstant<9>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 72])) ^ m_rkey[ 73]; + m_temp[2] = (rotlConstant<5>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 74])) ^ m_rkey[ 75]; + m_temp[3] = (rotlConstant<3>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 76])) ^ m_rkey[ 77]; + + m_temp[0] = (rotrConstant<9>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 66])) ^ m_rkey[ 67]; + m_temp[1] = (rotlConstant<5>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 68])) ^ m_rkey[ 69]; + m_temp[2] = (rotlConstant<3>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 70])) ^ m_rkey[ 71]; + m_temp[3] = (rotrConstant<9>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 60])) ^ m_rkey[ 61]; + m_temp[0] = (rotlConstant<5>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 62])) ^ m_rkey[ 63]; + m_temp[1] = (rotlConstant<3>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 64])) ^ m_rkey[ 65]; + m_temp[2] = (rotrConstant<9>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 54])) ^ m_rkey[ 55]; + m_temp[3] = (rotlConstant<5>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 56])) ^ m_rkey[ 57]; + m_temp[0] = (rotlConstant<3>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 58])) ^ m_rkey[ 59]; + m_temp[1] = (rotrConstant<9>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 48])) ^ m_rkey[ 49]; + m_temp[2] = (rotlConstant<5>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 50])) ^ m_rkey[ 51]; + m_temp[3] = (rotlConstant<3>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 52])) ^ m_rkey[ 53]; + + m_temp[0] = (rotrConstant<9>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 42])) ^ m_rkey[ 43]; + m_temp[1] = (rotlConstant<5>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 44])) ^ m_rkey[ 45]; + m_temp[2] = (rotlConstant<3>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 46])) ^ m_rkey[ 47]; + m_temp[3] = (rotrConstant<9>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 36])) ^ m_rkey[ 37]; + m_temp[0] = (rotlConstant<5>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 38])) ^ m_rkey[ 39]; + m_temp[1] = (rotlConstant<3>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 40])) ^ m_rkey[ 41]; + m_temp[2] = (rotrConstant<9>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 30])) ^ m_rkey[ 31]; + m_temp[3] = (rotlConstant<5>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 32])) ^ m_rkey[ 33]; + m_temp[0] = (rotlConstant<3>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 34])) ^ m_rkey[ 35]; + m_temp[1] = (rotrConstant<9>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 24])) ^ m_rkey[ 25]; + m_temp[2] = (rotlConstant<5>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 26])) ^ m_rkey[ 27]; + m_temp[3] = (rotlConstant<3>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 28])) ^ m_rkey[ 29]; + + m_temp[0] = (rotrConstant<9>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 18])) ^ m_rkey[ 19]; + m_temp[1] = (rotlConstant<5>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 20])) ^ m_rkey[ 21]; + m_temp[2] = (rotlConstant<3>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 22])) ^ m_rkey[ 23]; + m_temp[3] = (rotrConstant<9>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 12])) ^ m_rkey[ 13]; + m_temp[0] = (rotlConstant<5>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 14])) ^ m_rkey[ 15]; + m_temp[1] = (rotlConstant<3>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 16])) ^ m_rkey[ 17]; + m_temp[2] = (rotrConstant<9>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 6])) ^ m_rkey[ 7]; + m_temp[3] = (rotlConstant<5>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 8])) ^ m_rkey[ 9]; + m_temp[0] = (rotlConstant<3>(m_temp[0]) - (m_temp[3] ^ m_rkey[ 10])) ^ m_rkey[ 11]; + m_temp[1] = (rotrConstant<9>(m_temp[1]) - (m_temp[0] ^ m_rkey[ 0])) ^ m_rkey[ 1]; + m_temp[2] = (rotlConstant<5>(m_temp[2]) - (m_temp[1] ^ m_rkey[ 2])) ^ m_rkey[ 3]; + m_temp[3] = (rotlConstant<3>(m_temp[3]) - (m_temp[2] ^ m_rkey[ 4])) ^ m_rkey[ 5]; + + PutBlock oblock(xorBlock, outBlock); + oblock(m_temp[0])(m_temp[1])(m_temp[2])(m_temp[3]); +} + +#if CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS +size_t LEA::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, + byte *outBlocks, size_t length, word32 flags) const +{ +#if defined(CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) { + return LEA_Enc_AdvancedProcessBlocks_SSSE3(m_rkey, m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); + } +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return LEA_Enc_AdvancedProcessBlocks_NEON(m_rkey, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t LEA::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, + byte *outBlocks, size_t length, word32 flags) const +{ +#if defined(CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) { + return LEA_Dec_AdvancedProcessBlocks_SSSE3(m_rkey, m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); + } +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return LEA_Dec_AdvancedProcessBlocks_NEON(m_rkey, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/lea.h b/external/ours/library/crypto/src/shared/original/lea.h new file mode 100755 index 000000000..26650d397 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/lea_simd.cpp b/external/ours/library/crypto/src/shared/original/lea_simd.cpp new file mode 100755 index 000000000..7ea9cfa54 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/lea_simd.cpp @@ -0,0 +1,1072 @@ +// lea_simd.cpp - written and placed in the public domain by Jeffrey Walton +// +// This source file uses intrinsics and built-ins to gain access to +// SSSE3, ARM NEON and ARMv8a, and Power8 Altivec instructions. A separate +// source file is needed because additional CXXFLAGS are required to enable +// the appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" + +#include "lea.h" +#include "misc.h" + +// Uncomment for benchmarking C++ against SSE or NEON. +// Do so in both simon.cpp and simon_simd.cpp. +// #undef CRYPTOPP_SSSE3_AVAILABLE +// #undef CRYPTOPP_ARM_NEON_AVAILABLE + +#if (CRYPTOPP_SSSE3_AVAILABLE) +# include "adv_simd.h" +# include +# include +#endif + +#if defined(__XOP__) +# include +# if defined(__GNUC__) +# include +# endif +#endif + +#if (CRYPTOPP_ARM_NEON_HEADER) +# include "adv_simd.h" +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +#if defined(_M_ARM64) +# include "adv_simd.h" +#endif + +// Do not port this to POWER architecture. Naively we hoped +// for a 2x to 3x speedup. The result was a 5x slow down. +// The table below shows MiB/s and cpb. +// +// C++: +// LEA-128(128)/CTR (128-bit key)C++20715.64 +// LEA-128(192)/CTR (192-bit key)C++18617.48 +// LEA-128(256)/CTR (256-bit key)C++12426.2 +// +// Power8: +// LEA-128(128)/CTR (128-bit key)Power83788.7 +// LEA-128(192)/CTR (192-bit key)Power84082.1 +// LEA-128(256)/CTR (256-bit key)Power828116.0 + +#undef CRYPTOPP_POWER8_AVAILABLE +#if defined(CRYPTOPP_POWER8_AVAILABLE) +# include "adv_simd.h" +# include "ppc_simd.h" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char LEA_SIMD_FNAME[] = __FILE__; + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; + +// *************************** ARM NEON ***************************// + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + +inline uint32x4_t Xor(const uint32x4_t& a, const uint32x4_t& b) +{ + return veorq_u32(a, b); +} + +inline uint32x4_t Add(const uint32x4_t& a, const uint32x4_t& b) +{ + return vaddq_u32(a, b); +} + +inline uint32x4_t Sub(const uint32x4_t& a, const uint32x4_t& b) +{ + return vsubq_u32(a, b); +} + +template +inline uint32x4_t RotateLeft(const uint32x4_t& val) +{ + const uint32x4_t a(vshlq_n_u32(val, R)); + const uint32x4_t b(vshrq_n_u32(val, 32 - R)); + return vorrq_u32(a, b); +} + +template +inline uint32x4_t RotateRight(const uint32x4_t& val) +{ + const uint32x4_t a(vshlq_n_u32(val, 32 - R)); + const uint32x4_t b(vshrq_n_u32(val, R)); + return vorrq_u32(a, b); +} + +#if defined(__aarch32__) || defined(__aarch64__) +template <> +inline uint32x4_t RotateLeft<8>(const uint32x4_t& val) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8_t maskb[16] = { 14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3 }; + const uint8x16_t mask = vld1q_u8(maskb); +#else + const uint8_t maskb[16] = { 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14 }; + const uint8x16_t mask = vld1q_u8(maskb); +#endif + + return vreinterpretq_u32_u8( + vqtbl1q_u8(vreinterpretq_u8_u32(val), mask)); +} + +template <> +inline uint32x4_t RotateRight<8>(const uint32x4_t& val) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8_t maskb[16] = { 12,15,14,13, 8,11,10,9, 4,7,6,5, 0,3,2,1 }; + const uint8x16_t mask = vld1q_u8(maskb); +#else + const uint8_t maskb[16] = { 1,2,3,0, 5,6,7,4, 9,10,11,8, 13,14,14,12 }; + const uint8x16_t mask = vld1q_u8(maskb); +#endif + + return vreinterpretq_u32_u8( + vqtbl1q_u8(vreinterpretq_u8_u32(val), mask)); +} +#endif + +uint32x4_t UnpackLow32(uint32x4_t a, uint32x4_t b) +{ + uint32x2_t a1 = vget_low_u32(a); + uint32x2_t b1 = vget_low_u32(b); + uint32x2x2_t result = vzip_u32(a1, b1); + return vcombine_u32(result.val[0], result.val[1]); +} + +uint32x4_t UnpackHigh32(uint32x4_t a, uint32x4_t b) +{ + uint32x2_t a1 = vget_high_u32(a); + uint32x2_t b1 = vget_high_u32(b); + uint32x2x2_t result = vzip_u32(a1, b1); + return vcombine_u32(result.val[0], result.val[1]); +} + +uint32x4_t UnpackLow64(uint32x4_t a, uint32x4_t b) +{ + uint64x1_t a1 = vget_low_u64((uint64x2_t)a); + uint64x1_t b1 = vget_low_u64((uint64x2_t)b); + return (uint32x4_t)vcombine_u64(a1, b1); +} + +uint32x4_t UnpackHigh64(uint32x4_t a, uint32x4_t b) +{ + uint64x1_t a1 = vget_high_u64((uint64x2_t)a); + uint64x1_t b1 = vget_high_u64((uint64x2_t)b); + return (uint32x4_t)vcombine_u64(a1, b1); +} + +template +inline uint32x4_t LoadKey(const word32 rkey[]) +{ + return vdupq_n_u32(rkey[IDX]); +} + +template +inline uint32x4_t UnpackNEON(const uint32x4_t& a, const uint32x4_t& b, const uint32x4_t& c, const uint32x4_t& d) +{ + // Should not be instantiated + CRYPTOPP_ASSERT(0); + + CRYPTOPP_UNUSED(a); CRYPTOPP_UNUSED(b); + CRYPTOPP_UNUSED(c); CRYPTOPP_UNUSED(d); + return vmovq_n_u32(0); +} + +template <> +inline uint32x4_t UnpackNEON<0>(const uint32x4_t& a, const uint32x4_t& b, const uint32x4_t& c, const uint32x4_t& d) +{ + const uint32x4_t r1 = UnpackLow32(a, b); + const uint32x4_t r2 = UnpackLow32(c, d); + return UnpackLow64(r1, r2); +} + +template <> +inline uint32x4_t UnpackNEON<1>(const uint32x4_t& a, const uint32x4_t& b, const uint32x4_t& c, const uint32x4_t& d) +{ + const uint32x4_t r1 = UnpackLow32(a, b); + const uint32x4_t r2 = UnpackLow32(c, d); + return UnpackHigh64(r1, r2); +} + +template <> +inline uint32x4_t UnpackNEON<2>(const uint32x4_t& a, const uint32x4_t& b, const uint32x4_t& c, const uint32x4_t& d) +{ + const uint32x4_t r1 = UnpackHigh32(a, b); + const uint32x4_t r2 = UnpackHigh32(c, d); + return UnpackLow64(r1, r2); +} + +template <> +inline uint32x4_t UnpackNEON<3>(const uint32x4_t& a, const uint32x4_t& b, const uint32x4_t& c, const uint32x4_t& d) +{ + const uint32x4_t r1 = UnpackHigh32(a, b); + const uint32x4_t r2 = UnpackHigh32(c, d); + return UnpackHigh64(r1, r2); +} + +template +inline uint32x4_t UnpackNEON(const uint32x4_t& v) +{ + // Should not be instantiated + CRYPTOPP_ASSERT(0); + + CRYPTOPP_UNUSED(v); + return vmovq_n_u32(0); +} + +template <> +inline uint32x4_t UnpackNEON<0>(const uint32x4_t& v) +{ + // Splat to all lanes + return vdupq_n_u32(vgetq_lane_u32(v, 0)); +} + +template <> +inline uint32x4_t UnpackNEON<1>(const uint32x4_t& v) +{ + // Splat to all lanes + return vdupq_n_u32(vgetq_lane_u32(v, 1)); +} + +template <> +inline uint32x4_t UnpackNEON<2>(const uint32x4_t& v) +{ + // Splat to all lanes + return vdupq_n_u32(vgetq_lane_u32(v, 2)); +} + +template <> +inline uint32x4_t UnpackNEON<3>(const uint32x4_t& v) +{ + // Splat to all lanes + return vdupq_n_u32(vgetq_lane_u32(v, 3)); +} + +template +inline uint32x4_t RepackNEON(const uint32x4_t& a, const uint32x4_t& b, const uint32x4_t& c, const uint32x4_t& d) +{ + return UnpackNEON(a, b, c, d); +} + +template +inline uint32x4_t RepackNEON(const uint32x4_t& v) +{ + return UnpackNEON(v); +} + +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +// *************************** IA-32 ***************************// + +#if (CRYPTOPP_SSSE3_AVAILABLE) + +inline __m128i Xor(const __m128i& a, const __m128i& b) +{ + return _mm_xor_si128(a, b); +} + +inline __m128i Add(const __m128i& a, const __m128i& b) +{ + return _mm_add_epi32(a, b); +} + +inline __m128i Sub(const __m128i& a, const __m128i& b) +{ + return _mm_sub_epi32(a, b); +} + +template +inline __m128i RotateLeft(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, R); +#else + return _mm_or_si128( + _mm_slli_epi32(val, R), _mm_srli_epi32(val, 32-R)); +#endif +} + +template +inline __m128i RotateRight(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, 32-R); +#else + return _mm_or_si128( + _mm_slli_epi32(val, 32-R), _mm_srli_epi32(val, R)); +#endif +} + +// Faster than two Shifts and an Or. +template <> +inline __m128i RotateLeft<8>(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, 8); +#else + const __m128i mask = _mm_set_epi8(14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3); + return _mm_shuffle_epi8(val, mask); +#endif +} + +// Faster than two Shifts and an Or. +template <> +inline __m128i RotateRight<8>(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi32(val, 32-8); +#else + const __m128i mask = _mm_set_epi8(12,15,14,13, 8,11,10,9, 4,7,6,5, 0,3,2,1); + return _mm_shuffle_epi8(val, mask); +#endif +} + +template +inline __m128i LoadKey(const word32 rkey[]) +{ + float rk; std::memcpy(&rk, rkey+IDX, sizeof(rk)); + return _mm_castps_si128(_mm_load_ps1(&rk)); +} + +template +inline __m128i UnpackXMM(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // Should not be instantiated + CRYPTOPP_UNUSED(a); CRYPTOPP_UNUSED(b); + CRYPTOPP_UNUSED(c); CRYPTOPP_UNUSED(d); + CRYPTOPP_ASSERT(0); + return _mm_setzero_si128(); +} + +template <> +inline __m128i UnpackXMM<0>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // LEA is little-endian oriented, so there is no need for a separate shuffle. + const __m128i r1 = _mm_unpacklo_epi32(a, b); + const __m128i r2 = _mm_unpacklo_epi32(c, d); + return _mm_unpacklo_epi64(r1, r2); +} + +template <> +inline __m128i UnpackXMM<1>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // LEA is little-endian oriented, so there is no need for a separate shuffle. + const __m128i r1 = _mm_unpacklo_epi32(a, b); + const __m128i r2 = _mm_unpacklo_epi32(c, d); + return _mm_unpackhi_epi64(r1, r2); +} + +template <> +inline __m128i UnpackXMM<2>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // LEA is little-endian oriented, so there is no need for a separate shuffle. + const __m128i r1 = _mm_unpackhi_epi32(a, b); + const __m128i r2 = _mm_unpackhi_epi32(c, d); + return _mm_unpacklo_epi64(r1, r2); +} + +template <> +inline __m128i UnpackXMM<3>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // LEA is little-endian oriented, so there is no need for a separate shuffle. + const __m128i r1 = _mm_unpackhi_epi32(a, b); + const __m128i r2 = _mm_unpackhi_epi32(c, d); + return _mm_unpackhi_epi64(r1, r2); +} + +template +inline __m128i UnpackXMM(const __m128i& v) +{ + // Should not be instantiated + CRYPTOPP_UNUSED(v); CRYPTOPP_ASSERT(0); + return _mm_setzero_si128(); +} + +template <> +inline __m128i UnpackXMM<0>(const __m128i& v) +{ + // Splat to all lanes + return _mm_shuffle_epi8(v, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); +} + +template <> +inline __m128i UnpackXMM<1>(const __m128i& v) +{ + // Splat to all lanes + return _mm_shuffle_epi8(v, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); +} + +template <> +inline __m128i UnpackXMM<2>(const __m128i& v) +{ + // Splat to all lanes + return _mm_shuffle_epi8(v, _mm_set_epi8(11,10,9,8, 11,10,9,8, 11,10,9,8, 11,10,9,8)); +} + +template <> +inline __m128i UnpackXMM<3>(const __m128i& v) +{ + // Splat to all lanes + return _mm_shuffle_epi8(v, _mm_set_epi8(15,14,13,12, 15,14,13,12, 15,14,13,12, 15,14,13,12)); +} + +template +inline __m128i RepackXMM(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + return UnpackXMM(a, b, c, d); +} + +template +inline __m128i RepackXMM(const __m128i& v) +{ + return UnpackXMM(v); +} + +#endif // CRYPTOPP_SSSE3_AVAILABLE + +// *************************** Power8 ***************************// + +#if (CRYPTOPP_POWER8_AVAILABLE) + +using CryptoPP::uint8x16_p; +using CryptoPP::uint32x4_p; +using CryptoPP::uint64x2_p; + +inline uint32x4_p Xor(const uint32x4_p& a, const uint32x4_p& b) +{ + return VecXor(a, b); +} + +inline uint32x4_p Add(const uint32x4_p& a, const uint32x4_p& b) +{ + return VecAdd(a, b); +} + +inline uint32x4_p Sub(const uint32x4_p& a, const uint32x4_p& b) +{ + return VecSub(a, b); +} + +template +inline uint32x4_p RotateLeft(const uint32x4_p& val) +{ + const uint32x4_p m = {R, R, R, R}; + return vec_rl(val, m); +} + +template +inline uint32x4_p RotateRight(const uint32x4_p& val) +{ + const uint32x4_p m = {32-R, 32-R, 32-R, 32-R}; + return vec_rl(val, m); +} + +template +inline uint32x4_p LoadKey(const word32 rkey[]) +{ + return vec_splats(rkey[IDX]); +} + +template +inline uint32x4_p UnpackSIMD(const uint32x4_p& a, const uint32x4_p& b, const uint32x4_p& c, const uint32x4_p& d) +{ + // Should not be instantiated + CRYPTOPP_UNUSED(a); CRYPTOPP_UNUSED(b); + CRYPTOPP_UNUSED(c); CRYPTOPP_UNUSED(d); + CRYPTOPP_ASSERT(0); + return VecXor(a, a); +} + +template <> +inline uint32x4_p UnpackSIMD<0>(const uint32x4_p& a, const uint32x4_p& b, const uint32x4_p& c, const uint32x4_p& d) +{ + const uint64x2_p r1 = (uint64x2_p)vec_mergel(a, b); + const uint64x2_p r2 = (uint64x2_p)vec_mergel(c, d); + return (uint32x4_p)vec_mergel(r1, r2); +} + +template <> +inline uint32x4_p UnpackSIMD<1>(const uint32x4_p& a, const uint32x4_p& b, const uint32x4_p& c, const uint32x4_p& d) +{ + const uint64x2_p r1 = (uint64x2_p)vec_mergel(a, b); + const uint64x2_p r2 = (uint64x2_p)vec_mergel(c, d); + return (uint32x4_p)vec_mergeh(r1, r2); +} + +template <> +inline uint32x4_p UnpackSIMD<2>(const uint32x4_p& a, const uint32x4_p& b, const uint32x4_p& c, const uint32x4_p& d) +{ + const uint64x2_p r1 = (uint64x2_p)vec_mergeh(a, b); + const uint64x2_p r2 = (uint64x2_p)vec_mergeh(c, d); + return (uint32x4_p)vec_mergel(r1, r2); +} + +template <> +inline uint32x4_p UnpackSIMD<3>(const uint32x4_p& a, const uint32x4_p& b, const uint32x4_p& c, const uint32x4_p& d) +{ + const uint64x2_p r1 = (uint64x2_p)vec_mergeh(a, b); + const uint64x2_p r2 = (uint64x2_p)vec_mergeh(c, d); + return (uint32x4_p)vec_mergeh(r1, r2); +} + +template +inline uint32x4_p UnpackSIMD(const uint32x4_p& v) +{ + // Should not be instantiated + CRYPTOPP_ASSERT(0); + return VecXor(v, v); +} + +template <> +inline uint32x4_p UnpackSIMD<0>(const uint32x4_p& v) +{ + // Splat to all lanes + const uint8x16_p m = {3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0}; + return (uint32x4_p)VecPermute(v, v, m); +} + +template <> +inline uint32x4_p UnpackSIMD<1>(const uint32x4_p& v) +{ + // Splat to all lanes + const uint8x16_p m = {7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4}; + return (uint32x4_p)VecPermute(v, v, m); +} + +template <> +inline uint32x4_p UnpackSIMD<2>(const uint32x4_p& v) +{ + // Splat to all lanes + const uint8x16_p m = {11,10,9,8, 11,10,9,8, 11,10,9,8, 11,10,9,8}; + return (uint32x4_p)VecPermute(v, v, m); +} + +template <> +inline uint32x4_p UnpackSIMD<3>(const uint32x4_p& v) +{ + // Splat to all lanes + const uint8x16_p m = {15,14,13,12, 15,14,13,12, 15,14,13,12, 15,14,13,12}; + return (uint32x4_p)VecPermute(v, v, m); +} + +template +inline uint32x4_p RepackSIMD(const uint32x4_p& a, const uint32x4_p& b, const uint32x4_p& c, const uint32x4_p& d) +{ + return UnpackSIMD(a, b, c, d); +} + +template +inline uint32x4_p RepackSIMD(const uint32x4_p& v) +{ + return UnpackSIMD(v); +} + +#endif // CRYPTOPP_POWER8_AVAILABLE + +// *************************** LEA Encryption ***************************// + +#if (CRYPTOPP_ARM_NEON_AVAILABLE || CRYPTOPP_SSSE3_AVAILABLE) + +template +inline void LEA_Encryption(W temp[4], const word32 *subkeys, unsigned int rounds) +{ + temp[3] = RotateRight<3>(Add(Xor(temp[2], LoadKey<4>(subkeys)), Xor(temp[3], LoadKey<5>(subkeys)))); + temp[2] = RotateRight<5>(Add(Xor(temp[1], LoadKey<2>(subkeys)), Xor(temp[2], LoadKey<3>(subkeys)))); + temp[1] = RotateLeft<9>(Add(Xor(temp[0], LoadKey<0>(subkeys)), Xor(temp[1], LoadKey<1>(subkeys)))); + temp[0] = RotateRight<3>(Add(Xor(temp[3], LoadKey<10>(subkeys)), Xor(temp[0], LoadKey<11>(subkeys)))); + temp[3] = RotateRight<5>(Add(Xor(temp[2], LoadKey<8>(subkeys)), Xor(temp[3], LoadKey<9>(subkeys)))); + temp[2] = RotateLeft<9>(Add(Xor(temp[1], LoadKey<6>(subkeys)), Xor(temp[2], LoadKey<7>(subkeys)))); + temp[1] = RotateRight<3>(Add(Xor(temp[0], LoadKey<16>(subkeys)), Xor(temp[1], LoadKey<17>(subkeys)))); + temp[0] = RotateRight<5>(Add(Xor(temp[3], LoadKey<14>(subkeys)), Xor(temp[0], LoadKey<15>(subkeys)))); + temp[3] = RotateLeft<9>(Add(Xor(temp[2], LoadKey<12>(subkeys)), Xor(temp[3], LoadKey<13>(subkeys)))); + temp[2] = RotateRight<3>(Add(Xor(temp[1], LoadKey<22>(subkeys)), Xor(temp[2], LoadKey<23>(subkeys)))); + temp[1] = RotateRight<5>(Add(Xor(temp[0], LoadKey<20>(subkeys)), Xor(temp[1], LoadKey<21>(subkeys)))); + temp[0] = RotateLeft<9>(Add(Xor(temp[3], LoadKey<18>(subkeys)), Xor(temp[0], LoadKey<19>(subkeys)))); + + temp[3] = RotateRight<3>(Add(Xor(temp[2], LoadKey<28>(subkeys)), Xor(temp[3], LoadKey<29>(subkeys)))); + temp[2] = RotateRight<5>(Add(Xor(temp[1], LoadKey<26>(subkeys)), Xor(temp[2], LoadKey<27>(subkeys)))); + temp[1] = RotateLeft<9>(Add(Xor(temp[0], LoadKey<24>(subkeys)), Xor(temp[1], LoadKey<25>(subkeys)))); + temp[0] = RotateRight<3>(Add(Xor(temp[3], LoadKey<34>(subkeys)), Xor(temp[0], LoadKey<35>(subkeys)))); + temp[3] = RotateRight<5>(Add(Xor(temp[2], LoadKey<32>(subkeys)), Xor(temp[3], LoadKey<33>(subkeys)))); + temp[2] = RotateLeft<9>(Add(Xor(temp[1], LoadKey<30>(subkeys)), Xor(temp[2], LoadKey<31>(subkeys)))); + temp[1] = RotateRight<3>(Add(Xor(temp[0], LoadKey<40>(subkeys)), Xor(temp[1], LoadKey<41>(subkeys)))); + temp[0] = RotateRight<5>(Add(Xor(temp[3], LoadKey<38>(subkeys)), Xor(temp[0], LoadKey<39>(subkeys)))); + temp[3] = RotateLeft<9>(Add(Xor(temp[2], LoadKey<36>(subkeys)), Xor(temp[3], LoadKey<37>(subkeys)))); + temp[2] = RotateRight<3>(Add(Xor(temp[1], LoadKey<46>(subkeys)), Xor(temp[2], LoadKey<47>(subkeys)))); + temp[1] = RotateRight<5>(Add(Xor(temp[0], LoadKey<44>(subkeys)), Xor(temp[1], LoadKey<45>(subkeys)))); + temp[0] = RotateLeft<9>(Add(Xor(temp[3], LoadKey<42>(subkeys)), Xor(temp[0], LoadKey<43>(subkeys)))); + + temp[3] = RotateRight<3>(Add(Xor(temp[2], LoadKey<52>(subkeys)), Xor(temp[3], LoadKey<53>(subkeys)))); + temp[2] = RotateRight<5>(Add(Xor(temp[1], LoadKey<50>(subkeys)), Xor(temp[2], LoadKey<51>(subkeys)))); + temp[1] = RotateLeft<9>(Add(Xor(temp[0], LoadKey<48>(subkeys)), Xor(temp[1], LoadKey<49>(subkeys)))); + temp[0] = RotateRight<3>(Add(Xor(temp[3], LoadKey<58>(subkeys)), Xor(temp[0], LoadKey<59>(subkeys)))); + temp[3] = RotateRight<5>(Add(Xor(temp[2], LoadKey<56>(subkeys)), Xor(temp[3], LoadKey<57>(subkeys)))); + temp[2] = RotateLeft<9>(Add(Xor(temp[1], LoadKey<54>(subkeys)), Xor(temp[2], LoadKey<55>(subkeys)))); + temp[1] = RotateRight<3>(Add(Xor(temp[0], LoadKey<64>(subkeys)), Xor(temp[1], LoadKey<65>(subkeys)))); + temp[0] = RotateRight<5>(Add(Xor(temp[3], LoadKey<62>(subkeys)), Xor(temp[0], LoadKey<63>(subkeys)))); + temp[3] = RotateLeft<9>(Add(Xor(temp[2], LoadKey<60>(subkeys)), Xor(temp[3], LoadKey<61>(subkeys)))); + temp[2] = RotateRight<3>(Add(Xor(temp[1], LoadKey<70>(subkeys)), Xor(temp[2], LoadKey<71>(subkeys)))); + temp[1] = RotateRight<5>(Add(Xor(temp[0], LoadKey<68>(subkeys)), Xor(temp[1], LoadKey<69>(subkeys)))); + temp[0] = RotateLeft<9>(Add(Xor(temp[3], LoadKey<66>(subkeys)), Xor(temp[0], LoadKey<67>(subkeys)))); + + temp[3] = RotateRight<3>(Add(Xor(temp[2], LoadKey<76>(subkeys)), Xor(temp[3], LoadKey<77>(subkeys)))); + temp[2] = RotateRight<5>(Add(Xor(temp[1], LoadKey<74>(subkeys)), Xor(temp[2], LoadKey<75>(subkeys)))); + temp[1] = RotateLeft<9>(Add(Xor(temp[0], LoadKey<72>(subkeys)), Xor(temp[1], LoadKey<73>(subkeys)))); + temp[0] = RotateRight<3>(Add(Xor(temp[3], LoadKey<82>(subkeys)), Xor(temp[0], LoadKey<83>(subkeys)))); + temp[3] = RotateRight<5>(Add(Xor(temp[2], LoadKey<80>(subkeys)), Xor(temp[3], LoadKey<81>(subkeys)))); + temp[2] = RotateLeft<9>(Add(Xor(temp[1], LoadKey<78>(subkeys)), Xor(temp[2], LoadKey<79>(subkeys)))); + temp[1] = RotateRight<3>(Add(Xor(temp[0], LoadKey<88>(subkeys)), Xor(temp[1], LoadKey<89>(subkeys)))); + temp[0] = RotateRight<5>(Add(Xor(temp[3], LoadKey<86>(subkeys)), Xor(temp[0], LoadKey<87>(subkeys)))); + temp[3] = RotateLeft<9>(Add(Xor(temp[2], LoadKey<84>(subkeys)), Xor(temp[3], LoadKey<85>(subkeys)))); + temp[2] = RotateRight<3>(Add(Xor(temp[1], LoadKey<94>(subkeys)), Xor(temp[2], LoadKey<95>(subkeys)))); + temp[1] = RotateRight<5>(Add(Xor(temp[0], LoadKey<92>(subkeys)), Xor(temp[1], LoadKey<93>(subkeys)))); + temp[0] = RotateLeft<9>(Add(Xor(temp[3], LoadKey<90>(subkeys)), Xor(temp[0], LoadKey<91>(subkeys)))); + + temp[3] = RotateRight<3>(Add(Xor(temp[2], LoadKey<100>(subkeys)), Xor(temp[3], LoadKey<101>(subkeys)))); + temp[2] = RotateRight<5>(Add(Xor(temp[1], LoadKey<98>(subkeys)), Xor(temp[2], LoadKey<99>(subkeys)))); + temp[1] = RotateLeft<9>(Add(Xor(temp[0], LoadKey<96>(subkeys)), Xor(temp[1], LoadKey<97>(subkeys)))); + temp[0] = RotateRight<3>(Add(Xor(temp[3], LoadKey<106>(subkeys)), Xor(temp[0], LoadKey<107>(subkeys)))); + temp[3] = RotateRight<5>(Add(Xor(temp[2], LoadKey<104>(subkeys)), Xor(temp[3], LoadKey<105>(subkeys)))); + temp[2] = RotateLeft<9>(Add(Xor(temp[1], LoadKey<102>(subkeys)), Xor(temp[2], LoadKey<103>(subkeys)))); + temp[1] = RotateRight<3>(Add(Xor(temp[0], LoadKey<112>(subkeys)), Xor(temp[1], LoadKey<113>(subkeys)))); + temp[0] = RotateRight<5>(Add(Xor(temp[3], LoadKey<110>(subkeys)), Xor(temp[0], LoadKey<111>(subkeys)))); + temp[3] = RotateLeft<9>(Add(Xor(temp[2], LoadKey<108>(subkeys)), Xor(temp[3], LoadKey<109>(subkeys)))); + temp[2] = RotateRight<3>(Add(Xor(temp[1], LoadKey<118>(subkeys)), Xor(temp[2], LoadKey<119>(subkeys)))); + temp[1] = RotateRight<5>(Add(Xor(temp[0], LoadKey<116>(subkeys)), Xor(temp[1], LoadKey<117>(subkeys)))); + temp[0] = RotateLeft<9>(Add(Xor(temp[3], LoadKey<114>(subkeys)), Xor(temp[0], LoadKey<115>(subkeys)))); + + temp[3] = RotateRight<3>(Add(Xor(temp[2], LoadKey<124>(subkeys)), Xor(temp[3], LoadKey<125>(subkeys)))); + temp[2] = RotateRight<5>(Add(Xor(temp[1], LoadKey<122>(subkeys)), Xor(temp[2], LoadKey<123>(subkeys)))); + temp[1] = RotateLeft<9>(Add(Xor(temp[0], LoadKey<120>(subkeys)), Xor(temp[1], LoadKey<121>(subkeys)))); + temp[0] = RotateRight<3>(Add(Xor(temp[3], LoadKey<130>(subkeys)), Xor(temp[0], LoadKey<131>(subkeys)))); + temp[3] = RotateRight<5>(Add(Xor(temp[2], LoadKey<128>(subkeys)), Xor(temp[3], LoadKey<129>(subkeys)))); + temp[2] = RotateLeft<9>(Add(Xor(temp[1], LoadKey<126>(subkeys)), Xor(temp[2], LoadKey<127>(subkeys)))); + temp[1] = RotateRight<3>(Add(Xor(temp[0], LoadKey<136>(subkeys)), Xor(temp[1], LoadKey<137>(subkeys)))); + temp[0] = RotateRight<5>(Add(Xor(temp[3], LoadKey<134>(subkeys)), Xor(temp[0], LoadKey<135>(subkeys)))); + temp[3] = RotateLeft<9>(Add(Xor(temp[2], LoadKey<132>(subkeys)), Xor(temp[3], LoadKey<133>(subkeys)))); + temp[2] = RotateRight<3>(Add(Xor(temp[1], LoadKey<142>(subkeys)), Xor(temp[2], LoadKey<143>(subkeys)))); + temp[1] = RotateRight<5>(Add(Xor(temp[0], LoadKey<140>(subkeys)), Xor(temp[1], LoadKey<141>(subkeys)))); + temp[0] = RotateLeft<9>(Add(Xor(temp[3], LoadKey<138>(subkeys)), Xor(temp[0], LoadKey<139>(subkeys)))); + + if(rounds > 24) + { + temp[3] = RotateRight<3>(Add(Xor(temp[2], LoadKey<148>(subkeys)), Xor(temp[3], LoadKey<149>(subkeys)))); + temp[2] = RotateRight<5>(Add(Xor(temp[1], LoadKey<146>(subkeys)), Xor(temp[2], LoadKey<147>(subkeys)))); + temp[1] = RotateLeft<9>(Add(Xor(temp[0], LoadKey<144>(subkeys)), Xor(temp[1], LoadKey<145>(subkeys)))); + temp[0] = RotateRight<3>(Add(Xor(temp[3], LoadKey<154>(subkeys)), Xor(temp[0], LoadKey<155>(subkeys)))); + temp[3] = RotateRight<5>(Add(Xor(temp[2], LoadKey<152>(subkeys)), Xor(temp[3], LoadKey<153>(subkeys)))); + temp[2] = RotateLeft<9>(Add(Xor(temp[1], LoadKey<150>(subkeys)), Xor(temp[2], LoadKey<151>(subkeys)))); + temp[1] = RotateRight<3>(Add(Xor(temp[0], LoadKey<160>(subkeys)), Xor(temp[1], LoadKey<161>(subkeys)))); + temp[0] = RotateRight<5>(Add(Xor(temp[3], LoadKey<158>(subkeys)), Xor(temp[0], LoadKey<159>(subkeys)))); + temp[3] = RotateLeft<9>(Add(Xor(temp[2], LoadKey<156>(subkeys)), Xor(temp[3], LoadKey<157>(subkeys)))); + temp[2] = RotateRight<3>(Add(Xor(temp[1], LoadKey<166>(subkeys)), Xor(temp[2], LoadKey<167>(subkeys)))); + temp[1] = RotateRight<5>(Add(Xor(temp[0], LoadKey<164>(subkeys)), Xor(temp[1], LoadKey<165>(subkeys)))); + temp[0] = RotateLeft<9>(Add(Xor(temp[3], LoadKey<162>(subkeys)), Xor(temp[0], LoadKey<163>(subkeys)))); + } + + if(rounds > 28) + { + temp[3] = RotateRight<3>(Add(Xor(temp[2], LoadKey<172>(subkeys)), Xor(temp[3], LoadKey<173>(subkeys)))); + temp[2] = RotateRight<5>(Add(Xor(temp[1], LoadKey<170>(subkeys)), Xor(temp[2], LoadKey<171>(subkeys)))); + temp[1] = RotateLeft<9>(Add(Xor(temp[0], LoadKey<168>(subkeys)), Xor(temp[1], LoadKey<169>(subkeys)))); + temp[0] = RotateRight<3>(Add(Xor(temp[3], LoadKey<178>(subkeys)), Xor(temp[0], LoadKey<179>(subkeys)))); + temp[3] = RotateRight<5>(Add(Xor(temp[2], LoadKey<176>(subkeys)), Xor(temp[3], LoadKey<177>(subkeys)))); + temp[2] = RotateLeft<9>(Add(Xor(temp[1], LoadKey<174>(subkeys)), Xor(temp[2], LoadKey<175>(subkeys)))); + temp[1] = RotateRight<3>(Add(Xor(temp[0], LoadKey<184>(subkeys)), Xor(temp[1], LoadKey<185>(subkeys)))); + temp[0] = RotateRight<5>(Add(Xor(temp[3], LoadKey<182>(subkeys)), Xor(temp[0], LoadKey<183>(subkeys)))); + temp[3] = RotateLeft<9>(Add(Xor(temp[2], LoadKey<180>(subkeys)), Xor(temp[3], LoadKey<181>(subkeys)))); + temp[2] = RotateRight<3>(Add(Xor(temp[1], LoadKey<190>(subkeys)), Xor(temp[2], LoadKey<191>(subkeys)))); + temp[1] = RotateRight<5>(Add(Xor(temp[0], LoadKey<188>(subkeys)), Xor(temp[1], LoadKey<189>(subkeys)))); + temp[0] = RotateLeft<9>(Add(Xor(temp[3], LoadKey<186>(subkeys)), Xor(temp[0], LoadKey<187>(subkeys)))); + } +} + +// *************************** LEA Decryption ***************************// + +template +inline void LEA_Decryption(W temp[4], const word32 *subkeys, unsigned int rounds) +{ + if(rounds > 28) + { + temp[0] = Xor(Sub(RotateRight<9>(temp[0]), Xor(temp[3], LoadKey<186>(subkeys))), LoadKey<187>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<5>(temp[1]), Xor(temp[0], LoadKey<188>(subkeys))), LoadKey<189>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<3>(temp[2]), Xor(temp[1], LoadKey<190>(subkeys))), LoadKey<191>(subkeys)); + temp[3] = Xor(Sub(RotateRight<9>(temp[3]), Xor(temp[2], LoadKey<180>(subkeys))), LoadKey<181>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<5>(temp[0]), Xor(temp[3], LoadKey<182>(subkeys))), LoadKey<183>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<3>(temp[1]), Xor(temp[0], LoadKey<184>(subkeys))), LoadKey<185>(subkeys)); + temp[2] = Xor(Sub(RotateRight<9>(temp[2]), Xor(temp[1], LoadKey<174>(subkeys))), LoadKey<175>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<5>(temp[3]), Xor(temp[2], LoadKey<176>(subkeys))), LoadKey<177>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<3>(temp[0]), Xor(temp[3], LoadKey<178>(subkeys))), LoadKey<179>(subkeys)); + temp[1] = Xor(Sub(RotateRight<9>(temp[1]), Xor(temp[0], LoadKey<168>(subkeys))), LoadKey<169>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<5>(temp[2]), Xor(temp[1], LoadKey<170>(subkeys))), LoadKey<171>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<3>(temp[3]), Xor(temp[2], LoadKey<172>(subkeys))), LoadKey<173>(subkeys)); + } + + if(rounds > 24) + { + temp[0] = Xor(Sub(RotateRight<9>(temp[0]), Xor(temp[3], LoadKey<162>(subkeys))), LoadKey<163>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<5>(temp[1]), Xor(temp[0], LoadKey<164>(subkeys))), LoadKey<165>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<3>(temp[2]), Xor(temp[1], LoadKey<166>(subkeys))), LoadKey<167>(subkeys)); + temp[3] = Xor(Sub(RotateRight<9>(temp[3]), Xor(temp[2], LoadKey<156>(subkeys))), LoadKey<157>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<5>(temp[0]), Xor(temp[3], LoadKey<158>(subkeys))), LoadKey<159>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<3>(temp[1]), Xor(temp[0], LoadKey<160>(subkeys))), LoadKey<161>(subkeys)); + temp[2] = Xor(Sub(RotateRight<9>(temp[2]), Xor(temp[1], LoadKey<150>(subkeys))), LoadKey<151>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<5>(temp[3]), Xor(temp[2], LoadKey<152>(subkeys))), LoadKey<153>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<3>(temp[0]), Xor(temp[3], LoadKey<154>(subkeys))), LoadKey<155>(subkeys)); + temp[1] = Xor(Sub(RotateRight<9>(temp[1]), Xor(temp[0], LoadKey<144>(subkeys))), LoadKey<145>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<5>(temp[2]), Xor(temp[1], LoadKey<146>(subkeys))), LoadKey<147>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<3>(temp[3]), Xor(temp[2], LoadKey<148>(subkeys))), LoadKey<149>(subkeys)); + } + + temp[0] = Xor(Sub(RotateRight<9>(temp[0]), Xor(temp[3], LoadKey<138>(subkeys))), LoadKey<139>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<5>(temp[1]), Xor(temp[0], LoadKey<140>(subkeys))), LoadKey<141>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<3>(temp[2]), Xor(temp[1], LoadKey<142>(subkeys))), LoadKey<143>(subkeys)); + temp[3] = Xor(Sub(RotateRight<9>(temp[3]), Xor(temp[2], LoadKey<132>(subkeys))), LoadKey<133>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<5>(temp[0]), Xor(temp[3], LoadKey<134>(subkeys))), LoadKey<135>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<3>(temp[1]), Xor(temp[0], LoadKey<136>(subkeys))), LoadKey<137>(subkeys)); + temp[2] = Xor(Sub(RotateRight<9>(temp[2]), Xor(temp[1], LoadKey<126>(subkeys))), LoadKey<127>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<5>(temp[3]), Xor(temp[2], LoadKey<128>(subkeys))), LoadKey<129>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<3>(temp[0]), Xor(temp[3], LoadKey<130>(subkeys))), LoadKey<131>(subkeys)); + temp[1] = Xor(Sub(RotateRight<9>(temp[1]), Xor(temp[0], LoadKey<120>(subkeys))), LoadKey<121>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<5>(temp[2]), Xor(temp[1], LoadKey<122>(subkeys))), LoadKey<123>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<3>(temp[3]), Xor(temp[2], LoadKey<124>(subkeys))), LoadKey<125>(subkeys)); + + temp[0] = Xor(Sub(RotateRight<9>(temp[0]), Xor(temp[3], LoadKey<114>(subkeys))), LoadKey<115>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<5>(temp[1]), Xor(temp[0], LoadKey<116>(subkeys))), LoadKey<117>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<3>(temp[2]), Xor(temp[1], LoadKey<118>(subkeys))), LoadKey<119>(subkeys)); + temp[3] = Xor(Sub(RotateRight<9>(temp[3]), Xor(temp[2], LoadKey<108>(subkeys))), LoadKey<109>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<5>(temp[0]), Xor(temp[3], LoadKey<110>(subkeys))), LoadKey<111>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<3>(temp[1]), Xor(temp[0], LoadKey<112>(subkeys))), LoadKey<113>(subkeys)); + temp[2] = Xor(Sub(RotateRight<9>(temp[2]), Xor(temp[1], LoadKey<102>(subkeys))), LoadKey<103>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<5>(temp[3]), Xor(temp[2], LoadKey<104>(subkeys))), LoadKey<105>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<3>(temp[0]), Xor(temp[3], LoadKey<106>(subkeys))), LoadKey<107>(subkeys)); + temp[1] = Xor(Sub(RotateRight<9>(temp[1]), Xor(temp[0], LoadKey<96>(subkeys))), LoadKey<97>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<5>(temp[2]), Xor(temp[1], LoadKey<98>(subkeys))), LoadKey<99>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<3>(temp[3]), Xor(temp[2], LoadKey<100>(subkeys))), LoadKey<101>(subkeys)); + + temp[0] = Xor(Sub(RotateRight<9>(temp[0]), Xor(temp[3], LoadKey<90>(subkeys))), LoadKey<91>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<5>(temp[1]), Xor(temp[0], LoadKey<92>(subkeys))), LoadKey<93>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<3>(temp[2]), Xor(temp[1], LoadKey<94>(subkeys))), LoadKey<95>(subkeys)); + temp[3] = Xor(Sub(RotateRight<9>(temp[3]), Xor(temp[2], LoadKey<84>(subkeys))), LoadKey<85>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<5>(temp[0]), Xor(temp[3], LoadKey<86>(subkeys))), LoadKey<87>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<3>(temp[1]), Xor(temp[0], LoadKey<88>(subkeys))), LoadKey<89>(subkeys)); + temp[2] = Xor(Sub(RotateRight<9>(temp[2]), Xor(temp[1], LoadKey<78>(subkeys))), LoadKey<79>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<5>(temp[3]), Xor(temp[2], LoadKey<80>(subkeys))), LoadKey<81>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<3>(temp[0]), Xor(temp[3], LoadKey<82>(subkeys))), LoadKey<83>(subkeys)); + temp[1] = Xor(Sub(RotateRight<9>(temp[1]), Xor(temp[0], LoadKey<72>(subkeys))), LoadKey<73>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<5>(temp[2]), Xor(temp[1], LoadKey<74>(subkeys))), LoadKey<75>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<3>(temp[3]), Xor(temp[2], LoadKey<76>(subkeys))), LoadKey<77>(subkeys)); + + temp[0] = Xor(Sub(RotateRight<9>(temp[0]), Xor(temp[3], LoadKey<66>(subkeys))), LoadKey<67>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<5>(temp[1]), Xor(temp[0], LoadKey<68>(subkeys))), LoadKey<69>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<3>(temp[2]), Xor(temp[1], LoadKey<70>(subkeys))), LoadKey<71>(subkeys)); + temp[3] = Xor(Sub(RotateRight<9>(temp[3]), Xor(temp[2], LoadKey<60>(subkeys))), LoadKey<61>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<5>(temp[0]), Xor(temp[3], LoadKey<62>(subkeys))), LoadKey<63>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<3>(temp[1]), Xor(temp[0], LoadKey<64>(subkeys))), LoadKey<65>(subkeys)); + temp[2] = Xor(Sub(RotateRight<9>(temp[2]), Xor(temp[1], LoadKey<54>(subkeys))), LoadKey<55>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<5>(temp[3]), Xor(temp[2], LoadKey<56>(subkeys))), LoadKey<57>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<3>(temp[0]), Xor(temp[3], LoadKey<58>(subkeys))), LoadKey<59>(subkeys)); + temp[1] = Xor(Sub(RotateRight<9>(temp[1]), Xor(temp[0], LoadKey<48>(subkeys))), LoadKey<49>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<5>(temp[2]), Xor(temp[1], LoadKey<50>(subkeys))), LoadKey<51>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<3>(temp[3]), Xor(temp[2], LoadKey<52>(subkeys))), LoadKey<53>(subkeys)); + + temp[0] = Xor(Sub(RotateRight<9>(temp[0]), Xor(temp[3], LoadKey<42>(subkeys))), LoadKey<43>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<5>(temp[1]), Xor(temp[0], LoadKey<44>(subkeys))), LoadKey<45>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<3>(temp[2]), Xor(temp[1], LoadKey<46>(subkeys))), LoadKey<47>(subkeys)); + temp[3] = Xor(Sub(RotateRight<9>(temp[3]), Xor(temp[2], LoadKey<36>(subkeys))), LoadKey<37>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<5>(temp[0]), Xor(temp[3], LoadKey<38>(subkeys))), LoadKey<39>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<3>(temp[1]), Xor(temp[0], LoadKey<40>(subkeys))), LoadKey<41>(subkeys)); + temp[2] = Xor(Sub(RotateRight<9>(temp[2]), Xor(temp[1], LoadKey<30>(subkeys))), LoadKey<31>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<5>(temp[3]), Xor(temp[2], LoadKey<32>(subkeys))), LoadKey<33>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<3>(temp[0]), Xor(temp[3], LoadKey<34>(subkeys))), LoadKey<35>(subkeys)); + temp[1] = Xor(Sub(RotateRight<9>(temp[1]), Xor(temp[0], LoadKey<24>(subkeys))), LoadKey<25>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<5>(temp[2]), Xor(temp[1], LoadKey<26>(subkeys))), LoadKey<27>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<3>(temp[3]), Xor(temp[2], LoadKey<28>(subkeys))), LoadKey<29>(subkeys)); + + temp[0] = Xor(Sub(RotateRight<9>(temp[0]), Xor(temp[3], LoadKey<18>(subkeys))), LoadKey<19>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<5>(temp[1]), Xor(temp[0], LoadKey<20>(subkeys))), LoadKey<21>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<3>(temp[2]), Xor(temp[1], LoadKey<22>(subkeys))), LoadKey<23>(subkeys)); + temp[3] = Xor(Sub(RotateRight<9>(temp[3]), Xor(temp[2], LoadKey<12>(subkeys))), LoadKey<13>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<5>(temp[0]), Xor(temp[3], LoadKey<14>(subkeys))), LoadKey<15>(subkeys)); + temp[1] = Xor(Sub(RotateLeft<3>(temp[1]), Xor(temp[0], LoadKey<16>(subkeys))), LoadKey<17>(subkeys)); + temp[2] = Xor(Sub(RotateRight<9>(temp[2]), Xor(temp[1], LoadKey<6>(subkeys))), LoadKey<7>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<5>(temp[3]), Xor(temp[2], LoadKey<8>(subkeys))), LoadKey<9>(subkeys)); + temp[0] = Xor(Sub(RotateLeft<3>(temp[0]), Xor(temp[3], LoadKey<10>(subkeys))), LoadKey<11>(subkeys)); + temp[1] = Xor(Sub(RotateRight<9>(temp[1]), Xor(temp[0], LoadKey<0>(subkeys))), LoadKey<1>(subkeys)); + temp[2] = Xor(Sub(RotateLeft<5>(temp[2]), Xor(temp[1], LoadKey<2>(subkeys))), LoadKey<3>(subkeys)); + temp[3] = Xor(Sub(RotateLeft<3>(temp[3]), Xor(temp[2], LoadKey<4>(subkeys))), LoadKey<5>(subkeys)); +} + +#endif // LEA Encryption and Decryption + +// *************************** ARM NEON ***************************// + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + +inline void LEA_Enc_Block(uint32x4_t &block0, + const word32 *subkeys, unsigned int rounds) +{ + uint32x4_t temp[4]; + temp[0] = UnpackNEON<0>(block0); + temp[1] = UnpackNEON<1>(block0); + temp[2] = UnpackNEON<2>(block0); + temp[3] = UnpackNEON<3>(block0); + + LEA_Encryption(temp, subkeys, rounds); + + block0 = RepackNEON<0>(temp[0], temp[1], temp[2], temp[3]); +} + +inline void LEA_Dec_Block(uint32x4_t &block0, + const word32 *subkeys, unsigned int rounds) +{ + uint32x4_t temp[4]; + temp[0] = UnpackNEON<0>(block0); + temp[1] = UnpackNEON<1>(block0); + temp[2] = UnpackNEON<2>(block0); + temp[3] = UnpackNEON<3>(block0); + + LEA_Decryption(temp, subkeys, rounds); + + block0 = RepackNEON<0>(temp[0], temp[1], temp[2], temp[3]); +} + +inline void LEA_Enc_4_Blocks(uint32x4_t &block0, uint32x4_t &block1, + uint32x4_t &block2, uint32x4_t &block3, const word32 *subkeys, unsigned int rounds) +{ + uint32x4_t temp[4]; + temp[0] = UnpackNEON<0>(block0, block1, block2, block3); + temp[1] = UnpackNEON<1>(block0, block1, block2, block3); + temp[2] = UnpackNEON<2>(block0, block1, block2, block3); + temp[3] = UnpackNEON<3>(block0, block1, block2, block3); + + LEA_Encryption(temp, subkeys, rounds); + + block0 = RepackNEON<0>(temp[0], temp[1], temp[2], temp[3]); + block1 = RepackNEON<1>(temp[0], temp[1], temp[2], temp[3]); + block2 = RepackNEON<2>(temp[0], temp[1], temp[2], temp[3]); + block3 = RepackNEON<3>(temp[0], temp[1], temp[2], temp[3]); +} + +inline void LEA_Dec_4_Blocks(uint32x4_t &block0, uint32x4_t &block1, + uint32x4_t &block2, uint32x4_t &block3, const word32 *subkeys, unsigned int rounds) +{ + uint32x4_t temp[4]; + temp[0] = UnpackNEON<0>(block0, block1, block2, block3); + temp[1] = UnpackNEON<1>(block0, block1, block2, block3); + temp[2] = UnpackNEON<2>(block0, block1, block2, block3); + temp[3] = UnpackNEON<3>(block0, block1, block2, block3); + + LEA_Decryption(temp, subkeys, rounds); + + block0 = RepackNEON<0>(temp[0], temp[1], temp[2], temp[3]); + block1 = RepackNEON<1>(temp[0], temp[1], temp[2], temp[3]); + block2 = RepackNEON<2>(temp[0], temp[1], temp[2], temp[3]); + block3 = RepackNEON<3>(temp[0], temp[1], temp[2], temp[3]); +} + +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +// *************************** IA-32 ***************************// + +#if (CRYPTOPP_SSSE3_AVAILABLE) + +inline void LEA_Enc_Block(__m128i &block0, + const word32 *subkeys, unsigned int rounds) +{ + __m128i temp[4]; + temp[0] = UnpackXMM<0>(block0); + temp[1] = UnpackXMM<1>(block0); + temp[2] = UnpackXMM<2>(block0); + temp[3] = UnpackXMM<3>(block0); + + LEA_Encryption(temp, subkeys, rounds); + + block0 = RepackXMM<0>(temp[0], temp[1], temp[2], temp[3]); +} + +inline void LEA_Dec_Block(__m128i &block0, + const word32 *subkeys, unsigned int rounds) +{ + __m128i temp[4]; + temp[0] = UnpackXMM<0>(block0); + temp[1] = UnpackXMM<1>(block0); + temp[2] = UnpackXMM<2>(block0); + temp[3] = UnpackXMM<3>(block0); + + LEA_Decryption(temp, subkeys, rounds); + + block0 = RepackXMM<0>(temp[0], temp[1], temp[2], temp[3]); +} + +inline void LEA_Enc_4_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, const word32 *subkeys, unsigned int rounds) +{ + __m128i temp[4]; + temp[0] = UnpackXMM<0>(block0, block1, block2, block3); + temp[1] = UnpackXMM<1>(block0, block1, block2, block3); + temp[2] = UnpackXMM<2>(block0, block1, block2, block3); + temp[3] = UnpackXMM<3>(block0, block1, block2, block3); + + LEA_Encryption(temp, subkeys, rounds); + + block0 = RepackXMM<0>(temp[0], temp[1], temp[2], temp[3]); + block1 = RepackXMM<1>(temp[0], temp[1], temp[2], temp[3]); + block2 = RepackXMM<2>(temp[0], temp[1], temp[2], temp[3]); + block3 = RepackXMM<3>(temp[0], temp[1], temp[2], temp[3]); +} + +inline void LEA_Dec_4_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, const word32 *subkeys, unsigned int rounds) +{ + __m128i temp[4]; + temp[0] = UnpackXMM<0>(block0, block1, block2, block3); + temp[1] = UnpackXMM<1>(block0, block1, block2, block3); + temp[2] = UnpackXMM<2>(block0, block1, block2, block3); + temp[3] = UnpackXMM<3>(block0, block1, block2, block3); + + LEA_Decryption(temp, subkeys, rounds); + + block0 = RepackXMM<0>(temp[0], temp[1], temp[2], temp[3]); + block1 = RepackXMM<1>(temp[0], temp[1], temp[2], temp[3]); + block2 = RepackXMM<2>(temp[0], temp[1], temp[2], temp[3]); + block3 = RepackXMM<3>(temp[0], temp[1], temp[2], temp[3]); +} + +#endif // CRYPTOPP_SSSE3_AVAILABLE + +// *************************** Power8 ***************************// + +#if (CRYPTOPP_POWER8_AVAILABLE) + +inline void LEA_Enc_Block(uint32x4_p &block0, + const word32 *subkeys, unsigned int rounds) +{ + uint32x4_p temp[4]; + temp[0] = UnpackSIMD<0>(block0); + temp[1] = UnpackSIMD<1>(block0); + temp[2] = UnpackSIMD<2>(block0); + temp[3] = UnpackSIMD<3>(block0); + + LEA_Encryption(temp, subkeys, rounds); + + block0 = RepackSIMD<0>(temp[0], temp[1], temp[2], temp[3]); +} + +inline void LEA_Dec_Block(uint32x4_p &block0, + const word32 *subkeys, unsigned int rounds) +{ + uint32x4_p temp[4]; + temp[0] = UnpackSIMD<0>(block0); + temp[1] = UnpackSIMD<1>(block0); + temp[2] = UnpackSIMD<2>(block0); + temp[3] = UnpackSIMD<3>(block0); + + LEA_Decryption(temp, subkeys, rounds); + + block0 = RepackSIMD<0>(temp[0], temp[1], temp[2], temp[3]); +} + +inline void LEA_Enc_4_Blocks(uint32x4_p &block0, uint32x4_p &block1, + uint32x4_p &block2, uint32x4_p &block3, const word32 *subkeys, unsigned int rounds) +{ + uint32x4_p temp[4]; + temp[0] = UnpackSIMD<0>(block0, block1, block2, block3); + temp[1] = UnpackSIMD<1>(block0, block1, block2, block3); + temp[2] = UnpackSIMD<2>(block0, block1, block2, block3); + temp[3] = UnpackSIMD<3>(block0, block1, block2, block3); + + LEA_Encryption(temp, subkeys, rounds); + + block0 = RepackSIMD<0>(temp[0], temp[1], temp[2], temp[3]); + block1 = RepackSIMD<1>(temp[0], temp[1], temp[2], temp[3]); + block2 = RepackSIMD<2>(temp[0], temp[1], temp[2], temp[3]); + block3 = RepackSIMD<3>(temp[0], temp[1], temp[2], temp[3]); +} + +inline void LEA_Dec_4_Blocks(uint32x4_p &block0, uint32x4_p &block1, + uint32x4_p &block2, uint32x4_p &block3, const word32 *subkeys, unsigned int rounds) +{ + uint32x4_p temp[4]; + temp[0] = UnpackSIMD<0>(block0, block1, block2, block3); + temp[1] = UnpackSIMD<1>(block0, block1, block2, block3); + temp[2] = UnpackSIMD<2>(block0, block1, block2, block3); + temp[3] = UnpackSIMD<3>(block0, block1, block2, block3); + + LEA_Decryption(temp, subkeys, rounds); + + block0 = RepackSIMD<0>(temp[0], temp[1], temp[2], temp[3]); + block1 = RepackSIMD<1>(temp[0], temp[1], temp[2], temp[3]); + block2 = RepackSIMD<2>(temp[0], temp[1], temp[2], temp[3]); + block3 = RepackSIMD<3>(temp[0], temp[1], temp[2], temp[3]); +} + +#endif // CRYPTOPP_POWER8_AVAILABLE + +ANONYMOUS_NAMESPACE_END + +// *************************** SIMD Templates ***************************// + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_SSSE3_AVAILABLE) +size_t LEA_Enc_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_4x1_SSE(LEA_Enc_Block, LEA_Enc_4_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t LEA_Dec_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_4x1_SSE(LEA_Dec_Block, LEA_Dec_4_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_SSSE3_AVAILABLE + +#if defined(CRYPTOPP_ARM_NEON_AVAILABLE) +size_t LEA_Enc_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_4x1_NEON(LEA_Enc_Block, LEA_Enc_4_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t LEA_Dec_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_4x1_NEON(LEA_Dec_Block, LEA_Dec_4_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +#if defined(CRYPTOPP_POWER8_AVAILABLE) +size_t LEA_Enc_AdvancedProcessBlocks_POWER8(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_4x1_ALTIVEC(LEA_Enc_Block, LEA_Enc_4_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t LEA_Dec_AdvancedProcessBlocks_POWER8(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_4x1_ALTIVEC(LEA_Dec_Block, LEA_Dec_4_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_POWER8_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/lsh.h b/external/ours/library/crypto/src/shared/original/lsh.h new file mode 100755 index 000000000..2f9918d82 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/lsh256.cpp b/external/ours/library/crypto/src/shared/original/lsh256.cpp new file mode 100755 index 000000000..0f895bb40 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/lsh256.cpp @@ -0,0 +1,817 @@ +// lsh.cpp - 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. + +#include "pch.h" +#include "config.h" + +#include "lsh.h" +#include "cpu.h" +#include "misc.h" + +ANONYMOUS_NAMESPACE_BEGIN + +/* LSH Constants */ + +const unsigned int LSH256_MSG_BLK_BYTE_LEN = 128; +// const unsigned int LSH256_MSG_BLK_BIT_LEN = 1024; +// const unsigned int LSH256_CV_BYTE_LEN = 64; +const unsigned int LSH256_HASH_VAL_MAX_BYTE_LEN = 32; + +// const unsigned int MSG_BLK_WORD_LEN = 32; +const unsigned int CV_WORD_LEN = 16; +const unsigned int CONST_WORD_LEN = 8; +const unsigned int HASH_VAL_MAX_WORD_LEN = 8; +// const unsigned int WORD_BIT_LEN = 32; +const unsigned int NUM_STEPS = 26; + +const unsigned int ROT_EVEN_ALPHA = 29; +const unsigned int ROT_EVEN_BETA = 1; +const unsigned int ROT_ODD_ALPHA = 5; +const unsigned int ROT_ODD_BETA = 17; + +const unsigned int LSH_TYPE_256_256 = 0x0000020; +const unsigned int LSH_TYPE_256_224 = 0x000001C; + +// const unsigned int LSH_TYPE_224 = LSH_TYPE_256_224; +// const unsigned int LSH_TYPE_256 = LSH_TYPE_256_256; + +/* Error Code */ + +const unsigned int LSH_SUCCESS = 0x0; +// const unsigned int LSH_ERR_NULL_PTR = 0x2401; +// const unsigned int LSH_ERR_INVALID_ALGTYPE = 0x2402; +const unsigned int LSH_ERR_INVALID_DATABITLEN = 0x2403; +const unsigned int LSH_ERR_INVALID_STATE = 0x2404; + +/* Index into our state array */ + +const unsigned int AlgorithmType = 80; +const unsigned int RemainingBits = 81; + +NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(LSH) + +/* -------------------------------------------------------- * +* LSH: iv +* -------------------------------------------------------- */ + +//extern const word32 LSH256_IV224[CV_WORD_LEN]; +//extern const word32 LSH256_IV256[CV_WORD_LEN]; +//extern const word32 LSH256_StepConstants[CONST_WORD_LEN * NUM_STEPS]; + +CRYPTOPP_ALIGN_DATA(32) +extern +const word32 LSH256_IV224[CV_WORD_LEN] = { + 0x068608D3, 0x62D8F7A7, 0xD76652AB, 0x4C600A43, 0xBDC40AA8, 0x1ECA0B68, 0xDA1A89BE, 0x3147D354, + 0x707EB4F9, 0xF65B3862, 0x6B0B2ABE, 0x56B8EC0A, 0xCF237286, 0xEE0D1727, 0x33636595, 0x8BB8D05F +}; + +CRYPTOPP_ALIGN_DATA(32) +extern +const word32 LSH256_IV256[CV_WORD_LEN] = { + 0x46a10f1f, 0xfddce486, 0xb41443a8, 0x198e6b9d, 0x3304388d, 0xb0f5a3c7, 0xb36061c4, 0x7adbd553, + 0x105d5378, 0x2f74de54, 0x5c2f2d95, 0xf2553fbe, 0x8051357a, 0x138668c8, 0x47aa4484, 0xe01afb41 +}; + +/* -------------------------------------------------------- * +* LSH: step constants +* -------------------------------------------------------- */ + +extern +const word32 LSH256_StepConstants[CONST_WORD_LEN * NUM_STEPS] = { + 0x917caf90, 0x6c1b10a2, 0x6f352943, 0xcf778243, 0x2ceb7472, 0x29e96ff2, 0x8a9ba428, 0x2eeb2642, + 0x0e2c4021, 0x872bb30e, 0xa45e6cb2, 0x46f9c612, 0x185fe69e, 0x1359621b, 0x263fccb2, 0x1a116870, + 0x3a6c612f, 0xb2dec195, 0x02cb1f56, 0x40bfd858, 0x784684b6, 0x6cbb7d2e, 0x660c7ed8, 0x2b79d88a, + 0xa6cd9069, 0x91a05747, 0xcdea7558, 0x00983098, 0xbecb3b2e, 0x2838ab9a, 0x728b573e, 0xa55262b5, + 0x745dfa0f, 0x31f79ed8, 0xb85fce25, 0x98c8c898, 0x8a0669ec, 0x60e445c2, 0xfde295b0, 0xf7b5185a, + 0xd2580983, 0x29967709, 0x182df3dd, 0x61916130, 0x90705676, 0x452a0822, 0xe07846ad, 0xaccd7351, + 0x2a618d55, 0xc00d8032, 0x4621d0f5, 0xf2f29191, 0x00c6cd06, 0x6f322a67, 0x58bef48d, 0x7a40c4fd, + 0x8beee27f, 0xcd8db2f2, 0x67f2c63b, 0xe5842383, 0xc793d306, 0xa15c91d6, 0x17b381e5, 0xbb05c277, + 0x7ad1620a, 0x5b40a5bf, 0x5ab901a2, 0x69a7a768, 0x5b66d9cd, 0xfdee6877, 0xcb3566fc, 0xc0c83a32, + 0x4c336c84, 0x9be6651a, 0x13baa3fc, 0x114f0fd1, 0xc240a728, 0xec56e074, 0x009c63c7, 0x89026cf2, + 0x7f9ff0d0, 0x824b7fb5, 0xce5ea00f, 0x605ee0e2, 0x02e7cfea, 0x43375560, 0x9d002ac7, 0x8b6f5f7b, + 0x1f90c14f, 0xcdcb3537, 0x2cfeafdd, 0xbf3fc342, 0xeab7b9ec, 0x7a8cb5a3, 0x9d2af264, 0xfacedb06, + 0xb052106e, 0x99006d04, 0x2bae8d09, 0xff030601, 0xa271a6d6, 0x0742591d, 0xc81d5701, 0xc9a9e200, + 0x02627f1e, 0x996d719d, 0xda3b9634, 0x02090800, 0x14187d78, 0x499b7624, 0xe57458c9, 0x738be2c9, + 0x64e19d20, 0x06df0f36, 0x15d1cb0e, 0x0b110802, 0x2c95f58c, 0xe5119a6d, 0x59cd22ae, 0xff6eac3c, + 0x467ebd84, 0xe5ee453c, 0xe79cd923, 0x1c190a0d, 0xc28b81b8, 0xf6ac0852, 0x26efd107, 0x6e1ae93b, + 0xc53c41ca, 0xd4338221, 0x8475fd0a, 0x35231729, 0x4e0d3a7a, 0xa2b45b48, 0x16c0d82d, 0x890424a9, + 0x017e0c8f, 0x07b5a3f5, 0xfa73078e, 0x583a405e, 0x5b47b4c8, 0x570fa3ea, 0xd7990543, 0x8d28ce32, + 0x7f8a9b90, 0xbd5998fc, 0x6d7a9688, 0x927a9eb6, 0xa2fc7d23, 0x66b38e41, 0x709e491a, 0xb5f700bf, + 0x0a262c0f, 0x16f295b9, 0xe8111ef5, 0x0d195548, 0x9f79a0c5, 0x1a41cfa7, 0x0ee7638a, 0xacf7c074, + 0x30523b19, 0x09884ecf, 0xf93014dd, 0x266e9d55, 0x191a6664, 0x5c1176c1, 0xf64aed98, 0xa4b83520, + 0x828d5449, 0x91d71dd8, 0x2944f2d6, 0x950bf27b, 0x3380ca7d, 0x6d88381d, 0x4138868e, 0x5ced55c4, + 0x0fe19dcb, 0x68f4f669, 0x6e37c8ff, 0xa0fe6e10, 0xb44b47b0, 0xf5c0558a, 0x79bf14cf, 0x4a431a20, + 0xf17f68da, 0x5deb5fd1, 0xa600c86d, 0x9f6c7eb0, 0xff92f864, 0xb615e07f, 0x38d3e448, 0x8d5d3a6a, + 0x70e843cb, 0x494b312e, 0xa6c93613, 0x0beb2f4f, 0x928b5d63, 0xcbf66035, 0x0cb82c80, 0xea97a4f7, + 0x592c0f3b, 0x947c5f77, 0x6fff49b9, 0xf71a7e5a, 0x1de8c0f5, 0xc2569600, 0xc4e4ac8c, 0x823c9ce1 +}; + +NAMESPACE_END // LSH +NAMESPACE_END // Crypto++ + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::rotlFixed; +using CryptoPP::rotlConstant; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; +using CryptoPP::ConditionalByteReverse; +using CryptoPP::LITTLE_ENDIAN_ORDER; + +using CryptoPP::LSH::LSH256_IV224; +using CryptoPP::LSH::LSH256_IV256; +using CryptoPP::LSH::LSH256_StepConstants; + +typedef byte lsh_u8; +typedef word32 lsh_u32; +typedef word32 lsh_uint; +typedef word32 lsh_err; +typedef word32 lsh_type; + +struct LSH256_Context +{ + LSH256_Context(word32* state, word32 algType, word32& remainingBitLength) : + cv_l(state+0), cv_r(state+8), sub_msgs(state+16), + last_block(reinterpret_cast(state+48)), + remain_databitlen(remainingBitLength), + alg_type(static_cast(algType)) {} + + lsh_u32* cv_l; // start of our state block + lsh_u32* cv_r; + lsh_u32* sub_msgs; + lsh_u8* last_block; + lsh_u32& remain_databitlen; + lsh_type alg_type; +}; + +struct LSH256_Internal +{ + LSH256_Internal(word32* state) : + submsg_e_l(state+16), submsg_e_r(state+24), + submsg_o_l(state+32), submsg_o_r(state+40) { } + + lsh_u32* submsg_e_l; /* even left sub-message */ + lsh_u32* submsg_e_r; /* even right sub-message */ + lsh_u32* submsg_o_l; /* odd left sub-message */ + lsh_u32* submsg_o_r; /* odd right sub-message */ +}; + +const word32 g_gamma256[8] = { 0, 8, 16, 24, 24, 16, 8, 0 }; + +/* LSH AlgType Macro */ + +inline bool LSH_IS_LSH512(lsh_uint val) { + return (val & 0xf0000) == 0; +} + +inline lsh_uint LSH_GET_SMALL_HASHBIT(lsh_uint val) { + return val >> 24; +} + +inline lsh_uint LSH_GET_HASHBYTE(lsh_uint val) { + return val & 0xffff; +} + +inline lsh_uint LSH_GET_HASHBIT(lsh_uint val) { + return (LSH_GET_HASHBYTE(val) << 3) - LSH_GET_SMALL_HASHBIT(val); +} + +inline lsh_u32 loadLE32(lsh_u32 v) { + return ConditionalByteReverse(LITTLE_ENDIAN_ORDER, v); +} + +lsh_u32 ROTL(lsh_u32 x, lsh_u32 r) { + return rotlFixed(x, r); +} + +// Original code relied upon unaligned lsh_u32 buffer +inline void load_msg_blk(LSH256_Internal* i_state, const lsh_u8 msgblk[LSH256_MSG_BLK_BYTE_LEN]) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + typedef GetBlock InBlock; + + InBlock input(msgblk); + input(submsg_e_l[0])(submsg_e_l[1])(submsg_e_l[2])(submsg_e_l[3]) + (submsg_e_l[4])(submsg_e_l[5])(submsg_e_l[6])(submsg_e_l[7]) + (submsg_e_r[0])(submsg_e_r[1])(submsg_e_r[2])(submsg_e_r[3]) + (submsg_e_r[4])(submsg_e_r[5])(submsg_e_r[6])(submsg_e_r[7]) + (submsg_o_l[0])(submsg_o_l[1])(submsg_o_l[2])(submsg_o_l[3]) + (submsg_o_l[4])(submsg_o_l[5])(submsg_o_l[6])(submsg_o_l[7]) + (submsg_o_r[0])(submsg_o_r[1])(submsg_o_r[2])(submsg_o_r[3]) + (submsg_o_r[4])(submsg_o_r[5])(submsg_o_r[6])(submsg_o_r[7]); +} + +inline void msg_exp_even(LSH256_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + lsh_u32 temp; + temp = submsg_e_l[0]; + submsg_e_l[0] = submsg_o_l[0] + submsg_e_l[3]; + submsg_e_l[3] = submsg_o_l[3] + submsg_e_l[1]; + submsg_e_l[1] = submsg_o_l[1] + submsg_e_l[2]; + submsg_e_l[2] = submsg_o_l[2] + temp; + temp = submsg_e_l[4]; + submsg_e_l[4] = submsg_o_l[4] + submsg_e_l[7]; + submsg_e_l[7] = submsg_o_l[7] + submsg_e_l[6]; + submsg_e_l[6] = submsg_o_l[6] + submsg_e_l[5]; + submsg_e_l[5] = submsg_o_l[5] + temp; + temp = submsg_e_r[0]; + submsg_e_r[0] = submsg_o_r[0] + submsg_e_r[3]; + submsg_e_r[3] = submsg_o_r[3] + submsg_e_r[1]; + submsg_e_r[1] = submsg_o_r[1] + submsg_e_r[2]; + submsg_e_r[2] = submsg_o_r[2] + temp; + temp = submsg_e_r[4]; + submsg_e_r[4] = submsg_o_r[4] + submsg_e_r[7]; + submsg_e_r[7] = submsg_o_r[7] + submsg_e_r[6]; + submsg_e_r[6] = submsg_o_r[6] + submsg_e_r[5]; + submsg_e_r[5] = submsg_o_r[5] + temp; +} + +inline void msg_exp_odd(LSH256_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + lsh_u32 temp; + temp = submsg_o_l[0]; + submsg_o_l[0] = submsg_e_l[0] + submsg_o_l[3]; + submsg_o_l[3] = submsg_e_l[3] + submsg_o_l[1]; + submsg_o_l[1] = submsg_e_l[1] + submsg_o_l[2]; + submsg_o_l[2] = submsg_e_l[2] + temp; + temp = submsg_o_l[4]; + submsg_o_l[4] = submsg_e_l[4] + submsg_o_l[7]; + submsg_o_l[7] = submsg_e_l[7] + submsg_o_l[6]; + submsg_o_l[6] = submsg_e_l[6] + submsg_o_l[5]; + submsg_o_l[5] = submsg_e_l[5] + temp; + temp = submsg_o_r[0]; + submsg_o_r[0] = submsg_e_r[0] + submsg_o_r[3]; + submsg_o_r[3] = submsg_e_r[3] + submsg_o_r[1]; + submsg_o_r[1] = submsg_e_r[1] + submsg_o_r[2]; + submsg_o_r[2] = submsg_e_r[2] + temp; + temp = submsg_o_r[4]; + submsg_o_r[4] = submsg_e_r[4] + submsg_o_r[7]; + submsg_o_r[7] = submsg_e_r[7] + submsg_o_r[6]; + submsg_o_r[6] = submsg_e_r[6] + submsg_o_r[5]; + submsg_o_r[5] = submsg_e_r[5] + temp; +} + +inline void load_sc(const lsh_u32** p_const_v, size_t i) +{ + CRYPTOPP_ASSERT(p_const_v != NULLPTR); + + *p_const_v = &LSH256_StepConstants[i]; +} + +inline void msg_add_even(lsh_u32 cv_l[8], lsh_u32 cv_r[8], LSH256_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + + cv_l[0] ^= submsg_e_l[0]; cv_l[1] ^= submsg_e_l[1]; + cv_l[2] ^= submsg_e_l[2]; cv_l[3] ^= submsg_e_l[3]; + cv_l[4] ^= submsg_e_l[4]; cv_l[5] ^= submsg_e_l[5]; + cv_l[6] ^= submsg_e_l[6]; cv_l[7] ^= submsg_e_l[7]; + cv_r[0] ^= submsg_e_r[0]; cv_r[1] ^= submsg_e_r[1]; + cv_r[2] ^= submsg_e_r[2]; cv_r[3] ^= submsg_e_r[3]; + cv_r[4] ^= submsg_e_r[4]; cv_r[5] ^= submsg_e_r[5]; + cv_r[6] ^= submsg_e_r[6]; cv_r[7] ^= submsg_e_r[7]; +} + +inline void msg_add_odd(lsh_u32 cv_l[8], lsh_u32 cv_r[8], LSH256_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + cv_l[0] ^= submsg_o_l[0]; cv_l[1] ^= submsg_o_l[1]; + cv_l[2] ^= submsg_o_l[2]; cv_l[3] ^= submsg_o_l[3]; + cv_l[4] ^= submsg_o_l[4]; cv_l[5] ^= submsg_o_l[5]; + cv_l[6] ^= submsg_o_l[6]; cv_l[7] ^= submsg_o_l[7]; + cv_r[0] ^= submsg_o_r[0]; cv_r[1] ^= submsg_o_r[1]; + cv_r[2] ^= submsg_o_r[2]; cv_r[3] ^= submsg_o_r[3]; + cv_r[4] ^= submsg_o_r[4]; cv_r[5] ^= submsg_o_r[5]; + cv_r[6] ^= submsg_o_r[6]; cv_r[7] ^= submsg_o_r[7]; +} + +inline void add_blk(lsh_u32 cv_l[8], lsh_u32 cv_r[8]) +{ + cv_l[0] += cv_r[0]; + cv_l[1] += cv_r[1]; + cv_l[2] += cv_r[2]; + cv_l[3] += cv_r[3]; + cv_l[4] += cv_r[4]; + cv_l[5] += cv_r[5]; + cv_l[6] += cv_r[6]; + cv_l[7] += cv_r[7]; +} + +template +inline void rotate_blk(lsh_u32 cv[8]) +{ + cv[0] = rotlConstant(cv[0]); + cv[1] = rotlConstant(cv[1]); + cv[2] = rotlConstant(cv[2]); + cv[3] = rotlConstant(cv[3]); + cv[4] = rotlConstant(cv[4]); + cv[5] = rotlConstant(cv[5]); + cv[6] = rotlConstant(cv[6]); + cv[7] = rotlConstant(cv[7]); +} + +inline void xor_with_const(lsh_u32 cv_l[8], const lsh_u32 const_v[8]) +{ + cv_l[0] ^= const_v[0]; + cv_l[1] ^= const_v[1]; + cv_l[2] ^= const_v[2]; + cv_l[3] ^= const_v[3]; + cv_l[4] ^= const_v[4]; + cv_l[5] ^= const_v[5]; + cv_l[6] ^= const_v[6]; + cv_l[7] ^= const_v[7]; +} + +inline void rotate_msg_gamma(lsh_u32 cv_r[8]) +{ + cv_r[1] = rotlFixed(cv_r[1], g_gamma256[1]); + cv_r[2] = rotlFixed(cv_r[2], g_gamma256[2]); + cv_r[3] = rotlFixed(cv_r[3], g_gamma256[3]); + cv_r[4] = rotlFixed(cv_r[4], g_gamma256[4]); + cv_r[5] = rotlFixed(cv_r[5], g_gamma256[5]); + cv_r[6] = rotlFixed(cv_r[6], g_gamma256[6]); +} + +inline void word_perm(lsh_u32 cv_l[8], lsh_u32 cv_r[8]) +{ + lsh_u32 temp; + temp = cv_l[0]; + cv_l[0] = cv_l[6]; + cv_l[6] = cv_r[6]; + cv_r[6] = cv_r[2]; + cv_r[2] = cv_l[1]; + cv_l[1] = cv_l[4]; + cv_l[4] = cv_r[4]; + cv_r[4] = cv_r[0]; + cv_r[0] = cv_l[2]; + cv_l[2] = cv_l[5]; + cv_l[5] = cv_r[7]; + cv_r[7] = cv_r[1]; + cv_r[1] = temp; + temp = cv_l[3]; + cv_l[3] = cv_l[7]; + cv_l[7] = cv_r[5]; + cv_r[5] = cv_r[3]; + cv_r[3] = temp; +}; + +/* -------------------------------------------------------- * +* step function +* -------------------------------------------------------- */ + +template +inline void mix(lsh_u32 cv_l[8], lsh_u32 cv_r[8], const lsh_u32 const_v[8]) +{ + add_blk(cv_l, cv_r); + rotate_blk(cv_l); + xor_with_const(cv_l, const_v); + add_blk(cv_r, cv_l); + rotate_blk(cv_r); + add_blk(cv_l, cv_r); + rotate_msg_gamma(cv_r); +} + +/* -------------------------------------------------------- * +* compression function +* -------------------------------------------------------- */ + +inline void compress(LSH256_Context* ctx, const lsh_u8 pdMsgBlk[LSH256_MSG_BLK_BYTE_LEN]) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + LSH256_Internal s_state(ctx->cv_l); + LSH256_Internal* i_state = &s_state; + + const lsh_u32* const_v = NULL; + lsh_u32* cv_l = ctx->cv_l; + lsh_u32* cv_r = ctx->cv_r; + + load_msg_blk(i_state, pdMsgBlk); + + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 0); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + for (size_t i = 1; i < NUM_STEPS / 2; i++) + { + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_exp_odd(i_state); + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); +} + +/* -------------------------------------------------------- */ + +inline void load_iv(lsh_u32 cv_l[8], lsh_u32 cv_r[8], const lsh_u32 iv[16]) +{ + cv_l[0] = iv[0]; + cv_l[1] = iv[1]; + cv_l[2] = iv[2]; + cv_l[3] = iv[3]; + cv_l[4] = iv[4]; + cv_l[5] = iv[5]; + cv_l[6] = iv[6]; + cv_l[7] = iv[7]; + cv_r[0] = iv[8]; + cv_r[1] = iv[9]; + cv_r[2] = iv[10]; + cv_r[3] = iv[11]; + cv_r[4] = iv[12]; + cv_r[5] = iv[13]; + cv_r[6] = iv[14]; + cv_r[7] = iv[15]; +} + +inline void zero_iv(lsh_u32 cv_l[8], lsh_u32 cv_r[8]) +{ + memset(cv_l, 0x00, 8*sizeof(lsh_u32)); + memset(cv_r, 0x00, 8*sizeof(lsh_u32)); +} + +inline void zero_submsgs(LSH256_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + lsh_u32* sub_msgs = ctx->sub_msgs; + memset(sub_msgs, 0x00, 32*sizeof(lsh_u32)); +} + +inline void init224(LSH256_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH256_IV224); +} + +inline void init256(LSH256_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH256_IV256); +} + +/* -------------------------------------------------------- */ + +inline void fin(LSH256_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + for (size_t i = 0; i < HASH_VAL_MAX_WORD_LEN; i++){ + ctx->cv_l[i] = loadLE32(ctx->cv_l[i] ^ ctx->cv_r[i]); + } +} + +/* -------------------------------------------------------- */ + +inline void get_hash(LSH256_Context* ctx, lsh_u8* pbHashVal) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + CRYPTOPP_ASSERT(pbHashVal != NULLPTR); + + lsh_uint alg_type = ctx->alg_type; + lsh_uint hash_val_byte_len = LSH_GET_HASHBYTE(alg_type); + lsh_uint hash_val_bit_len = LSH_GET_SMALL_HASHBIT(alg_type); + + // Multiplying by looks odd... + memcpy(pbHashVal, ctx->cv_l, hash_val_byte_len); + if (hash_val_bit_len){ + pbHashVal[hash_val_byte_len-1] &= (((lsh_u8)0xff) << hash_val_bit_len); + } +} + +/* -------------------------------------------------------- */ + +lsh_err lsh256_init(LSH256_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + lsh_u32 alg_type = ctx->alg_type; + const lsh_u32* const_v = NULL; + ctx->remain_databitlen = 0; + + switch (alg_type) + { + case LSH_TYPE_256_256: + init256(ctx); + return LSH_SUCCESS; + case LSH_TYPE_256_224: + init224(ctx); + return LSH_SUCCESS; + default: + break; + } + + lsh_u32* cv_l = ctx->cv_l; + lsh_u32* cv_r = ctx->cv_r; + + zero_iv(cv_l, cv_r); + cv_l[0] = LSH256_HASH_VAL_MAX_BYTE_LEN; + cv_l[1] = LSH_GET_HASHBIT(alg_type); + + for (size_t i = 0; i < NUM_STEPS / 2; i++) + { + //Mix + load_sc(&const_v, i * 16); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + load_sc(&const_v, i * 16 + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + return LSH_SUCCESS; +} + +lsh_err lsh256_update(LSH256_Context* ctx, const lsh_u8* data, size_t databitlen) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(data != NULLPTR); + CRYPTOPP_ASSERT(databitlen % 8 == 0); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + if (databitlen == 0){ + return LSH_SUCCESS; + } + + // We are byte oriented. tail bits will always be 0. + size_t databytelen = databitlen >> 3; + // lsh_uint pos2 = databitlen & 0x7; + const size_t pos2 = 0; + + size_t remain_msg_byte = ctx->remain_databitlen >> 3; + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH256_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + if (remain_msg_bit > 0){ + return LSH_ERR_INVALID_DATABITLEN; + } + + if (databytelen + remain_msg_byte < LSH256_MSG_BLK_BYTE_LEN) + { + memcpy(ctx->last_block + remain_msg_byte, data, databytelen); + ctx->remain_databitlen += (lsh_uint)databitlen; + remain_msg_byte += (lsh_uint)databytelen; + if (pos2){ + ctx->last_block[remain_msg_byte] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + } + return LSH_SUCCESS; + } + + if (remain_msg_byte > 0){ + size_t more_byte = LSH256_MSG_BLK_BYTE_LEN - remain_msg_byte; + memcpy(ctx->last_block + remain_msg_byte, data, more_byte); + compress(ctx, ctx->last_block); + data += more_byte; + databytelen -= more_byte; + remain_msg_byte = 0; + ctx->remain_databitlen = 0; + } + + while (databytelen >= LSH256_MSG_BLK_BYTE_LEN) + { + // This call to compress caused some trouble. + // The data pointer can become unaligned in the + // previous block. + compress(ctx, data); + data += LSH256_MSG_BLK_BYTE_LEN; + databytelen -= LSH256_MSG_BLK_BYTE_LEN; + } + + if (databytelen > 0){ + memcpy(ctx->last_block, data, databytelen); + ctx->remain_databitlen = (lsh_uint)(databytelen << 3); + } + + if (pos2){ + ctx->last_block[databytelen] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + ctx->remain_databitlen += pos2; + } + + return LSH_SUCCESS; +} + +lsh_err lsh256_final(LSH256_Context* ctx, lsh_u8* hashval) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(hashval != NULLPTR); + + // We are byte oriented. tail bits will always be 0. + size_t remain_msg_byte = ctx->remain_databitlen >> 3; + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH256_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + + if (remain_msg_bit){ + ctx->last_block[remain_msg_byte] |= (0x1 << (7 - remain_msg_bit)); + } + else{ + ctx->last_block[remain_msg_byte] = 0x80; + } + memset(ctx->last_block + remain_msg_byte + 1, 0, LSH256_MSG_BLK_BYTE_LEN - remain_msg_byte - 1); + + compress(ctx, ctx->last_block); + + fin(ctx); + get_hash(ctx, hashval); + + return LSH_SUCCESS; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_ENABLE_64BIT_SSE) +# if defined(CRYPTOPP_AVX2_AVAILABLE) + extern void LSH256_Base_Restart_AVX2(word32* state); + extern void LSH256_Base_Update_AVX2(word32* state, const byte *input, size_t size); + extern void LSH256_Base_TruncatedFinal_AVX2(word32* state, byte *hash, size_t size); +# endif +# if defined(CRYPTOPP_SSSE3_AVAILABLE) + extern void LSH256_Base_Restart_SSSE3(word32* state); + extern void LSH256_Base_Update_SSSE3(word32* state, const byte *input, size_t size); + extern void LSH256_Base_TruncatedFinal_SSSE3(word32* state, byte *hash, size_t size); +# endif +#endif + +void LSH256_Base_Restart_CXX(word32* state) +{ + state[RemainingBits] = 0; + LSH256_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh256_init(&ctx); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_init failed"); +} + +void LSH256_Base_Update_CXX(word32* state, const byte *input, size_t size) +{ + LSH256_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh256_update(&ctx, input, 8*size); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_update failed"); +} + +void LSH256_Base_TruncatedFinal_CXX(word32* state, byte *hash, size_t) +{ + LSH256_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh256_final(&ctx, hash); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_final failed"); +} + +std::string LSH256_Base::AlgorithmProvider() const +{ +#if defined(CRYPTOPP_ENABLE_64BIT_SSE) +#if defined(CRYPTOPP_AVX2_AVAILABLE) + if (HasAVX2()) + return "AVX2"; + else +#endif +#if defined(CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return "SSSE3"; + else +#endif +#endif // CRYPTOPP_ENABLE_64BIT_SSE + + return "C++"; +} + +void LSH256_Base::Restart() +{ +#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasAVX2()) + LSH256_Base_Restart_AVX2(m_state); + else +#endif +#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasSSSE3()) + LSH256_Base_Restart_SSSE3(m_state); + else +#endif + + LSH256_Base_Restart_CXX(m_state); +} + +void LSH256_Base::Update(const byte *input, size_t size) +{ + CRYPTOPP_ASSERT(input != NULLPTR); + CRYPTOPP_ASSERT(size); + +#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasAVX2()) + LSH256_Base_Update_AVX2(m_state, input, size); + else +#endif +#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasSSSE3()) + LSH256_Base_Update_SSSE3(m_state, input, size); + else +#endif + + LSH256_Base_Update_CXX(m_state, input, size); +} + +void LSH256_Base::TruncatedFinal(byte *hash, size_t size) +{ + CRYPTOPP_ASSERT(hash != NULLPTR); + ThrowIfInvalidTruncatedSize(size); + + // TODO: determine if LSH256 supports truncated hashes. See the code + // in get_hash(), where a bit-length is added to the last output + // byte of the hash function. + byte fullHash[LSH256_HASH_VAL_MAX_BYTE_LEN]; + bool copyOut = (size < DigestSize()); + +#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasAVX2()) + LSH256_Base_TruncatedFinal_AVX2(m_state, copyOut ? fullHash : hash, size); + else +#endif +#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasSSSE3()) + LSH256_Base_TruncatedFinal_SSSE3(m_state, copyOut ? fullHash : hash, size); + else +#endif + + LSH256_Base_TruncatedFinal_CXX(m_state, copyOut ? fullHash : hash, size); + + if (copyOut) + memcpy(hash, fullHash, size); + + Restart(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/lsh256_avx.cpp b/external/ours/library/crypto/src/shared/original/lsh256_avx.cpp new file mode 100755 index 000000000..a8c0ef23c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/lsh256_avx.cpp @@ -0,0 +1,648 @@ +// lsh.cpp - 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. + +#include "pch.h" +#include "config.h" + +#include "lsh.h" +#include "misc.h" + +#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + +#if defined(CRYPTOPP_AVX2_AVAILABLE) +# include +# include +#endif + +// GCC at 4.5. Clang is unknown. Also see https://stackoverflow.com/a/42493893. +#if (CRYPTOPP_GCC_VERSION >= 40500) +# include +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +/* LSH Constants */ + +const unsigned int LSH256_MSG_BLK_BYTE_LEN = 128; +// const unsigned int LSH256_MSG_BLK_BIT_LEN = 1024; +// const unsigned int LSH256_CV_BYTE_LEN = 64; +const unsigned int LSH256_HASH_VAL_MAX_BYTE_LEN = 32; + +// const unsigned int MSG_BLK_WORD_LEN = 32; +const unsigned int CV_WORD_LEN = 16; +const unsigned int CONST_WORD_LEN = 8; +// const unsigned int HASH_VAL_MAX_WORD_LEN = 8; +// const unsigned int WORD_BIT_LEN = 32; +const unsigned int NUM_STEPS = 26; + +const unsigned int ROT_EVEN_ALPHA = 29; +const unsigned int ROT_EVEN_BETA = 1; +const unsigned int ROT_ODD_ALPHA = 5; +const unsigned int ROT_ODD_BETA = 17; + +const unsigned int LSH_TYPE_256_256 = 0x0000020; +const unsigned int LSH_TYPE_256_224 = 0x000001C; + +// const unsigned int LSH_TYPE_224 = LSH_TYPE_256_224; +// const unsigned int LSH_TYPE_256 = LSH_TYPE_256_256; + +/* Error Code */ + +const unsigned int LSH_SUCCESS = 0x0; +// const unsigned int LSH_ERR_NULL_PTR = 0x2401; +// const unsigned int LSH_ERR_INVALID_ALGTYPE = 0x2402; +const unsigned int LSH_ERR_INVALID_DATABITLEN = 0x2403; +const unsigned int LSH_ERR_INVALID_STATE = 0x2404; + +/* Index into our state array */ + +const unsigned int AlgorithmType = 80; +const unsigned int RemainingBits = 81; + +NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(LSH) + +// lsh256.cpp +extern const word32 LSH256_IV224[CV_WORD_LEN]; +extern const word32 LSH256_IV256[CV_WORD_LEN]; +extern const word32 LSH256_StepConstants[CONST_WORD_LEN * NUM_STEPS]; + +NAMESPACE_END // LSH +NAMESPACE_END // Crypto++ + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::rotlFixed; +using CryptoPP::rotlConstant; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; +using CryptoPP::ConditionalByteReverse; +using CryptoPP::LITTLE_ENDIAN_ORDER; + +typedef byte lsh_u8; +typedef word32 lsh_u32; +typedef word32 lsh_uint; +typedef word32 lsh_err; +typedef word32 lsh_type; + +using CryptoPP::LSH::LSH256_IV224; +using CryptoPP::LSH::LSH256_IV256; +using CryptoPP::LSH::LSH256_StepConstants; + +struct LSH256_AVX2_Context +{ + LSH256_AVX2_Context(word32* state, word32 algType, word32& remainingBitLength) : + cv_l(state+0), cv_r(state+8), sub_msgs(state+16), + last_block(reinterpret_cast(state+48)), + remain_databitlen(remainingBitLength), + alg_type(static_cast(algType)) {} + + lsh_u32* cv_l; // start of our state block + lsh_u32* cv_r; + lsh_u32* sub_msgs; + lsh_u8* last_block; + lsh_u32& remain_databitlen; + lsh_type alg_type; +}; + +struct LSH256_AVX2_Internal +{ + LSH256_AVX2_Internal(word32* state) : + submsg_e_l(state+16), submsg_e_r(state+24), + submsg_o_l(state+32), submsg_o_r(state+40) { } + + lsh_u32* submsg_e_l; /* even left sub-message */ + lsh_u32* submsg_e_r; /* even right sub-message */ + lsh_u32* submsg_o_l; /* odd left sub-message */ + lsh_u32* submsg_o_r; /* odd right sub-message */ +}; + +// Zero the upper 128 bits of all YMM registers on exit. +// It avoids AVX state transition penalties when saving state. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735 +// makes using zeroupper a little tricky. + +struct AVX_Cleanup +{ + ~AVX_Cleanup() { + _mm256_zeroupper(); + } +}; + +// const word32 g_gamma256[8] = { 0, 8, 16, 24, 24, 16, 8, 0 }; + +/* LSH AlgType Macro */ + +inline bool LSH_IS_LSH512(lsh_uint val) { + return (val & 0xf0000) == 0; +} + +inline lsh_uint LSH_GET_SMALL_HASHBIT(lsh_uint val) { + return val >> 24; +} + +inline lsh_uint LSH_GET_HASHBYTE(lsh_uint val) { + return val & 0xffff; +} + +inline lsh_uint LSH_GET_HASHBIT(lsh_uint val) { + return (LSH_GET_HASHBYTE(val) << 3) - LSH_GET_SMALL_HASHBIT(val); +} + +inline lsh_u32 loadLE32(lsh_u32 v) { + return ConditionalByteReverse(LITTLE_ENDIAN_ORDER, v); +} + +lsh_u32 ROTL(lsh_u32 x, lsh_u32 r) { + return rotlFixed(x, r); +} + +// Original code relied upon unaligned lsh_u32 buffer +inline void load_msg_blk(LSH256_AVX2_Internal* i_state, const lsh_u8 msgblk[LSH256_MSG_BLK_BYTE_LEN]) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + _mm256_storeu_si256(M256_CAST(submsg_e_l+0), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+0))); + _mm256_storeu_si256(M256_CAST(submsg_e_r+0), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+32))); + _mm256_storeu_si256(M256_CAST(submsg_o_l+0), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+64))); + _mm256_storeu_si256(M256_CAST(submsg_o_r+0), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+96))); +} + +inline void msg_exp_even(LSH256_AVX2_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + const __m256i mask = _mm256_set_epi32(0x1b1a1918, 0x17161514, + 0x13121110, 0x1f1e1d1c, 0x07060504, 0x03020100, 0x0b0a0908, 0x0f0e0d0c); + + _mm256_storeu_si256(M256_CAST(submsg_e_l+0), _mm256_add_epi32( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_l+0)), + _mm256_shuffle_epi8( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_l+0)), mask))); + _mm256_storeu_si256(M256_CAST(submsg_e_r+0), _mm256_add_epi32( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_r+0)), + _mm256_shuffle_epi8( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_r+0)), mask))); +} + +inline void msg_exp_odd(LSH256_AVX2_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + const __m256i mask = _mm256_set_epi32(0x1b1a1918, 0x17161514, + 0x13121110, 0x1f1e1d1c, 0x07060504, 0x03020100, 0x0b0a0908, 0x0f0e0d0c); + + _mm256_storeu_si256(M256_CAST(submsg_o_l+0), _mm256_add_epi32( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_l+0)), + _mm256_shuffle_epi8( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_l+0)), mask))); + _mm256_storeu_si256(M256_CAST(submsg_o_r+0), _mm256_add_epi32( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_r+0)), + _mm256_shuffle_epi8( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_r+0)), mask))); +} + +inline void load_sc(const lsh_u32** p_const_v, size_t i) +{ + CRYPTOPP_ASSERT(p_const_v != NULLPTR); + + *p_const_v = &LSH256_StepConstants[i]; +} + +inline void msg_add_even(lsh_u32 cv_l[8], lsh_u32 cv_r[8], LSH256_AVX2_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + + _mm256_storeu_si256(M256_CAST(cv_l+0), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_l+0)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_l+0)))); + _mm256_storeu_si256(M256_CAST(cv_r+0), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_r+0)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_r+0)))); +} + +inline void msg_add_odd(lsh_u32 cv_l[8], lsh_u32 cv_r[8], LSH256_AVX2_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + _mm256_storeu_si256(M256_CAST(cv_l), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_l)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_l)))); + _mm256_storeu_si256(M256_CAST(cv_r), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_r)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_r)))); +} + +inline void add_blk(lsh_u32 cv_l[8], lsh_u32 cv_r[8]) +{ + _mm256_storeu_si256(M256_CAST(cv_l), _mm256_add_epi32( + _mm256_loadu_si256(CONST_M256_CAST(cv_l)), + _mm256_loadu_si256(CONST_M256_CAST(cv_r)))); +} + +template +inline void rotate_blk(lsh_u32 cv[8]) +{ + _mm256_storeu_si256(M256_CAST(cv), _mm256_or_si256( + _mm256_slli_epi32(_mm256_loadu_si256(CONST_M256_CAST(cv)), R), + _mm256_srli_epi32(_mm256_loadu_si256(CONST_M256_CAST(cv)), 32-R))); +} + +inline void xor_with_const(lsh_u32 cv_l[8], const lsh_u32 const_v[8]) +{ + _mm256_storeu_si256(M256_CAST(cv_l), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_l)), + _mm256_loadu_si256(CONST_M256_CAST(const_v)))); +} + +inline void rotate_msg_gamma(lsh_u32 cv_r[8]) +{ + // g_gamma256[8] = { 0, 8, 16, 24, 24, 16, 8, 0 }; + _mm256_storeu_si256(M256_CAST(cv_r+0), + _mm256_shuffle_epi8(_mm256_loadu_si256(CONST_M256_CAST(cv_r+0)), + _mm256_set_epi8( + /* hi lane */ 15,14,13,12, 10,9,8,11, 5,4,7,6, 0,3,2,1, + /* lo lane */ 12,15,14,13, 9,8,11,10, 6,5,4,7, 3,2,1,0))); +} + +inline void word_perm(lsh_u32 cv_l[8], lsh_u32 cv_r[8]) +{ + __m256i temp = _mm256_shuffle_epi32( + _mm256_loadu_si256(CONST_M256_CAST(cv_l)), _MM_SHUFFLE(3,1,0,2)); + _mm256_storeu_si256(M256_CAST(cv_r), + _mm256_shuffle_epi32( + _mm256_loadu_si256(CONST_M256_CAST(cv_r)), _MM_SHUFFLE(1,2,3,0))); + _mm256_storeu_si256(M256_CAST(cv_l), + _mm256_permute2x128_si256(temp, + _mm256_loadu_si256(CONST_M256_CAST(cv_r)), _MM_SHUFFLE(0,3,0,1))); + _mm256_storeu_si256(M256_CAST(cv_r), + _mm256_permute2x128_si256(temp, + _mm256_loadu_si256(CONST_M256_CAST(cv_r)), _MM_SHUFFLE(0,2,0,0))); +}; + +/* -------------------------------------------------------- * +* step function +* -------------------------------------------------------- */ + +template +inline void mix(lsh_u32 cv_l[8], lsh_u32 cv_r[8], const lsh_u32 const_v[8]) +{ + add_blk(cv_l, cv_r); + rotate_blk(cv_l); + xor_with_const(cv_l, const_v); + add_blk(cv_r, cv_l); + rotate_blk(cv_r); + add_blk(cv_l, cv_r); + rotate_msg_gamma(cv_r); +} + +/* -------------------------------------------------------- * +* compression function +* -------------------------------------------------------- */ + +inline void compress(LSH256_AVX2_Context* ctx, const lsh_u8 pdMsgBlk[LSH256_MSG_BLK_BYTE_LEN]) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + LSH256_AVX2_Internal s_state(ctx->cv_l); + LSH256_AVX2_Internal* i_state = &s_state; + + const lsh_u32* const_v = NULL; + lsh_u32* cv_l = ctx->cv_l; + lsh_u32* cv_r = ctx->cv_r; + + load_msg_blk(i_state, pdMsgBlk); + + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 0); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + for (size_t i = 1; i < NUM_STEPS / 2; i++) + { + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_exp_odd(i_state); + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); +} + +/* -------------------------------------------------------- */ + +inline void load_iv(word32 cv_l[8], word32 cv_r[8], const word32 iv[16]) +{ + // The IV's are 32-byte aligned so we can use aligned loads. + _mm256_storeu_si256(M256_CAST(cv_l+0), + _mm256_load_si256(CONST_M256_CAST(iv+0))); + _mm256_storeu_si256(M256_CAST(cv_r+0), + _mm256_load_si256(CONST_M256_CAST(iv+8))); +} + +inline void zero_iv(lsh_u32 cv_l[8], lsh_u32 cv_r[8]) +{ + _mm256_storeu_si256(M256_CAST(cv_l+0), _mm256_setzero_si256()); + _mm256_storeu_si256(M256_CAST(cv_r+0), _mm256_setzero_si256()); +} + +inline void zero_submsgs(LSH256_AVX2_Context* ctx) +{ + lsh_u32* sub_msgs = ctx->sub_msgs; + + _mm256_storeu_si256(M256_CAST(sub_msgs+ 0), _mm256_setzero_si256()); + _mm256_storeu_si256(M256_CAST(sub_msgs+ 8), _mm256_setzero_si256()); + _mm256_storeu_si256(M256_CAST(sub_msgs+16), _mm256_setzero_si256()); + _mm256_storeu_si256(M256_CAST(sub_msgs+24), _mm256_setzero_si256()); +} + +inline void init224(LSH256_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH256_IV224); +} + +inline void init256(LSH256_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH256_IV256); +} + +/* -------------------------------------------------------- */ + +inline void fin(LSH256_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + _mm256_storeu_si256(M256_CAST(ctx->cv_l+0), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(ctx->cv_l+0)), + _mm256_loadu_si256(CONST_M256_CAST(ctx->cv_r+0)))); +} + +/* -------------------------------------------------------- */ + +inline void get_hash(LSH256_AVX2_Context* ctx, lsh_u8* pbHashVal) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + CRYPTOPP_ASSERT(pbHashVal != NULLPTR); + + lsh_uint alg_type = ctx->alg_type; + lsh_uint hash_val_byte_len = LSH_GET_HASHBYTE(alg_type); + lsh_uint hash_val_bit_len = LSH_GET_SMALL_HASHBIT(alg_type); + + // Multiplying by looks odd... + memcpy(pbHashVal, ctx->cv_l, hash_val_byte_len); + if (hash_val_bit_len){ + pbHashVal[hash_val_byte_len-1] &= (((lsh_u8)0xff) << hash_val_bit_len); + } +} + +/* -------------------------------------------------------- */ + +lsh_err lsh256_init_avx2(LSH256_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + lsh_u32 alg_type = ctx->alg_type; + const lsh_u32* const_v = NULL; + ctx->remain_databitlen = 0; + + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735. + AVX_Cleanup cleanup; + + switch (alg_type) + { + case LSH_TYPE_256_256: + init256(ctx); + return LSH_SUCCESS; + case LSH_TYPE_256_224: + init224(ctx); + return LSH_SUCCESS; + default: + break; + } + + lsh_u32* cv_l = ctx->cv_l; + lsh_u32* cv_r = ctx->cv_r; + + zero_iv(cv_l, cv_r); + cv_l[0] = LSH256_HASH_VAL_MAX_BYTE_LEN; + cv_l[1] = LSH_GET_HASHBIT(alg_type); + + for (size_t i = 0; i < NUM_STEPS / 2; i++) + { + //Mix + load_sc(&const_v, i * 16); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + load_sc(&const_v, i * 16 + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + return LSH_SUCCESS; +} + +lsh_err lsh256_update_avx2(LSH256_AVX2_Context* ctx, const lsh_u8* data, size_t databitlen) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(data != NULLPTR); + CRYPTOPP_ASSERT(databitlen % 8 == 0); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735. + AVX_Cleanup cleanup; + + if (databitlen == 0){ + return LSH_SUCCESS; + } + + // We are byte oriented. tail bits will always be 0. + size_t databytelen = databitlen >> 3; + // lsh_uint pos2 = databitlen & 0x7; + const size_t pos2 = 0; + + size_t remain_msg_byte = ctx->remain_databitlen >> 3; + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH256_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + if (remain_msg_bit > 0){ + return LSH_ERR_INVALID_DATABITLEN; + } + + if (databytelen + remain_msg_byte < LSH256_MSG_BLK_BYTE_LEN) + { + memcpy(ctx->last_block + remain_msg_byte, data, databytelen); + ctx->remain_databitlen += (lsh_uint)databitlen; + remain_msg_byte += (lsh_uint)databytelen; + if (pos2){ + ctx->last_block[remain_msg_byte] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + } + return LSH_SUCCESS; + } + + if (remain_msg_byte > 0){ + size_t more_byte = LSH256_MSG_BLK_BYTE_LEN - remain_msg_byte; + memcpy(ctx->last_block + remain_msg_byte, data, more_byte); + compress(ctx, ctx->last_block); + data += more_byte; + databytelen -= more_byte; + remain_msg_byte = 0; + ctx->remain_databitlen = 0; + } + + while (databytelen >= LSH256_MSG_BLK_BYTE_LEN) + { + // This call to compress caused some trouble. + // The data pointer can become unaligned in the + // previous block. + compress(ctx, data); + data += LSH256_MSG_BLK_BYTE_LEN; + databytelen -= LSH256_MSG_BLK_BYTE_LEN; + } + + if (databytelen > 0){ + memcpy(ctx->last_block, data, databytelen); + ctx->remain_databitlen = (lsh_uint)(databytelen << 3); + } + + if (pos2){ + ctx->last_block[databytelen] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + ctx->remain_databitlen += pos2; + } + + return LSH_SUCCESS; +} + +lsh_err lsh256_final_avx2(LSH256_AVX2_Context* ctx, lsh_u8* hashval) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(hashval != NULLPTR); + + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735. + AVX_Cleanup cleanup; + + // We are byte oriented. tail bits will always be 0. + size_t remain_msg_byte = ctx->remain_databitlen >> 3; + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH256_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + + if (remain_msg_bit){ + ctx->last_block[remain_msg_byte] |= (0x1 << (7 - remain_msg_bit)); + } + else{ + ctx->last_block[remain_msg_byte] = 0x80; + } + memset(ctx->last_block + remain_msg_byte + 1, 0, LSH256_MSG_BLK_BYTE_LEN - remain_msg_byte - 1); + + compress(ctx, ctx->last_block); + + fin(ctx); + get_hash(ctx, hashval); + + return LSH_SUCCESS; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +extern +void LSH256_Base_Restart_AVX2(word32* state) +{ + state[RemainingBits] = 0; + LSH256_AVX2_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh256_init_avx2(&ctx); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_init_avx2 failed"); +} + +extern +void LSH256_Base_Update_AVX2(word32* state, const byte *input, size_t size) +{ + LSH256_AVX2_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh256_update_avx2(&ctx, input, 8*size); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_update_avx2 failed"); +} + +extern +void LSH256_Base_TruncatedFinal_AVX2(word32* state, byte *hash, size_t) +{ + LSH256_AVX2_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh256_final_avx2(&ctx, hash); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_final_avx2 failed"); +} + +NAMESPACE_END + +#endif // CRYPTOPP_AVX2_AVAILABLE diff --git a/external/ours/library/crypto/src/shared/original/lsh256_sse.cpp b/external/ours/library/crypto/src/shared/original/lsh256_sse.cpp new file mode 100755 index 000000000..4417142cf --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/lsh256_sse.cpp @@ -0,0 +1,710 @@ +// lsh.cpp - 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. + +#include "pch.h" +#include "config.h" + +#include "lsh.h" +#include "cpu.h" +#include "misc.h" + +#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + +#if defined(CRYPTOPP_SSSE3_AVAILABLE) +# include +# include +#endif + +#if defined(CRYPTOPP_XOP_AVAILABLE) +# include +#endif + +// GCC at 4.5. Clang is unknown. Also see https://stackoverflow.com/a/42493893. +#if (CRYPTOPP_GCC_VERSION >= 40500) +# include +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +/* LSH Constants */ + +const unsigned int LSH256_MSG_BLK_BYTE_LEN = 128; +// const unsigned int LSH256_MSG_BLK_BIT_LEN = 1024; +// const unsigned int LSH256_CV_BYTE_LEN = 64; +const unsigned int LSH256_HASH_VAL_MAX_BYTE_LEN = 32; + +// const unsigned int MSG_BLK_WORD_LEN = 32; +const unsigned int CV_WORD_LEN = 16; +const unsigned int CONST_WORD_LEN = 8; +// const unsigned int HASH_VAL_MAX_WORD_LEN = 8; +// const unsigned int WORD_BIT_LEN = 32; +const unsigned int NUM_STEPS = 26; + +const unsigned int ROT_EVEN_ALPHA = 29; +const unsigned int ROT_EVEN_BETA = 1; +const unsigned int ROT_ODD_ALPHA = 5; +const unsigned int ROT_ODD_BETA = 17; + +const unsigned int LSH_TYPE_256_256 = 0x0000020; +const unsigned int LSH_TYPE_256_224 = 0x000001C; + +// const unsigned int LSH_TYPE_224 = LSH_TYPE_256_224; +// const unsigned int LSH_TYPE_256 = LSH_TYPE_256_256; + +/* Error Code */ + +const unsigned int LSH_SUCCESS = 0x0; +// const unsigned int LSH_ERR_NULL_PTR = 0x2401; +// const unsigned int LSH_ERR_INVALID_ALGTYPE = 0x2402; +const unsigned int LSH_ERR_INVALID_DATABITLEN = 0x2403; +const unsigned int LSH_ERR_INVALID_STATE = 0x2404; + +/* Index into our state array */ + +const unsigned int AlgorithmType = 80; +const unsigned int RemainingBits = 81; + +NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(LSH) + +// lsh256.cpp +extern const word32 LSH256_IV224[CV_WORD_LEN]; +extern const word32 LSH256_IV256[CV_WORD_LEN]; +extern const word32 LSH256_StepConstants[CONST_WORD_LEN * NUM_STEPS]; + +NAMESPACE_END // LSH +NAMESPACE_END // Crypto++ + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::rotlFixed; +using CryptoPP::rotlConstant; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; +using CryptoPP::ConditionalByteReverse; +using CryptoPP::LITTLE_ENDIAN_ORDER; + +typedef byte lsh_u8; +typedef word32 lsh_u32; +typedef word32 lsh_uint; +typedef word32 lsh_err; +typedef word32 lsh_type; + +using CryptoPP::LSH::LSH256_IV224; +using CryptoPP::LSH::LSH256_IV256; +using CryptoPP::LSH::LSH256_StepConstants; + +struct LSH256_SSSE3_Context +{ + LSH256_SSSE3_Context(word32* state, word32 algType, word32& remainingBitLength) : + cv_l(state+0), cv_r(state+8), sub_msgs(state+16), + last_block(reinterpret_cast(state+48)), + remain_databitlen(remainingBitLength), + alg_type(static_cast(algType)) {} + + lsh_u32* cv_l; // start of our state block + lsh_u32* cv_r; + lsh_u32* sub_msgs; + lsh_u8* last_block; + lsh_u32& remain_databitlen; + lsh_type alg_type; +}; + +struct LSH256_SSSE3_Internal +{ + LSH256_SSSE3_Internal(word32* state) : + submsg_e_l(state+16), submsg_e_r(state+24), + submsg_o_l(state+32), submsg_o_r(state+40) { } + + lsh_u32* submsg_e_l; /* even left sub-message */ + lsh_u32* submsg_e_r; /* even right sub-message */ + lsh_u32* submsg_o_l; /* odd left sub-message */ + lsh_u32* submsg_o_r; /* odd right sub-message */ +}; + +// const word32 g_gamma256[8] = { 0, 8, 16, 24, 24, 16, 8, 0 }; + +/* LSH AlgType Macro */ + +inline bool LSH_IS_LSH512(lsh_uint val) { + return (val & 0xf0000) == 0; +} + +inline lsh_uint LSH_GET_SMALL_HASHBIT(lsh_uint val) { + return val >> 24; +} + +inline lsh_uint LSH_GET_HASHBYTE(lsh_uint val) { + return val & 0xffff; +} + +inline lsh_uint LSH_GET_HASHBIT(lsh_uint val) { + return (LSH_GET_HASHBYTE(val) << 3) - LSH_GET_SMALL_HASHBIT(val); +} + +inline lsh_u32 loadLE32(lsh_u32 v) { + return ConditionalByteReverse(LITTLE_ENDIAN_ORDER, v); +} + +lsh_u32 ROTL(lsh_u32 x, lsh_u32 r) { + return rotlFixed(x, r); +} + +// Original code relied upon unaligned lsh_u32 buffer +inline void load_msg_blk(LSH256_SSSE3_Internal* i_state, const lsh_u8 msgblk[LSH256_MSG_BLK_BYTE_LEN]) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + _mm_storeu_si128(M128_CAST(submsg_e_l+0), + _mm_loadu_si128(CONST_M128_CAST(msgblk+0))); + _mm_storeu_si128(M128_CAST(submsg_e_l+4), + _mm_loadu_si128(CONST_M128_CAST(msgblk+16))); + _mm_storeu_si128(M128_CAST(submsg_e_r+0), + _mm_loadu_si128(CONST_M128_CAST(msgblk+32))); + _mm_storeu_si128(M128_CAST(submsg_e_r+4), + _mm_loadu_si128(CONST_M128_CAST(msgblk+48))); + _mm_storeu_si128(M128_CAST(submsg_o_l+0), + _mm_loadu_si128(CONST_M128_CAST(msgblk+64))); + _mm_storeu_si128(M128_CAST(submsg_o_l+4), + _mm_loadu_si128(CONST_M128_CAST(msgblk+80))); + _mm_storeu_si128(M128_CAST(submsg_o_r+0), + _mm_loadu_si128(CONST_M128_CAST(msgblk+96))); + _mm_storeu_si128(M128_CAST(submsg_o_r+4), + _mm_loadu_si128(CONST_M128_CAST(msgblk+112))); +} + +inline void msg_exp_even(LSH256_SSSE3_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + _mm_storeu_si128(M128_CAST(submsg_e_l+0), _mm_add_epi32( + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+0)), _MM_SHUFFLE(3,2,1,0)), + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+0)), _MM_SHUFFLE(1,0,2,3)))); + + _mm_storeu_si128(M128_CAST(submsg_e_l+4), _mm_add_epi32( + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+4)), _MM_SHUFFLE(3,2,1,0)), + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+4)), _MM_SHUFFLE(2,1,0,3)))); + + _mm_storeu_si128(M128_CAST(submsg_e_r+0), _mm_add_epi32( + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+0)), _MM_SHUFFLE(3,2,1,0)), + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+0)), _MM_SHUFFLE(1,0,2,3)))); + + _mm_storeu_si128(M128_CAST(submsg_e_r+4), _mm_add_epi32( + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+4)), _MM_SHUFFLE(3,2,1,0)), + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+4)), _MM_SHUFFLE(2,1,0,3)))); +} + +inline void msg_exp_odd(LSH256_SSSE3_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + _mm_storeu_si128(M128_CAST(submsg_o_l+0), _mm_add_epi32( + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+0)), _MM_SHUFFLE(3,2,1,0)), + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+0)), _MM_SHUFFLE(1,0,2,3)))); + + _mm_storeu_si128(M128_CAST(submsg_o_l+4), _mm_add_epi32( + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+4)), _MM_SHUFFLE(3,2,1,0)), + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+4)), _MM_SHUFFLE(2,1,0,3)))); + + _mm_storeu_si128(M128_CAST(submsg_o_r+0), _mm_add_epi32( + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+0)), _MM_SHUFFLE(3,2,1,0)), + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+0)), _MM_SHUFFLE(1,0,2,3)))); + + _mm_storeu_si128(M128_CAST(submsg_o_r+4), _mm_add_epi32( + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+4)), _MM_SHUFFLE(3,2,1,0)), + _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+4)), _MM_SHUFFLE(2,1,0,3)))); +} + +inline void load_sc(const lsh_u32** p_const_v, size_t i) +{ + CRYPTOPP_ASSERT(p_const_v != NULLPTR); + + *p_const_v = &LSH256_StepConstants[i]; +} + +inline void msg_add_even(lsh_u32 cv_l[8], lsh_u32 cv_r[8], LSH256_SSSE3_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_e_l = i_state->submsg_e_l; + lsh_u32* submsg_e_r = i_state->submsg_e_r; + + _mm_storeu_si128(M128_CAST(cv_l+0), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+0)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+0)))); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+4)))); + _mm_storeu_si128(M128_CAST(cv_r+0), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r+0)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+0)))); + _mm_storeu_si128(M128_CAST(cv_r+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+4)))); +} + +inline void msg_add_odd(lsh_u32 cv_l[8], lsh_u32 cv_r[8], LSH256_SSSE3_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u32* submsg_o_l = i_state->submsg_o_l; + lsh_u32* submsg_o_r = i_state->submsg_o_r; + + _mm_storeu_si128(M128_CAST(cv_l), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l)))); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+4)))); + _mm_storeu_si128(M128_CAST(cv_r), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r)))); + _mm_storeu_si128(M128_CAST(cv_r+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+4)))); +} + +inline void add_blk(lsh_u32 cv_l[8], const lsh_u32 cv_r[8]) +{ + _mm_storeu_si128(M128_CAST(cv_l), _mm_add_epi32( + _mm_loadu_si128(CONST_M128_CAST(cv_l)), + _mm_loadu_si128(CONST_M128_CAST(cv_r)))); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_add_epi32( + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(cv_r+4)))); +} + +template +inline void rotate_blk(lsh_u32 cv[8]) +{ +#if defined(CRYPTOPP_XOP_AVAILABLE) + _mm_storeu_si128(M128_CAST(cv), + _mm_roti_epi32(_mm_loadu_si128(CONST_M128_CAST(cv)), R)); + _mm_storeu_si128(M128_CAST(cv+4), + _mm_roti_epi32(_mm_loadu_si128(CONST_M128_CAST(cv+4)), R)); +#else + _mm_storeu_si128(M128_CAST(cv), _mm_or_si128( + _mm_slli_epi32(_mm_loadu_si128(CONST_M128_CAST(cv)), R), + _mm_srli_epi32(_mm_loadu_si128(CONST_M128_CAST(cv)), 32-R))); + _mm_storeu_si128(M128_CAST(cv+4), _mm_or_si128( + _mm_slli_epi32(_mm_loadu_si128(CONST_M128_CAST(cv+4)), R), + _mm_srli_epi32(_mm_loadu_si128(CONST_M128_CAST(cv+4)), 32-R))); +#endif +} + +inline void xor_with_const(lsh_u32* cv_l, const lsh_u32* const_v) +{ + _mm_storeu_si128(M128_CAST(cv_l), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l)), + _mm_loadu_si128(CONST_M128_CAST(const_v)))); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(const_v+4)))); +} + +inline void rotate_msg_gamma(lsh_u32 cv_r[8]) +{ + // g_gamma256[8] = { 0, 8, 16, 24, 24, 16, 8, 0 }; + _mm_storeu_si128(M128_CAST(cv_r+0), + _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(cv_r+0)), + _mm_set_epi8(12,15,14,13, 9,8,11,10, 6,5,4,7, 3,2,1,0))); + _mm_storeu_si128(M128_CAST(cv_r+4), + _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(cv_r+4)), + _mm_set_epi8(15,14,13,12, 10,9,8,11, 5,4,7,6, 0,3,2,1))); +} + +inline void word_perm(lsh_u32 cv_l[8], lsh_u32 cv_r[8]) +{ + _mm_storeu_si128(M128_CAST(cv_l+0), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(cv_l+0)), _MM_SHUFFLE(3,1,0,2))); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)), _MM_SHUFFLE(3,1,0,2))); + _mm_storeu_si128(M128_CAST(cv_r+0), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(cv_r+0)), _MM_SHUFFLE(1,2,3,0))); + _mm_storeu_si128(M128_CAST(cv_r+4), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(cv_r+4)), _MM_SHUFFLE(1,2,3,0))); + + __m128i temp = _mm_loadu_si128(CONST_M128_CAST(cv_l+0)); + _mm_storeu_si128(M128_CAST(cv_l+0), + _mm_loadu_si128(CONST_M128_CAST(cv_l+4))); + _mm_storeu_si128(M128_CAST(cv_l+4), + _mm_loadu_si128(CONST_M128_CAST(cv_r+4))); + _mm_storeu_si128(M128_CAST(cv_r+4), + _mm_loadu_si128(CONST_M128_CAST(cv_r+0))); + _mm_storeu_si128(M128_CAST(cv_r+0), temp); +}; + +/* -------------------------------------------------------- * +* step function +* -------------------------------------------------------- */ + +template +inline void mix(lsh_u32 cv_l[8], lsh_u32 cv_r[8], const lsh_u32 const_v[8]) +{ + add_blk(cv_l, cv_r); + rotate_blk(cv_l); + xor_with_const(cv_l, const_v); + add_blk(cv_r, cv_l); + rotate_blk(cv_r); + add_blk(cv_l, cv_r); + rotate_msg_gamma(cv_r); +} + +/* -------------------------------------------------------- * +* compression function +* -------------------------------------------------------- */ + +inline void compress(LSH256_SSSE3_Context* ctx, const lsh_u8 pdMsgBlk[LSH256_MSG_BLK_BYTE_LEN]) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + LSH256_SSSE3_Internal s_state(ctx->cv_l); + LSH256_SSSE3_Internal* i_state = &s_state; + + const lsh_u32* const_v = NULL; + lsh_u32* cv_l = ctx->cv_l; + lsh_u32* cv_r = ctx->cv_r; + + load_msg_blk(i_state, pdMsgBlk); + + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 0); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + for (size_t i = 1; i < NUM_STEPS / 2; i++) + { + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_exp_odd(i_state); + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); +} + +/* -------------------------------------------------------- */ + +inline void load_iv(lsh_u32 cv_l[8], lsh_u32 cv_r[8], const lsh_u32 iv[16]) +{ + _mm_storeu_si128(M128_CAST(cv_l+ 0), + _mm_load_si128(CONST_M128_CAST(iv+ 0))); + _mm_storeu_si128(M128_CAST(cv_l+ 4), + _mm_load_si128(CONST_M128_CAST(iv+ 4))); + _mm_storeu_si128(M128_CAST(cv_r+ 0), + _mm_load_si128(CONST_M128_CAST(iv+ 8))); + _mm_storeu_si128(M128_CAST(cv_r+ 4), + _mm_load_si128(CONST_M128_CAST(iv+12))); +} + +inline void zero_iv(lsh_u32 cv_l[8], lsh_u32 cv_r[8]) +{ + _mm_storeu_si128(M128_CAST(cv_l+0), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_r+0), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_r+4), _mm_setzero_si128()); +} + +inline void zero_submsgs(LSH256_SSSE3_Context* ctx) +{ + lsh_u32* sub_msgs = ctx->sub_msgs; + + _mm_storeu_si128(M128_CAST(sub_msgs+ 0), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+ 4), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+ 8), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+12), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+16), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+20), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+24), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+28), _mm_setzero_si128()); +} + +inline void init224(LSH256_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH256_IV224); +} + +inline void init256(LSH256_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH256_IV256); +} + +/* -------------------------------------------------------- */ + +inline void fin(LSH256_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + _mm_storeu_si128(M128_CAST(ctx->cv_l+0), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_l+0)), + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_r+0)))); + _mm_storeu_si128(M128_CAST(ctx->cv_l+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_r+4)))); +} + +/* -------------------------------------------------------- */ + +inline void get_hash(LSH256_SSSE3_Context* ctx, lsh_u8* pbHashVal) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + CRYPTOPP_ASSERT(pbHashVal != NULLPTR); + + lsh_uint alg_type = ctx->alg_type; + lsh_uint hash_val_byte_len = LSH_GET_HASHBYTE(alg_type); + lsh_uint hash_val_bit_len = LSH_GET_SMALL_HASHBIT(alg_type); + + // Multiplying by sizeof(lsh_u8) looks odd... + memcpy(pbHashVal, ctx->cv_l, hash_val_byte_len); + if (hash_val_bit_len){ + pbHashVal[hash_val_byte_len-1] &= (((lsh_u8)0xff) << hash_val_bit_len); + } +} + +/* -------------------------------------------------------- */ + +lsh_err lsh256_ssse3_init(LSH256_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + lsh_u32 alg_type = ctx->alg_type; + const lsh_u32* const_v = NULL; + ctx->remain_databitlen = 0; + + switch (alg_type) + { + case LSH_TYPE_256_256: + init256(ctx); + return LSH_SUCCESS; + case LSH_TYPE_256_224: + init224(ctx); + return LSH_SUCCESS; + default: + break; + } + + lsh_u32* cv_l = ctx->cv_l; + lsh_u32* cv_r = ctx->cv_r; + + zero_iv(cv_l, cv_r); + cv_l[0] = LSH256_HASH_VAL_MAX_BYTE_LEN; + cv_l[1] = LSH_GET_HASHBIT(alg_type); + + for (size_t i = 0; i < NUM_STEPS / 2; i++) + { + //Mix + load_sc(&const_v, i * 16); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + load_sc(&const_v, i * 16 + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + return LSH_SUCCESS; +} + +lsh_err lsh256_ssse3_update(LSH256_SSSE3_Context* ctx, const lsh_u8* data, size_t databitlen) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(data != NULLPTR); + CRYPTOPP_ASSERT(databitlen % 8 == 0); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + if (databitlen == 0){ + return LSH_SUCCESS; + } + + // We are byte oriented. tail bits will always be 0. + size_t databytelen = databitlen >> 3; + // lsh_uint pos2 = databitlen & 0x7; + const size_t pos2 = 0; + + size_t remain_msg_byte = ctx->remain_databitlen >> 3; + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH256_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + if (remain_msg_bit > 0){ + return LSH_ERR_INVALID_DATABITLEN; + } + + if (databytelen + remain_msg_byte < LSH256_MSG_BLK_BYTE_LEN) + { + memcpy(ctx->last_block + remain_msg_byte, data, databytelen); + ctx->remain_databitlen += (lsh_uint)databitlen; + remain_msg_byte += (lsh_uint)databytelen; + if (pos2){ + ctx->last_block[remain_msg_byte] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + } + return LSH_SUCCESS; + } + + if (remain_msg_byte > 0){ + size_t more_byte = LSH256_MSG_BLK_BYTE_LEN - remain_msg_byte; + memcpy(ctx->last_block + remain_msg_byte, data, more_byte); + compress(ctx, ctx->last_block); + data += more_byte; + databytelen -= more_byte; + remain_msg_byte = 0; + ctx->remain_databitlen = 0; + } + + while (databytelen >= LSH256_MSG_BLK_BYTE_LEN) + { + // This call to compress caused some trouble. + // The data pointer can become unaligned in the + // previous block. + compress(ctx, data); + data += LSH256_MSG_BLK_BYTE_LEN; + databytelen -= LSH256_MSG_BLK_BYTE_LEN; + } + + if (databytelen > 0){ + memcpy(ctx->last_block, data, databytelen); + ctx->remain_databitlen = (lsh_uint)(databytelen << 3); + } + + if (pos2){ + ctx->last_block[databytelen] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + ctx->remain_databitlen += pos2; + } + + return LSH_SUCCESS; +} + +lsh_err lsh256_ssse3_final(LSH256_SSSE3_Context* ctx, lsh_u8* hashval) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(hashval != NULLPTR); + + // We are byte oriented. tail bits will always be 0. + size_t remain_msg_byte = ctx->remain_databitlen >> 3; + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH256_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + + if (remain_msg_bit){ + ctx->last_block[remain_msg_byte] |= (0x1 << (7 - remain_msg_bit)); + } + else{ + ctx->last_block[remain_msg_byte] = 0x80; + } + memset(ctx->last_block + remain_msg_byte + 1, 0, LSH256_MSG_BLK_BYTE_LEN - remain_msg_byte - 1); + + compress(ctx, ctx->last_block); + + fin(ctx); + get_hash(ctx, hashval); + + return LSH_SUCCESS; +} + +ANONYMOUS_NAMESPACE_END // Anonymous + +NAMESPACE_BEGIN(CryptoPP) + +extern +void LSH256_Base_Restart_SSSE3(word32* state) +{ + state[RemainingBits] = 0; + LSH256_SSSE3_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh256_ssse3_init(&ctx); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_ssse3_init failed"); +} + +extern +void LSH256_Base_Update_SSSE3(word32* state, const byte *input, size_t size) +{ + LSH256_SSSE3_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh256_ssse3_update(&ctx, input, 8*size); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_ssse3_update failed"); +} + +extern +void LSH256_Base_TruncatedFinal_SSSE3(word32* state, byte *hash, size_t) +{ + LSH256_SSSE3_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh256_ssse3_final(&ctx, hash); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_ssse3_final failed"); +} + +NAMESPACE_END + +#endif // CRYPTOPP_SSSE3_AVAILABLE diff --git a/external/ours/library/crypto/src/shared/original/lsh512.cpp b/external/ours/library/crypto/src/shared/original/lsh512.cpp new file mode 100755 index 000000000..8f24f3bad --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/lsh512.cpp @@ -0,0 +1,893 @@ +// lsh.cpp - 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. + + +#include "pch.h" +#include "config.h" + +#include "lsh.h" +#include "cpu.h" +#include "misc.h" + +ANONYMOUS_NAMESPACE_BEGIN + +/* LSH Constants */ + +const unsigned int LSH512_MSG_BLK_BYTE_LEN = 256; +// const unsigned int LSH512_MSG_BLK_BIT_LEN = 2048; +// const unsigned int LSH512_CV_BYTE_LEN = 128; +const unsigned int LSH512_HASH_VAL_MAX_BYTE_LEN = 64; + +// const unsigned int MSG_BLK_WORD_LEN = 32; +const unsigned int CV_WORD_LEN = 16; +const unsigned int CONST_WORD_LEN = 8; +const unsigned int HASH_VAL_MAX_WORD_LEN = 8; +const unsigned int NUM_STEPS = 28; + +const unsigned int ROT_EVEN_ALPHA = 23; +const unsigned int ROT_EVEN_BETA = 59; +const unsigned int ROT_ODD_ALPHA = 7; +const unsigned int ROT_ODD_BETA = 3; + +const unsigned int LSH_TYPE_512_512 = 0x0010040; +const unsigned int LSH_TYPE_512_384 = 0x0010030; +const unsigned int LSH_TYPE_512_256 = 0x0010020; +const unsigned int LSH_TYPE_512_224 = 0x001001C; + +// const unsigned int LSH_TYPE_384 = LSH_TYPE_512_384; +// const unsigned int LSH_TYPE_512 = LSH_TYPE_512_512; + +/* Error Code */ + +const unsigned int LSH_SUCCESS = 0x0; +// const unsigned int LSH_ERR_NULL_PTR = 0x2401; +// const unsigned int LSH_ERR_INVALID_ALGTYPE = 0x2402; +const unsigned int LSH_ERR_INVALID_DATABITLEN = 0x2403; +const unsigned int LSH_ERR_INVALID_STATE = 0x2404; + +/* Index into our state array */ + +const unsigned int AlgorithmType = 80; +const unsigned int RemainingBits = 81; + +NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(LSH) + +/* -------------------------------------------------------- * +* LSH: iv +* -------------------------------------------------------- */ + +//extern const word64 LSH512_IV224[CV_WORD_LEN]; +//extern const word64 LSH512_IV256[CV_WORD_LEN]; +//extern const word64 LSH512_IV384[CV_WORD_LEN]; +//extern const word64 LSH512_IV512[CV_WORD_LEN]; +//extern const word64 LSH512_StepConstants[CONST_WORD_LEN * NUM_STEPS]; + +CRYPTOPP_ALIGN_DATA(32) +extern +const word64 LSH512_IV224[CV_WORD_LEN] = { + W64LIT(0x0C401E9FE8813A55), W64LIT(0x4A5F446268FD3D35), W64LIT(0xFF13E452334F612A), W64LIT(0xF8227661037E354A), + W64LIT(0xA5F223723C9CA29D), W64LIT(0x95D965A11AED3979), W64LIT(0x01E23835B9AB02CC), W64LIT(0x52D49CBAD5B30616), + W64LIT(0x9E5C2027773F4ED3), W64LIT(0x66A5C8801925B701), W64LIT(0x22BBC85B4C6779D9), W64LIT(0xC13171A42C559C23), + W64LIT(0x31E2B67D25BE3813), W64LIT(0xD522C4DEED8E4D83), W64LIT(0xA79F5509B43FBAFE), W64LIT(0xE00D2CD88B4B6C6A), +}; + +CRYPTOPP_ALIGN_DATA(32) +extern +const word64 LSH512_IV256[CV_WORD_LEN] = { + W64LIT(0x6DC57C33DF989423), W64LIT(0xD8EA7F6E8342C199), W64LIT(0x76DF8356F8603AC4), W64LIT(0x40F1B44DE838223A), + W64LIT(0x39FFE7CFC31484CD), W64LIT(0x39C4326CC5281548), W64LIT(0x8A2FF85A346045D8), W64LIT(0xFF202AA46DBDD61E), + W64LIT(0xCF785B3CD5FCDB8B), W64LIT(0x1F0323B64A8150BF), W64LIT(0xFF75D972F29EA355), W64LIT(0x2E567F30BF1CA9E1), + W64LIT(0xB596875BF8FF6DBA), W64LIT(0xFCCA39B089EF4615), W64LIT(0xECFF4017D020B4B6), W64LIT(0x7E77384C772ED802), +}; + +CRYPTOPP_ALIGN_DATA(32) +extern +const word64 LSH512_IV384[CV_WORD_LEN] = { + W64LIT(0x53156A66292808F6), W64LIT(0xB2C4F362B204C2BC), W64LIT(0xB84B7213BFA05C4E), W64LIT(0x976CEB7C1B299F73), + W64LIT(0xDF0CC63C0570AE97), W64LIT(0xDA4441BAA486CE3F), W64LIT(0x6559F5D9B5F2ACC2), W64LIT(0x22DACF19B4B52A16), + W64LIT(0xBBCDACEFDE80953A), W64LIT(0xC9891A2879725B3E), W64LIT(0x7C9FE6330237E440), W64LIT(0xA30BA550553F7431), + W64LIT(0xBB08043FB34E3E30), W64LIT(0xA0DEC48D54618EAD), W64LIT(0x150317267464BC57), W64LIT(0x32D1501FDE63DC93) +}; + +CRYPTOPP_ALIGN_DATA(32) +extern +const word64 LSH512_IV512[CV_WORD_LEN] = { + W64LIT(0xadd50f3c7f07094e), W64LIT(0xe3f3cee8f9418a4f), W64LIT(0xb527ecde5b3d0ae9), W64LIT(0x2ef6dec68076f501), + W64LIT(0x8cb994cae5aca216), W64LIT(0xfbb9eae4bba48cc7), W64LIT(0x650a526174725fea), W64LIT(0x1f9a61a73f8d8085), + W64LIT(0xb6607378173b539b), W64LIT(0x1bc99853b0c0b9ed), W64LIT(0xdf727fc19b182d47), W64LIT(0xdbef360cf893a457), + W64LIT(0x4981f5e570147e80), W64LIT(0xd00c4490ca7d3e30), W64LIT(0x5d73940c0e4ae1ec), W64LIT(0x894085e2edb2d819) +}; + +/* -------------------------------------------------------- * +* LSH: step constants +* -------------------------------------------------------- */ + +extern +const word64 LSH512_StepConstants[CONST_WORD_LEN * NUM_STEPS] = { + W64LIT(0x97884283c938982a), W64LIT(0xba1fca93533e2355), W64LIT(0xc519a2e87aeb1c03), W64LIT(0x9a0fc95462af17b1), + W64LIT(0xfc3dda8ab019a82b), W64LIT(0x02825d079a895407), W64LIT(0x79f2d0a7ee06a6f7), W64LIT(0xd76d15eed9fdf5fe), + W64LIT(0x1fcac64d01d0c2c1), W64LIT(0xd9ea5de69161790f), W64LIT(0xdebc8b6366071fc8), W64LIT(0xa9d91db711c6c94b), + W64LIT(0x3a18653ac9c1d427), W64LIT(0x84df64a223dd5b09), W64LIT(0x6cc37895f4ad9e70), W64LIT(0x448304c8d7f3f4d5), + W64LIT(0xea91134ed29383e0), W64LIT(0xc4484477f2da88e8), W64LIT(0x9b47eec96d26e8a6), W64LIT(0x82f6d4c8d89014f4), + W64LIT(0x527da0048b95fb61), W64LIT(0x644406c60138648d), W64LIT(0x303c0e8aa24c0edc), W64LIT(0xc787cda0cbe8ca19), + W64LIT(0x7ba46221661764ca), W64LIT(0x0c8cbc6acd6371ac), W64LIT(0xe336b836940f8f41), W64LIT(0x79cb9da168a50976), + W64LIT(0xd01da49021915cb3), W64LIT(0xa84accc7399cf1f1), W64LIT(0x6c4a992cee5aeb0c), W64LIT(0x4f556e6cb4b2e3e0), + W64LIT(0x200683877d7c2f45), W64LIT(0x9949273830d51db8), W64LIT(0x19eeeecaa39ed124), W64LIT(0x45693f0a0dae7fef), + W64LIT(0xedc234b1b2ee1083), W64LIT(0xf3179400d68ee399), W64LIT(0xb6e3c61b4945f778), W64LIT(0xa4c3db216796c42f), + W64LIT(0x268a0b04f9ab7465), W64LIT(0xe2705f6905f2d651), W64LIT(0x08ddb96e426ff53d), W64LIT(0xaea84917bc2e6f34), + W64LIT(0xaff6e664a0fe9470), W64LIT(0x0aab94d765727d8c), W64LIT(0x9aa9e1648f3d702e), W64LIT(0x689efc88fe5af3d3), + W64LIT(0xb0950ffea51fd98b), W64LIT(0x52cfc86ef8c92833), W64LIT(0xe69727b0b2653245), W64LIT(0x56f160d3ea9da3e2), + W64LIT(0xa6dd4b059f93051f), W64LIT(0xb6406c3cd7f00996), W64LIT(0x448b45f3ccad9ec8), W64LIT(0x079b8587594ec73b), + W64LIT(0x45a50ea3c4f9653b), W64LIT(0x22983767c1f15b85), W64LIT(0x7dbed8631797782b), W64LIT(0x485234be88418638), + W64LIT(0x842850a5329824c5), W64LIT(0xf6aca914c7f9a04c), W64LIT(0xcfd139c07a4c670c), W64LIT(0xa3210ce0a8160242), + W64LIT(0xeab3b268be5ea080), W64LIT(0xbacf9f29b34ce0a7), W64LIT(0x3c973b7aaf0fa3a8), W64LIT(0x9a86f346c9c7be80), + W64LIT(0xac78f5d7cabcea49), W64LIT(0xa355bddcc199ed42), W64LIT(0xa10afa3ac6b373db), W64LIT(0xc42ded88be1844e5), + W64LIT(0x9e661b271cff216a), W64LIT(0x8a6ec8dd002d8861), W64LIT(0xd3d2b629beb34be4), W64LIT(0x217a3a1091863f1a), + W64LIT(0x256ecda287a733f5), W64LIT(0xf9139a9e5b872fe5), W64LIT(0xac0535017a274f7c), W64LIT(0xf21b7646d65d2aa9), + W64LIT(0x048142441c208c08), W64LIT(0xf937a5dd2db5e9eb), W64LIT(0xa688dfe871ff30b7), W64LIT(0x9bb44aa217c5593b), + W64LIT(0x943c702a2edb291a), W64LIT(0x0cae38f9e2b715de), W64LIT(0xb13a367ba176cc28), W64LIT(0x0d91bd1d3387d49b), + W64LIT(0x85c386603cac940c), W64LIT(0x30dd830ae39fd5e4), W64LIT(0x2f68c85a712fe85d), W64LIT(0x4ffeecb9dd1e94d6), + W64LIT(0xd0ac9a590a0443ae), W64LIT(0xbae732dc99ccf3ea), W64LIT(0xeb70b21d1842f4d9), W64LIT(0x9f4eda50bb5c6fa8), + W64LIT(0x4949e69ce940a091), W64LIT(0x0e608dee8375ba14), W64LIT(0x983122cba118458c), W64LIT(0x4eeba696fbb36b25), + W64LIT(0x7d46f3630e47f27e), W64LIT(0xa21a0f7666c0dea4), W64LIT(0x5c22cf355b37cec4), W64LIT(0xee292b0c17cc1847), + W64LIT(0x9330838629e131da), W64LIT(0x6eee7c71f92fce22), W64LIT(0xc953ee6cb95dd224), W64LIT(0x3a923d92af1e9073), + W64LIT(0xc43a5671563a70fb), W64LIT(0xbc2985dd279f8346), W64LIT(0x7ef2049093069320), W64LIT(0x17543723e3e46035), + W64LIT(0xc3b409b00b130c6d), W64LIT(0x5d6aee6b28fdf090), W64LIT(0x1d425b26172ff6ed), W64LIT(0xcccfd041cdaf03ad), + W64LIT(0xfe90c7c790ab6cbf), W64LIT(0xe5af6304c722ca02), W64LIT(0x70f695239999b39e), W64LIT(0x6b8b5b07c844954c), + W64LIT(0x77bdb9bb1e1f7a30), W64LIT(0xc859599426ee80ed), W64LIT(0x5f9d813d4726e40a), W64LIT(0x9ca0120f7cb2b179), + W64LIT(0x8f588f583c182cbd), W64LIT(0x951267cbe9eccce7), W64LIT(0x678bb8bd334d520e), W64LIT(0xf6e662d00cd9e1b7), + W64LIT(0x357774d93d99aaa7), W64LIT(0x21b2edbb156f6eb5), W64LIT(0xfd1ebe846e0aee69), W64LIT(0x3cb2218c2f642b15), + W64LIT(0xe7e7e7945444ea4c), W64LIT(0xa77a33b5d6b9b47c), W64LIT(0xf34475f0809f6075), W64LIT(0xdd4932dce6bb99ad), + W64LIT(0xacec4e16d74451dc), W64LIT(0xd4a0a8d084de23d6), W64LIT(0x1bdd42f278f95866), W64LIT(0xeed3adbb938f4051), + W64LIT(0xcfcf7be8992f3733), W64LIT(0x21ade98c906e3123), W64LIT(0x37ba66711fffd668), W64LIT(0x267c0fc3a255478a), + W64LIT(0x993a64ee1b962e88), W64LIT(0x754979556301faaa), W64LIT(0xf920356b7251be81), W64LIT(0xc281694f22cf923f), + W64LIT(0x9f4b6481c8666b02), W64LIT(0xcf97761cfe9f5444), W64LIT(0xf220d7911fd63e9f), W64LIT(0xa28bd365f79cd1b0), + W64LIT(0xd39f5309b1c4b721), W64LIT(0xbec2ceb864fca51f), W64LIT(0x1955a0ddc410407a), W64LIT(0x43eab871f261d201), + W64LIT(0xeaafe64a2ed16da1), W64LIT(0x670d931b9df39913), W64LIT(0x12f868b0f614de91), W64LIT(0x2e5f395d946e8252), + W64LIT(0x72f25cbb767bd8f4), W64LIT(0x8191871d61a1c4dd), W64LIT(0x6ef67ea1d450ba93), W64LIT(0x2ea32a645433d344), + W64LIT(0x9a963079003f0f8b), W64LIT(0x74a0aeb9918cac7a), W64LIT(0x0b6119a70af36fa3), W64LIT(0x8d9896f202f0d480), + W64LIT(0x654f1831f254cd66), W64LIT(0x1318a47f0366a25e), W64LIT(0x65752076250b4e01), W64LIT(0xd1cd8eb888071772), + W64LIT(0x30c6a9793f4e9b25), W64LIT(0x154f684b1e3926ee), W64LIT(0x6c7ac0b1fe6312ae), W64LIT(0x262f88f4f3c5550d), + W64LIT(0xb4674a24472233cb), W64LIT(0x2bbd23826a090071), W64LIT(0xda95969b30594f66), W64LIT(0x9f5c47408f1e8a43), + W64LIT(0xf77022b88de9c055), W64LIT(0x64b7b36957601503), W64LIT(0xe73b72b06175c11a), W64LIT(0x55b87de8b91a6233), + W64LIT(0x1bb16e6b6955ff7f), W64LIT(0xe8e0a5ec7309719c), W64LIT(0x702c31cb89a8b640), W64LIT(0xfba387cfada8cde2), + W64LIT(0x6792db4677aa164c), W64LIT(0x1c6b1cc0b7751867), W64LIT(0x22ae2311d736dc01), W64LIT(0x0e3666a1d37c9588), + W64LIT(0xcd1fd9d4bf557e9a), W64LIT(0xc986925f7c7b0e84), W64LIT(0x9c5dfd55325ef6b0), W64LIT(0x9f2b577d5676b0dd), + W64LIT(0xfa6e21be21c062b3), W64LIT(0x8787dd782c8d7f83), W64LIT(0xd0d134e90e12dd23), W64LIT(0x449d087550121d96), + W64LIT(0xecf9ae9414d41967), W64LIT(0x5018f1dbf789934d), W64LIT(0xfa5b52879155a74c), W64LIT(0xca82d4d3cd278e7c), + W64LIT(0x688fdfdfe22316ad), W64LIT(0x0f6555a4ba0d030a), W64LIT(0xa2061df720f000f3), W64LIT(0xe1a57dc5622fb3da), + W64LIT(0xe6a842a8e8ed8153), W64LIT(0x690acdd3811ce09d), W64LIT(0x55adda18e6fcf446), W64LIT(0x4d57a8a0f4b60b46), + W64LIT(0xf86fbfc20539c415), W64LIT(0x74bafa5ec7100d19), W64LIT(0xa824151810f0f495), W64LIT(0x8723432791e38ebb), + W64LIT(0x8eeaeb91d66ed539), W64LIT(0x73d8a1549dfd7e06), W64LIT(0x0387f2ffe3f13a9b), W64LIT(0xa5004995aac15193), + W64LIT(0x682f81c73efdda0d), W64LIT(0x2fb55925d71d268d), W64LIT(0xcc392d2901e58a3d), W64LIT(0xaa666ab975724a42) +}; + +NAMESPACE_END // LSH +NAMESPACE_END // Crypto++ + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::rotlFixed; +using CryptoPP::rotlConstant; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; +using CryptoPP::ConditionalByteReverse; +using CryptoPP::LITTLE_ENDIAN_ORDER; + +using CryptoPP::LSH::LSH512_IV224; +using CryptoPP::LSH::LSH512_IV256; +using CryptoPP::LSH::LSH512_IV384; +using CryptoPP::LSH::LSH512_IV512; +using CryptoPP::LSH::LSH512_StepConstants; + +typedef byte lsh_u8; +typedef word32 lsh_u32; +typedef word64 lsh_u64; +typedef word32 lsh_uint; +typedef word32 lsh_err; +typedef word32 lsh_type; + +struct LSH512_Context +{ + LSH512_Context(word64* state, word64 algType, word64& remainingBitLength) : + cv_l(state+0), cv_r(state+8), sub_msgs(state+16), + last_block(reinterpret_cast(state+48)), + remain_databitlen(remainingBitLength), + alg_type(static_cast(algType)) {} + + lsh_u64* cv_l; // start of our state block + lsh_u64* cv_r; + lsh_u64* sub_msgs; + lsh_u8* last_block; + lsh_u64& remain_databitlen; + lsh_type alg_type; +}; + +struct LSH512_Internal +{ + LSH512_Internal(word64* state) : + submsg_e_l(state+16), submsg_e_r(state+24), + submsg_o_l(state+32), submsg_o_r(state+40) { } + + lsh_u64* submsg_e_l; /* even left sub-message */ + lsh_u64* submsg_e_r; /* even right sub-message */ + lsh_u64* submsg_o_l; /* odd left sub-message */ + lsh_u64* submsg_o_r; /* odd right sub-message */ +}; + +const lsh_u32 g_gamma512[8] = { 0, 16, 32, 48, 8, 24, 40, 56 }; + +/* LSH AlgType Macro */ + +inline bool LSH_IS_LSH512(lsh_uint val) { + return (val & 0xf0000) == 0x10000; +} + +inline lsh_uint LSH_GET_SMALL_HASHBIT(lsh_uint val) { + return val >> 24; +} + +inline lsh_uint LSH_GET_HASHBYTE(lsh_uint val) { + return val & 0xffff; +} + +inline lsh_uint LSH_GET_HASHBIT(lsh_uint val) { + return (LSH_GET_HASHBYTE(val) << 3) - LSH_GET_SMALL_HASHBIT(val); +} + +inline lsh_u64 loadLE64(lsh_u64 v) { + return ConditionalByteReverse(LITTLE_ENDIAN_ORDER, v); +} + +lsh_u64 ROTL64(lsh_u64 x, lsh_u32 r) { + return rotlFixed(x, r); +} + +// Original code relied upon unaligned lsh_u64 buffer +inline void load_msg_blk(LSH512_Internal* i_state, const lsh_u8* msgblk) +{ + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + typedef GetBlock InBlock; + + InBlock input(msgblk); + input(submsg_e_l[0])(submsg_e_l[1])(submsg_e_l[2])(submsg_e_l[3]) + (submsg_e_l[4])(submsg_e_l[5])(submsg_e_l[6])(submsg_e_l[7]) + (submsg_e_r[0])(submsg_e_r[1])(submsg_e_r[2])(submsg_e_r[3]) + (submsg_e_r[4])(submsg_e_r[5])(submsg_e_r[6])(submsg_e_r[7]) + (submsg_o_l[0])(submsg_o_l[1])(submsg_o_l[2])(submsg_o_l[3]) + (submsg_o_l[4])(submsg_o_l[5])(submsg_o_l[6])(submsg_o_l[7]) + (submsg_o_r[0])(submsg_o_r[1])(submsg_o_r[2])(submsg_o_r[3]) + (submsg_o_r[4])(submsg_o_r[5])(submsg_o_r[6])(submsg_o_r[7]); +} + +inline void msg_exp_even(LSH512_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + lsh_u64 temp; + temp = submsg_e_l[0]; + submsg_e_l[0] = submsg_o_l[0] + submsg_e_l[3]; + submsg_e_l[3] = submsg_o_l[3] + submsg_e_l[1]; + submsg_e_l[1] = submsg_o_l[1] + submsg_e_l[2]; + submsg_e_l[2] = submsg_o_l[2] + temp; + temp = submsg_e_l[4]; + submsg_e_l[4] = submsg_o_l[4] + submsg_e_l[7]; + submsg_e_l[7] = submsg_o_l[7] + submsg_e_l[6]; + submsg_e_l[6] = submsg_o_l[6] + submsg_e_l[5]; + submsg_e_l[5] = submsg_o_l[5] + temp; + temp = submsg_e_r[0]; + submsg_e_r[0] = submsg_o_r[0] + submsg_e_r[3]; + submsg_e_r[3] = submsg_o_r[3] + submsg_e_r[1]; + submsg_e_r[1] = submsg_o_r[1] + submsg_e_r[2]; + submsg_e_r[2] = submsg_o_r[2] + temp; + temp = submsg_e_r[4]; + submsg_e_r[4] = submsg_o_r[4] + submsg_e_r[7]; + submsg_e_r[7] = submsg_o_r[7] + submsg_e_r[6]; + submsg_e_r[6] = submsg_o_r[6] + submsg_e_r[5]; + submsg_e_r[5] = submsg_o_r[5] + temp; +} + +inline void msg_exp_odd(LSH512_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + lsh_u64 temp; + temp = submsg_o_l[0]; + submsg_o_l[0] = submsg_e_l[0] + submsg_o_l[3]; + submsg_o_l[3] = submsg_e_l[3] + submsg_o_l[1]; + submsg_o_l[1] = submsg_e_l[1] + submsg_o_l[2]; + submsg_o_l[2] = submsg_e_l[2] + temp; + temp = submsg_o_l[4]; + submsg_o_l[4] = submsg_e_l[4] + submsg_o_l[7]; + submsg_o_l[7] = submsg_e_l[7] + submsg_o_l[6]; + submsg_o_l[6] = submsg_e_l[6] + submsg_o_l[5]; + submsg_o_l[5] = submsg_e_l[5] + temp; + temp = submsg_o_r[0]; + submsg_o_r[0] = submsg_e_r[0] + submsg_o_r[3]; + submsg_o_r[3] = submsg_e_r[3] + submsg_o_r[1]; + submsg_o_r[1] = submsg_e_r[1] + submsg_o_r[2]; + submsg_o_r[2] = submsg_e_r[2] + temp; + temp = submsg_o_r[4]; + submsg_o_r[4] = submsg_e_r[4] + submsg_o_r[7]; + submsg_o_r[7] = submsg_e_r[7] + submsg_o_r[6]; + submsg_o_r[6] = submsg_e_r[6] + submsg_o_r[5]; + submsg_o_r[5] = submsg_e_r[5] + temp; +} + +inline void load_sc(const lsh_u64** p_const_v, size_t i) +{ + *p_const_v = &LSH512_StepConstants[i]; +} + +inline void msg_add_even(lsh_u64 cv_l[8], lsh_u64 cv_r[8], LSH512_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + + cv_l[0] ^= submsg_e_l[0]; cv_l[1] ^= submsg_e_l[1]; + cv_l[2] ^= submsg_e_l[2]; cv_l[3] ^= submsg_e_l[3]; + cv_l[4] ^= submsg_e_l[4]; cv_l[5] ^= submsg_e_l[5]; + cv_l[6] ^= submsg_e_l[6]; cv_l[7] ^= submsg_e_l[7]; + cv_r[0] ^= submsg_e_r[0]; cv_r[1] ^= submsg_e_r[1]; + cv_r[2] ^= submsg_e_r[2]; cv_r[3] ^= submsg_e_r[3]; + cv_r[4] ^= submsg_e_r[4]; cv_r[5] ^= submsg_e_r[5]; + cv_r[6] ^= submsg_e_r[6]; cv_r[7] ^= submsg_e_r[7]; +} + +inline void msg_add_odd(lsh_u64 cv_l[8], lsh_u64 cv_r[8], LSH512_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + cv_l[0] ^= submsg_o_l[0]; cv_l[1] ^= submsg_o_l[1]; + cv_l[2] ^= submsg_o_l[2]; cv_l[3] ^= submsg_o_l[3]; + cv_l[4] ^= submsg_o_l[4]; cv_l[5] ^= submsg_o_l[5]; + cv_l[6] ^= submsg_o_l[6]; cv_l[7] ^= submsg_o_l[7]; + cv_r[0] ^= submsg_o_r[0]; cv_r[1] ^= submsg_o_r[1]; + cv_r[2] ^= submsg_o_r[2]; cv_r[3] ^= submsg_o_r[3]; + cv_r[4] ^= submsg_o_r[4]; cv_r[5] ^= submsg_o_r[5]; + cv_r[6] ^= submsg_o_r[6]; cv_r[7] ^= submsg_o_r[7]; +} + +inline void add_blk(lsh_u64 cv_l[8], lsh_u64 cv_r[8]) +{ + cv_l[0] += cv_r[0]; + cv_l[1] += cv_r[1]; + cv_l[2] += cv_r[2]; + cv_l[3] += cv_r[3]; + cv_l[4] += cv_r[4]; + cv_l[5] += cv_r[5]; + cv_l[6] += cv_r[6]; + cv_l[7] += cv_r[7]; +} + +template +inline void rotate_blk(lsh_u64 cv[8]) +{ + cv[0] = rotlConstant(cv[0]); + cv[1] = rotlConstant(cv[1]); + cv[2] = rotlConstant(cv[2]); + cv[3] = rotlConstant(cv[3]); + cv[4] = rotlConstant(cv[4]); + cv[5] = rotlConstant(cv[5]); + cv[6] = rotlConstant(cv[6]); + cv[7] = rotlConstant(cv[7]); +} + +inline void xor_with_const(lsh_u64 cv_l[8], const lsh_u64* const_v) +{ + cv_l[0] ^= const_v[0]; + cv_l[1] ^= const_v[1]; + cv_l[2] ^= const_v[2]; + cv_l[3] ^= const_v[3]; + cv_l[4] ^= const_v[4]; + cv_l[5] ^= const_v[5]; + cv_l[6] ^= const_v[6]; + cv_l[7] ^= const_v[7]; +} + +inline void rotate_msg_gamma(lsh_u64 cv_r[8]) +{ + cv_r[1] = ROTL64(cv_r[1], g_gamma512[1]); + cv_r[2] = ROTL64(cv_r[2], g_gamma512[2]); + cv_r[3] = ROTL64(cv_r[3], g_gamma512[3]); + cv_r[4] = ROTL64(cv_r[4], g_gamma512[4]); + cv_r[5] = ROTL64(cv_r[5], g_gamma512[5]); + cv_r[6] = ROTL64(cv_r[6], g_gamma512[6]); + cv_r[7] = ROTL64(cv_r[7], g_gamma512[7]); +} + +inline void word_perm(lsh_u64 cv_l[8], lsh_u64 cv_r[8]) +{ + lsh_u64 temp; + temp = cv_l[0]; + cv_l[0] = cv_l[6]; + cv_l[6] = cv_r[6]; + cv_r[6] = cv_r[2]; + cv_r[2] = cv_l[1]; + cv_l[1] = cv_l[4]; + cv_l[4] = cv_r[4]; + cv_r[4] = cv_r[0]; + cv_r[0] = cv_l[2]; + cv_l[2] = cv_l[5]; + cv_l[5] = cv_r[7]; + cv_r[7] = cv_r[1]; + cv_r[1] = temp; + temp = cv_l[3]; + cv_l[3] = cv_l[7]; + cv_l[7] = cv_r[5]; + cv_r[5] = cv_r[3]; + cv_r[3] = temp; +}; + +/* -------------------------------------------------------- * +* step function +* -------------------------------------------------------- */ + +template +inline void mix(lsh_u64 cv_l[8], lsh_u64 cv_r[8], const lsh_u64 const_v[8]) +{ + add_blk(cv_l, cv_r); + rotate_blk(cv_l); + xor_with_const(cv_l, const_v); + add_blk(cv_r, cv_l); + rotate_blk(cv_r); + add_blk(cv_l, cv_r); + rotate_msg_gamma(cv_r); +} + +/* -------------------------------------------------------- * +* compression function +* -------------------------------------------------------- */ + +inline void compress(LSH512_Context* ctx, const lsh_u8 pdMsgBlk[LSH512_MSG_BLK_BYTE_LEN]) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + LSH512_Internal s_state(ctx->cv_l); + LSH512_Internal* i_state = &s_state; + + const lsh_u64* const_v = NULL; + lsh_u64 *cv_l = ctx->cv_l; + lsh_u64 *cv_r = ctx->cv_r; + + load_msg_blk(i_state, pdMsgBlk); + + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 0); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + for (size_t i = 1; i < NUM_STEPS / 2; i++) + { + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_exp_odd(i_state); + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); +} + +/* -------------------------------------------------------- */ + +inline void load_iv(lsh_u64 cv_l[8], lsh_u64 cv_r[8], const lsh_u64 iv[16]) +{ + cv_l[0] = iv[0]; + cv_l[1] = iv[1]; + cv_l[2] = iv[2]; + cv_l[3] = iv[3]; + cv_l[4] = iv[4]; + cv_l[5] = iv[5]; + cv_l[6] = iv[6]; + cv_l[7] = iv[7]; + cv_r[0] = iv[8]; + cv_r[1] = iv[9]; + cv_r[2] = iv[10]; + cv_r[3] = iv[11]; + cv_r[4] = iv[12]; + cv_r[5] = iv[13]; + cv_r[6] = iv[14]; + cv_r[7] = iv[15]; +} + +inline void zero_iv(lsh_u64 cv_l[8], lsh_u64 cv_r[8]) +{ + memset(cv_l, 0, 8*sizeof(lsh_u64)); + memset(cv_r, 0, 8*sizeof(lsh_u64)); +} + +inline void zero_submsgs(LSH512_Context* ctx) +{ + lsh_u64* sub_msgs = ctx->sub_msgs; + + memset(sub_msgs, 0x00, 32*sizeof(lsh_u64)); +} + +inline void init224(LSH512_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV224); +} + +inline void init256(LSH512_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV256); +} + +inline void init384(LSH512_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV384); +} + +inline void init512(LSH512_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV512); +} + +/* -------------------------------------------------------- */ + +inline void fin(LSH512_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + for (size_t i = 0; i < HASH_VAL_MAX_WORD_LEN; i++){ + ctx->cv_l[i] = loadLE64(ctx->cv_l[i] ^ ctx->cv_r[i]); + } +} + +/* -------------------------------------------------------- */ + +inline void get_hash(LSH512_Context* ctx, lsh_u8* pbHashVal) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + CRYPTOPP_ASSERT(pbHashVal != NULLPTR); + + lsh_uint alg_type = ctx->alg_type; + lsh_uint hash_val_byte_len = LSH_GET_HASHBYTE(alg_type); + lsh_uint hash_val_bit_len = LSH_GET_SMALL_HASHBIT(alg_type); + + // Multiplying by looks odd... + memcpy(pbHashVal, ctx->cv_l, hash_val_byte_len); + if (hash_val_bit_len){ + pbHashVal[hash_val_byte_len-1] &= (((lsh_u8)0xff) << hash_val_bit_len); + } +} + +/* -------------------------------------------------------- */ + +lsh_err lsh512_init(LSH512_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + lsh_u32 alg_type = ctx->alg_type; + const lsh_u64* const_v = NULL; + ctx->remain_databitlen = 0; + + switch (alg_type){ + case LSH_TYPE_512_512: + init512(ctx); + return LSH_SUCCESS; + case LSH_TYPE_512_384: + init384(ctx); + return LSH_SUCCESS; + case LSH_TYPE_512_256: + init256(ctx); + return LSH_SUCCESS; + case LSH_TYPE_512_224: + init224(ctx); + return LSH_SUCCESS; + default: + break; + } + + lsh_u64* cv_l = ctx->cv_l; + lsh_u64* cv_r = ctx->cv_r; + + zero_iv(cv_l, cv_r); + cv_l[0] = LSH512_HASH_VAL_MAX_BYTE_LEN; + cv_l[1] = LSH_GET_HASHBIT(alg_type); + + for (size_t i = 0; i < NUM_STEPS / 2; i++) + { + //Mix + load_sc(&const_v, i * 16); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + load_sc(&const_v, i * 16 + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + return LSH_SUCCESS; +} + +lsh_err lsh512_update(LSH512_Context* ctx, const lsh_u8* data, size_t databitlen) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(data != NULLPTR); + CRYPTOPP_ASSERT(databitlen % 8 == 0); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + if (databitlen == 0){ + return LSH_SUCCESS; + } + + // We are byte oriented. tail bits will always be 0. + size_t databytelen = databitlen >> 3; + // lsh_uint pos2 = databitlen & 0x7; + const size_t pos2 = 0; + + size_t remain_msg_byte = static_cast(ctx->remain_databitlen >> 3); + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH512_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + if (remain_msg_bit > 0){ + return LSH_ERR_INVALID_DATABITLEN; + } + + if (databytelen + remain_msg_byte < LSH512_MSG_BLK_BYTE_LEN){ + memcpy(ctx->last_block + remain_msg_byte, data, databytelen); + ctx->remain_databitlen += (lsh_uint)databitlen; + remain_msg_byte += (lsh_uint)databytelen; + if (pos2){ + ctx->last_block[remain_msg_byte] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + } + return LSH_SUCCESS; + } + + if (remain_msg_byte > 0){ + size_t more_byte = LSH512_MSG_BLK_BYTE_LEN - remain_msg_byte; + memcpy(ctx->last_block + remain_msg_byte, data, more_byte); + compress(ctx, ctx->last_block); + data += more_byte; + databytelen -= more_byte; + remain_msg_byte = 0; + ctx->remain_databitlen = 0; + } + + while (databytelen >= LSH512_MSG_BLK_BYTE_LEN) + { + // This call to compress caused some trouble. + // The data pointer can become unaligned in the + // previous block. + compress(ctx, data); + data += LSH512_MSG_BLK_BYTE_LEN; + databytelen -= LSH512_MSG_BLK_BYTE_LEN; + } + + if (databytelen > 0){ + memcpy(ctx->last_block, data, databytelen); + ctx->remain_databitlen = (lsh_uint)(databytelen << 3); + } + + if (pos2){ + ctx->last_block[databytelen] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + ctx->remain_databitlen += pos2; + } + return LSH_SUCCESS; +} + +lsh_err lsh512_final(LSH512_Context* ctx, lsh_u8* hashval) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(hashval != NULLPTR); + + // We are byte oriented. tail bits will always be 0. + size_t remain_msg_byte = static_cast(ctx->remain_databitlen >> 3); + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH512_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + + if (remain_msg_bit){ + ctx->last_block[remain_msg_byte] |= (0x1 << (7 - remain_msg_bit)); + } + else{ + ctx->last_block[remain_msg_byte] = 0x80; + } + memset(ctx->last_block + remain_msg_byte + 1, 0, LSH512_MSG_BLK_BYTE_LEN - remain_msg_byte - 1); + + compress(ctx, ctx->last_block); + + fin(ctx); + get_hash(ctx, hashval); + + return LSH_SUCCESS; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_ENABLE_64BIT_SSE) +# if defined(CRYPTOPP_AVX2_AVAILABLE) + extern void LSH512_Base_Restart_AVX2(word64* state); + extern void LSH512_Base_Update_AVX2(word64* state, const byte *input, size_t size); + extern void LSH512_Base_TruncatedFinal_AVX2(word64* state, byte *hash, size_t size); +# endif +# if defined(CRYPTOPP_SSSE3_AVAILABLE) + extern void LSH512_Base_Restart_SSSE3(word64* state); + extern void LSH512_Base_Update_SSSE3(word64* state, const byte *input, size_t size); + extern void LSH512_Base_TruncatedFinal_SSSE3(word64* state, byte *hash, size_t size); +# endif +#endif + +std::string LSH512_Base::AlgorithmProvider() const +{ +#if defined(CRYPTOPP_ENABLE_64BIT_SSE) +#if defined(CRYPTOPP_AVX2_AVAILABLE) + if (HasAVX2()) + return "AVX2"; + else +#endif +#if defined(CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return "SSSE3"; + else +#endif +#endif // CRYPTOPP_ENABLE_64BIT_SSE + + return "C++"; +} + +void LSH512_Base_Restart_CXX(word64* state) +{ + state[RemainingBits] = 0; + LSH512_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh512_init(&ctx); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH512_Base: lsh512_init failed"); +} + +void LSH512_Base_Update_CXX(word64* state, const byte *input, size_t size) +{ + LSH512_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh512_update(&ctx, input, 8*size); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH512_Base: lsh512_update failed"); +} + +void LSH512_Base_TruncatedFinal_CXX(word64* state, byte *hash, size_t) +{ + LSH512_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh512_final(&ctx, hash); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH512_Base: lsh512_final failed"); +} + + +void LSH512_Base::Restart() +{ +#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasAVX2()) + LSH512_Base_Restart_AVX2(m_state); + else +#endif +#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasSSSE3()) + LSH512_Base_Restart_SSSE3(m_state); + else +#endif + + LSH512_Base_Restart_CXX(m_state); +} + +void LSH512_Base::Update(const byte *input, size_t size) +{ + CRYPTOPP_ASSERT(input != NULLPTR); + CRYPTOPP_ASSERT(size); + +#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasAVX2()) + LSH512_Base_Update_AVX2(m_state, input, size); + else +#endif +#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasSSSE3()) + LSH512_Base_Update_SSSE3(m_state, input, size); + else +#endif + + LSH512_Base_Update_CXX(m_state, input, size); +} + +void LSH512_Base::TruncatedFinal(byte *hash, size_t size) +{ + CRYPTOPP_ASSERT(hash != NULLPTR); + ThrowIfInvalidTruncatedSize(size); + + // TODO: determine if LSH512 supports truncated hashes. See the code + // in get_hash(), where a bit-length is added to the last output + // byte of the hash function. + byte fullHash[LSH512_HASH_VAL_MAX_BYTE_LEN]; + bool copyOut = (size < DigestSize()); + +#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasAVX2()) + LSH512_Base_TruncatedFinal_AVX2(m_state, copyOut ? fullHash : hash, size); + else +#endif +#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + if (HasSSSE3()) + LSH512_Base_TruncatedFinal_SSSE3(m_state, copyOut ? fullHash : hash, size); + else +#endif + + LSH512_Base_TruncatedFinal_CXX(m_state, copyOut ? fullHash : hash, size); + + if (copyOut) + memcpy(hash, fullHash, size); + + Restart(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/lsh512_avx.cpp b/external/ours/library/crypto/src/shared/original/lsh512_avx.cpp new file mode 100755 index 000000000..5065967d0 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/lsh512_avx.cpp @@ -0,0 +1,760 @@ +// lsh.cpp - 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. + +#include "pch.h" +#include "config.h" + +#include "lsh.h" +#include "misc.h" + +#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + +#if defined(CRYPTOPP_AVX2_AVAILABLE) +# include +# include +#endif + +// GCC at 4.5. Clang is unknown. Also see https://stackoverflow.com/a/42493893. +#if (CRYPTOPP_GCC_VERSION >= 40500) +# include +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +/* LSH Constants */ + +const unsigned int LSH512_MSG_BLK_BYTE_LEN = 256; +// const unsigned int LSH512_MSG_BLK_BIT_LEN = 2048; +// const unsigned int LSH512_CV_BYTE_LEN = 128; +const unsigned int LSH512_HASH_VAL_MAX_BYTE_LEN = 64; + +// const unsigned int MSG_BLK_WORD_LEN = 32; +const unsigned int CV_WORD_LEN = 16; +const unsigned int CONST_WORD_LEN = 8; +// const unsigned int HASH_VAL_MAX_WORD_LEN = 8; +const unsigned int NUM_STEPS = 28; + +const unsigned int ROT_EVEN_ALPHA = 23; +const unsigned int ROT_EVEN_BETA = 59; +const unsigned int ROT_ODD_ALPHA = 7; +const unsigned int ROT_ODD_BETA = 3; + +const unsigned int LSH_TYPE_512_512 = 0x0010040; +const unsigned int LSH_TYPE_512_384 = 0x0010030; +const unsigned int LSH_TYPE_512_256 = 0x0010020; +const unsigned int LSH_TYPE_512_224 = 0x001001C; + +// const unsigned int LSH_TYPE_384 = LSH_TYPE_512_384; +// const unsigned int LSH_TYPE_512 = LSH_TYPE_512_512; + +/* Error Code */ + +const unsigned int LSH_SUCCESS = 0x0; +// const unsigned int LSH_ERR_NULL_PTR = 0x2401; +// const unsigned int LSH_ERR_INVALID_ALGTYPE = 0x2402; +const unsigned int LSH_ERR_INVALID_DATABITLEN = 0x2403; +const unsigned int LSH_ERR_INVALID_STATE = 0x2404; + +/* Index into our state array */ + +const unsigned int AlgorithmType = 80; +const unsigned int RemainingBits = 81; + +NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(LSH) + +// lsh512.cpp +extern const word64 LSH512_IV224[CV_WORD_LEN]; +extern const word64 LSH512_IV256[CV_WORD_LEN]; +extern const word64 LSH512_IV384[CV_WORD_LEN]; +extern const word64 LSH512_IV512[CV_WORD_LEN]; +extern const word64 LSH512_StepConstants[CONST_WORD_LEN * NUM_STEPS]; + +NAMESPACE_END // LSH +NAMESPACE_END // Crypto++ + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::rotlFixed; +using CryptoPP::rotlConstant; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; +using CryptoPP::ConditionalByteReverse; +using CryptoPP::LITTLE_ENDIAN_ORDER; + +using CryptoPP::LSH::LSH512_IV224; +using CryptoPP::LSH::LSH512_IV256; +using CryptoPP::LSH::LSH512_IV384; +using CryptoPP::LSH::LSH512_IV512; +using CryptoPP::LSH::LSH512_StepConstants; + +typedef byte lsh_u8; +typedef word32 lsh_u32; +typedef word64 lsh_u64; +typedef word32 lsh_uint; +typedef word32 lsh_err; +typedef word32 lsh_type; + +struct LSH512_AVX2_Context +{ + LSH512_AVX2_Context(word64* state, word64 algType, word64& remainingBitLength) : + cv_l(state+0), cv_r(state+8), sub_msgs(state+16), + last_block(reinterpret_cast(state+48)), + remain_databitlen(remainingBitLength), + alg_type(static_cast(algType)) {} + + lsh_u64* cv_l; // start of our state block + lsh_u64* cv_r; + lsh_u64* sub_msgs; + lsh_u8* last_block; + lsh_u64& remain_databitlen; + lsh_type alg_type; +}; + +struct LSH512_AVX2_Internal +{ + LSH512_AVX2_Internal(word64* state) : + submsg_e_l(state+16), submsg_e_r(state+24), + submsg_o_l(state+32), submsg_o_r(state+40) { } + + lsh_u64* submsg_e_l; /* even left sub-message */ + lsh_u64* submsg_e_r; /* even right sub-message */ + lsh_u64* submsg_o_l; /* odd left sub-message */ + lsh_u64* submsg_o_r; /* odd right sub-message */ +}; + +// Zero the upper 128 bits of all YMM registers on exit. +// It avoids AVX state transition penalties when saving state. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735 +// makes using zeroupper a little tricky. + +struct AVX_Cleanup +{ + ~AVX_Cleanup() { + _mm256_zeroupper(); + } +}; + +// const lsh_u32 g_gamma512[8] = { 0, 16, 32, 48, 8, 24, 40, 56 }; + +/* LSH AlgType Macro */ + +inline bool LSH_IS_LSH512(lsh_uint val) { + return (val & 0xf0000) == 0x10000; +} + +inline lsh_uint LSH_GET_SMALL_HASHBIT(lsh_uint val) { + return val >> 24; +} + +inline lsh_uint LSH_GET_HASHBYTE(lsh_uint val) { + return val & 0xffff; +} + +inline lsh_uint LSH_GET_HASHBIT(lsh_uint val) { + return (LSH_GET_HASHBYTE(val) << 3) - LSH_GET_SMALL_HASHBIT(val); +} + +inline lsh_u64 loadLE64(lsh_u64 v) { + return ConditionalByteReverse(LITTLE_ENDIAN_ORDER, v); +} + +lsh_u64 ROTL64(lsh_u64 x, lsh_u32 r) { + return rotlFixed(x, r); +} + +// Original code relied upon unaligned lsh_u64 buffer +inline void load_msg_blk(LSH512_AVX2_Internal* i_state, const lsh_u8 msgblk[LSH512_MSG_BLK_BYTE_LEN]) +{ + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + _mm256_storeu_si256(M256_CAST(submsg_e_l+0), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+0))); + _mm256_storeu_si256(M256_CAST(submsg_e_l+4), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+32))); + + _mm256_storeu_si256(M256_CAST(submsg_e_r+0), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+64))); + _mm256_storeu_si256(M256_CAST(submsg_e_r+4), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+96))); + + _mm256_storeu_si256(M256_CAST(submsg_o_l+0), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+128))); + _mm256_storeu_si256(M256_CAST(submsg_o_l+4), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+160))); + + _mm256_storeu_si256(M256_CAST(submsg_o_r+0), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+192))); + _mm256_storeu_si256(M256_CAST(submsg_o_r+4), + _mm256_loadu_si256(CONST_M256_CAST(msgblk+224))); +} + +inline void msg_exp_even(LSH512_AVX2_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + _mm256_storeu_si256(M256_CAST(submsg_e_l+0), _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_l+0)), + _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_l+0)), + _MM_SHUFFLE(1,0,2,3)))); + _mm256_storeu_si256(M256_CAST(submsg_e_l+4), _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_l+4)), + _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_l+4)), + _MM_SHUFFLE(2,1,0,3)))); + + _mm256_storeu_si256(M256_CAST(submsg_e_r+0), _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_r+0)), + _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_r+0)), + _MM_SHUFFLE(1,0,2,3)))); + _mm256_storeu_si256(M256_CAST(submsg_e_r+4), _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_r+4)), + _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_r+4)), + _MM_SHUFFLE(2,1,0,3)))); +} + +inline void msg_exp_odd(LSH512_AVX2_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + _mm256_storeu_si256(M256_CAST(submsg_o_l+0), + _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_l+0)), + _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_l+0)), + _MM_SHUFFLE(1,0,2,3)))); + _mm256_storeu_si256(M256_CAST(submsg_o_l+4), + _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_l+4)), + _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_l+4)), + _MM_SHUFFLE(2,1,0,3)))); + + _mm256_storeu_si256(M256_CAST(submsg_o_r+0), + _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_r+0)), + _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_r+0)), + _MM_SHUFFLE(1,0,2,3)))); + _mm256_storeu_si256(M256_CAST(submsg_o_r+4), + _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_r+4)), + _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_r+4)), + _MM_SHUFFLE(2,1,0,3)))); +} + +inline void load_sc(const lsh_u64** p_const_v, size_t i) +{ + *p_const_v = &LSH512_StepConstants[i]; +} + +inline void msg_add_even(lsh_u64 cv_l[8], lsh_u64 cv_r[8], LSH512_AVX2_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + + _mm256_storeu_si256(M256_CAST(cv_l), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_l)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_l)))); + _mm256_storeu_si256(M256_CAST(cv_r), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_r)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_r)))); + + _mm256_storeu_si256(M256_CAST(cv_l+4), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_l+4)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_l+4)))); + _mm256_storeu_si256(M256_CAST(cv_r+4), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_r+4)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_e_r+4)))); +} + +inline void msg_add_odd(lsh_u64 cv_l[8], lsh_u64 cv_r[8], LSH512_AVX2_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + _mm256_storeu_si256(M256_CAST(cv_l), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_l)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_l)))); + _mm256_storeu_si256(M256_CAST(cv_r), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_r)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_r)))); + + _mm256_storeu_si256(M256_CAST(cv_l+4), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_l+4)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_l+4)))); + _mm256_storeu_si256(M256_CAST(cv_r+4), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_r+4)), + _mm256_loadu_si256(CONST_M256_CAST(submsg_o_r+4)))); +} + +inline void add_blk(lsh_u64 cv_l[8], lsh_u64 cv_r[8]) +{ + _mm256_storeu_si256(M256_CAST(cv_l), _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(cv_l)), + _mm256_loadu_si256(CONST_M256_CAST(cv_r)))); + _mm256_storeu_si256(M256_CAST(cv_l+4), _mm256_add_epi64( + _mm256_loadu_si256(CONST_M256_CAST(cv_l+4)), + _mm256_loadu_si256(CONST_M256_CAST(cv_r+4)))); +} + +template +inline void rotate_blk(lsh_u64 cv[8]) +{ + _mm256_storeu_si256(M256_CAST(cv), _mm256_or_si256( + _mm256_slli_epi64(_mm256_loadu_si256(CONST_M256_CAST(cv)), R), + _mm256_srli_epi64(_mm256_loadu_si256(CONST_M256_CAST(cv)), 64-R))); + _mm256_storeu_si256(M256_CAST(cv+4), _mm256_or_si256( + _mm256_slli_epi64(_mm256_loadu_si256(CONST_M256_CAST(cv+4)), R), + _mm256_srli_epi64(_mm256_loadu_si256(CONST_M256_CAST(cv+4)), 64-R))); +} + +inline void xor_with_const(lsh_u64 cv_l[8], const lsh_u64 const_v[8]) +{ + _mm256_storeu_si256(M256_CAST(cv_l), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_l)), + _mm256_loadu_si256(CONST_M256_CAST(const_v)))); + _mm256_storeu_si256(M256_CAST(cv_l+4), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(cv_l+4)), + _mm256_loadu_si256(CONST_M256_CAST(const_v+4)))); +} + +inline void rotate_msg_gamma(lsh_u64 cv_r[8]) +{ + // g_gamma512[8] = { 0, 16, 32, 48, 8, 24, 40, 56 }; + _mm256_storeu_si256(M256_CAST(cv_r+0), + _mm256_shuffle_epi8( + _mm256_loadu_si256(CONST_M256_CAST(cv_r+0)), + _mm256_set_epi8( + /* hi lane */ 9,8,15,14, 13,12,11,10, 3,2,1,0, 7,6,5,4, + /* lo lane */ 13,12,11,10, 9,8,15,14, 7,6,5,4, 3,2,1,0))); + _mm256_storeu_si256(M256_CAST(cv_r+4), + _mm256_shuffle_epi8( + _mm256_loadu_si256(CONST_M256_CAST(cv_r+4)), + _mm256_set_epi8( + /* hi lane */ 8,15,14,13, 12,11,10,9, 2,1,0,7, 6,5,4,3, + /* lo lane */ 12,11,10,9, 8,15,14,13, 6,5,4,3, 2,1,0,7))); +} + +inline void word_perm(lsh_u64 cv_l[8], lsh_u64 cv_r[8]) +{ + __m256i temp[2]; + _mm256_storeu_si256(M256_CAST(cv_l+0), _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(cv_l+0)), _MM_SHUFFLE(3,1,0,2))); + _mm256_storeu_si256(M256_CAST(cv_l+4), _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(cv_l+4)), _MM_SHUFFLE(3,1,0,2))); + _mm256_storeu_si256(M256_CAST(cv_r+0), _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(cv_r+0)), _MM_SHUFFLE(1,2,3,0))); + _mm256_storeu_si256(M256_CAST(cv_r+4), _mm256_permute4x64_epi64( + _mm256_loadu_si256(CONST_M256_CAST(cv_r+4)), _MM_SHUFFLE(1,2,3,0))); + + temp[0] = _mm256_loadu_si256(CONST_M256_CAST(cv_l+0)); + temp[1] = _mm256_loadu_si256(CONST_M256_CAST(cv_r+0)); + + _mm256_storeu_si256(M256_CAST(cv_l+0), + _mm256_loadu_si256(CONST_M256_CAST(cv_l+4))); + _mm256_storeu_si256(M256_CAST(cv_l+4), + _mm256_loadu_si256(CONST_M256_CAST(cv_r+4))); + + _mm256_storeu_si256(M256_CAST(cv_r+0), temp[0]); + _mm256_storeu_si256(M256_CAST(cv_r+4), temp[1]); +}; + +/* -------------------------------------------------------- * +* step function +* -------------------------------------------------------- */ + +template +inline void mix(lsh_u64 cv_l[8], lsh_u64 cv_r[8], const lsh_u64 const_v[8]) +{ + add_blk(cv_l, cv_r); + rotate_blk(cv_l); + xor_with_const(cv_l, const_v); + add_blk(cv_r, cv_l); + rotate_blk(cv_r); + add_blk(cv_l, cv_r); + rotate_msg_gamma(cv_r); +} + +/* -------------------------------------------------------- * +* compression function +* -------------------------------------------------------- */ + +inline void compress(LSH512_AVX2_Context* ctx, const lsh_u8 pdMsgBlk[LSH512_MSG_BLK_BYTE_LEN]) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + LSH512_AVX2_Internal s_state(ctx->cv_l); + LSH512_AVX2_Internal* i_state = &s_state; + + const lsh_u64* const_v = NULL; + lsh_u64 *cv_l = ctx->cv_l; + lsh_u64 *cv_r = ctx->cv_r; + + load_msg_blk(i_state, pdMsgBlk); + + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 0); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + for (size_t i = 1; i < NUM_STEPS / 2; i++) + { + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_exp_odd(i_state); + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); +} + +/* -------------------------------------------------------- */ + +inline void load_iv(word64 cv_l[8], word64 cv_r[8], const word64 iv[16]) +{ + // The IV's are 32-byte aligned so we can use aligned loads. + _mm256_storeu_si256(M256_CAST(cv_l+0), + _mm256_load_si256(CONST_M256_CAST(iv+0))); + _mm256_storeu_si256(M256_CAST(cv_l+4), + _mm256_load_si256(CONST_M256_CAST(iv+4))); + + _mm256_storeu_si256(M256_CAST(cv_r+0), + _mm256_load_si256(CONST_M256_CAST(iv+8))); + _mm256_storeu_si256(M256_CAST(cv_r+4), + _mm256_load_si256(CONST_M256_CAST(iv+12))); +} + +inline void zero_iv(lsh_u64 cv_l[8], lsh_u64 cv_r[8]) +{ + _mm256_storeu_si256(M256_CAST(cv_l+0), _mm256_setzero_si256()); + _mm256_storeu_si256(M256_CAST(cv_l+4), _mm256_setzero_si256()); + _mm256_storeu_si256(M256_CAST(cv_r+0), _mm256_setzero_si256()); + _mm256_storeu_si256(M256_CAST(cv_r+4), _mm256_setzero_si256()); +} + +inline void zero_submsgs(LSH512_AVX2_Context* ctx) +{ + lsh_u64* sub_msgs = ctx->sub_msgs; + + _mm256_storeu_si256(M256_CAST(sub_msgs+ 0), + _mm256_setzero_si256()); + _mm256_storeu_si256(M256_CAST(sub_msgs+ 4), + _mm256_setzero_si256()); + + _mm256_storeu_si256(M256_CAST(sub_msgs+ 8), + _mm256_setzero_si256()); + _mm256_storeu_si256(M256_CAST(sub_msgs+12), + _mm256_setzero_si256()); +} + +inline void init224(LSH512_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV224); +} + +inline void init256(LSH512_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV256); +} + +inline void init384(LSH512_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV384); +} + +inline void init512(LSH512_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV512); +} + +/* -------------------------------------------------------- */ + +inline void fin(LSH512_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + _mm256_storeu_si256(M256_CAST(ctx->cv_l+0), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(ctx->cv_l+0)), + _mm256_loadu_si256(CONST_M256_CAST(ctx->cv_r+0)))); + + _mm256_storeu_si256(M256_CAST(ctx->cv_l+4), _mm256_xor_si256( + _mm256_loadu_si256(CONST_M256_CAST(ctx->cv_l+4)), + _mm256_loadu_si256(CONST_M256_CAST(ctx->cv_r+4)))); +} + +/* -------------------------------------------------------- */ + +inline void get_hash(LSH512_AVX2_Context* ctx, lsh_u8* pbHashVal) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + CRYPTOPP_ASSERT(pbHashVal != NULLPTR); + + lsh_uint alg_type = ctx->alg_type; + lsh_uint hash_val_byte_len = LSH_GET_HASHBYTE(alg_type); + lsh_uint hash_val_bit_len = LSH_GET_SMALL_HASHBIT(alg_type); + + // Multiplying by sizeof(lsh_u8) looks odd... + memcpy(pbHashVal, ctx->cv_l, hash_val_byte_len); + if (hash_val_bit_len){ + pbHashVal[hash_val_byte_len-1] &= (((lsh_u8)0xff) << hash_val_bit_len); + } +} + +/* -------------------------------------------------------- */ + +lsh_err lsh512_init_avx2(LSH512_AVX2_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + lsh_u32 alg_type = ctx->alg_type; + const lsh_u64* const_v = NULL; + ctx->remain_databitlen = 0; + + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735. + AVX_Cleanup cleanup; + + switch (alg_type){ + case LSH_TYPE_512_512: + init512(ctx); + return LSH_SUCCESS; + case LSH_TYPE_512_384: + init384(ctx); + return LSH_SUCCESS; + case LSH_TYPE_512_256: + init256(ctx); + return LSH_SUCCESS; + case LSH_TYPE_512_224: + init224(ctx); + return LSH_SUCCESS; + default: + break; + } + + lsh_u64* cv_l = ctx->cv_l; + lsh_u64* cv_r = ctx->cv_r; + + zero_iv(cv_l, cv_r); + cv_l[0] = LSH512_HASH_VAL_MAX_BYTE_LEN; + cv_l[1] = LSH_GET_HASHBIT(alg_type); + + for (size_t i = 0; i < NUM_STEPS / 2; i++) + { + //Mix + load_sc(&const_v, i * 16); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + load_sc(&const_v, i * 16 + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + return LSH_SUCCESS; +} + +lsh_err lsh512_update_avx2(LSH512_AVX2_Context* ctx, const lsh_u8* data, size_t databitlen) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(data != NULLPTR); + CRYPTOPP_ASSERT(databitlen % 8 == 0); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735. + AVX_Cleanup cleanup; + + if (databitlen == 0){ + return LSH_SUCCESS; + } + + // We are byte oriented. tail bits will always be 0. + size_t databytelen = databitlen >> 3; + // lsh_uint pos2 = databitlen & 0x7; + const size_t pos2 = 0; + + size_t remain_msg_byte = static_cast(ctx->remain_databitlen >> 3); + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH512_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + if (remain_msg_bit > 0){ + return LSH_ERR_INVALID_DATABITLEN; + } + + if (databytelen + remain_msg_byte < LSH512_MSG_BLK_BYTE_LEN){ + memcpy(ctx->last_block + remain_msg_byte, data, databytelen); + ctx->remain_databitlen += (lsh_uint)databitlen; + remain_msg_byte += (lsh_uint)databytelen; + if (pos2){ + ctx->last_block[remain_msg_byte] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + } + return LSH_SUCCESS; + } + + if (remain_msg_byte > 0){ + size_t more_byte = LSH512_MSG_BLK_BYTE_LEN - remain_msg_byte; + memcpy(ctx->last_block + remain_msg_byte, data, more_byte); + compress(ctx, ctx->last_block); + data += more_byte; + databytelen -= more_byte; + remain_msg_byte = 0; + ctx->remain_databitlen = 0; + } + + while (databytelen >= LSH512_MSG_BLK_BYTE_LEN) + { + // This call to compress caused some trouble. + // The data pointer can become unaligned in the + // previous block. + compress(ctx, data); + data += LSH512_MSG_BLK_BYTE_LEN; + databytelen -= LSH512_MSG_BLK_BYTE_LEN; + } + + if (databytelen > 0){ + memcpy(ctx->last_block, data, databytelen); + ctx->remain_databitlen = (lsh_uint)(databytelen << 3); + } + + if (pos2){ + ctx->last_block[databytelen] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + ctx->remain_databitlen += pos2; + } + return LSH_SUCCESS; +} + +lsh_err lsh512_final_avx2(LSH512_AVX2_Context* ctx, lsh_u8* hashval) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(hashval != NULLPTR); + + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735. + AVX_Cleanup cleanup; + + // We are byte oriented. tail bits will always be 0. + size_t remain_msg_byte = static_cast(ctx->remain_databitlen >> 3); + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH512_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + + if (remain_msg_bit){ + ctx->last_block[remain_msg_byte] |= (0x1 << (7 - remain_msg_bit)); + } + else{ + ctx->last_block[remain_msg_byte] = 0x80; + } + memset(ctx->last_block + remain_msg_byte + 1, 0, LSH512_MSG_BLK_BYTE_LEN - remain_msg_byte - 1); + + compress(ctx, ctx->last_block); + + fin(ctx); + get_hash(ctx, hashval); + + return LSH_SUCCESS; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +extern +void LSH512_Base_Restart_AVX2(word64* state) +{ + state[RemainingBits] = 0; + LSH512_AVX2_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh512_init_avx2(&ctx); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH512_Base: lsh512_init_avx2 failed"); +} + +extern +void LSH512_Base_Update_AVX2(word64* state, const byte *input, size_t size) +{ + LSH512_AVX2_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh512_update_avx2(&ctx, input, 8*size); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH512_Base: lsh512_update_avx2 failed"); +} + +extern +void LSH512_Base_TruncatedFinal_AVX2(word64* state, byte *hash, size_t) +{ + LSH512_AVX2_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh512_final_avx2(&ctx, hash); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH512_Base: lsh512_final_avx2 failed"); +} + +NAMESPACE_END + +#endif // CRYPTOPP_AVX2_AVAILABLE diff --git a/external/ours/library/crypto/src/shared/original/lsh512_sse.cpp b/external/ours/library/crypto/src/shared/original/lsh512_sse.cpp new file mode 100755 index 000000000..0eb102939 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/lsh512_sse.cpp @@ -0,0 +1,938 @@ +// lsh.cpp - 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. + +#include "pch.h" +#include "config.h" + +#include "lsh.h" +#include "misc.h" + +#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE) + +#if defined(CRYPTOPP_SSSE3_AVAILABLE) +# include +# include +#endif + +#if defined(CRYPTOPP_XOP_AVAILABLE) +# include +#endif + +// GCC at 4.5. Clang is unknown. Also see https://stackoverflow.com/a/42493893. +#if (CRYPTOPP_GCC_VERSION >= 40500) +# include +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +/* LSH Constants */ + +const unsigned int LSH512_MSG_BLK_BYTE_LEN = 256; +// const unsigned int LSH512_MSG_BLK_BIT_LEN = 2048; +// const unsigned int LSH512_CV_BYTE_LEN = 128; +const unsigned int LSH512_HASH_VAL_MAX_BYTE_LEN = 64; + +// const unsigned int MSG_BLK_WORD_LEN = 32; +const unsigned int CV_WORD_LEN = 16; +const unsigned int CONST_WORD_LEN = 8; +// const unsigned int HASH_VAL_MAX_WORD_LEN = 8; +const unsigned int NUM_STEPS = 28; + +const unsigned int ROT_EVEN_ALPHA = 23; +const unsigned int ROT_EVEN_BETA = 59; +const unsigned int ROT_ODD_ALPHA = 7; +const unsigned int ROT_ODD_BETA = 3; + +const unsigned int LSH_TYPE_512_512 = 0x0010040; +const unsigned int LSH_TYPE_512_384 = 0x0010030; +const unsigned int LSH_TYPE_512_256 = 0x0010020; +const unsigned int LSH_TYPE_512_224 = 0x001001C; + +// const unsigned int LSH_TYPE_384 = LSH_TYPE_512_384; +// const unsigned int LSH_TYPE_512 = LSH_TYPE_512_512; + +/* Error Code */ + +const unsigned int LSH_SUCCESS = 0x0; +// const unsigned int LSH_ERR_NULL_PTR = 0x2401; +// const unsigned int LSH_ERR_INVALID_ALGTYPE = 0x2402; +const unsigned int LSH_ERR_INVALID_DATABITLEN = 0x2403; +const unsigned int LSH_ERR_INVALID_STATE = 0x2404; + +/* Index into our state array */ + +const unsigned int AlgorithmType = 80; +const unsigned int RemainingBits = 81; + +NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(LSH) + +// lsh512.cpp +extern const word64 LSH512_IV224[CV_WORD_LEN]; +extern const word64 LSH512_IV256[CV_WORD_LEN]; +extern const word64 LSH512_IV384[CV_WORD_LEN]; +extern const word64 LSH512_IV512[CV_WORD_LEN]; +extern const word64 LSH512_StepConstants[CONST_WORD_LEN * NUM_STEPS]; + +NAMESPACE_END // LSH +NAMESPACE_END // Crypto++ + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::rotlFixed; +using CryptoPP::rotlConstant; + +using CryptoPP::GetBlock; +using CryptoPP::LittleEndian; +using CryptoPP::ConditionalByteReverse; +using CryptoPP::LITTLE_ENDIAN_ORDER; + +using CryptoPP::LSH::LSH512_IV224; +using CryptoPP::LSH::LSH512_IV256; +using CryptoPP::LSH::LSH512_IV384; +using CryptoPP::LSH::LSH512_IV512; +using CryptoPP::LSH::LSH512_StepConstants; + +typedef byte lsh_u8; +typedef word32 lsh_u32; +typedef word64 lsh_u64; +typedef word32 lsh_uint; +typedef word32 lsh_err; +typedef word32 lsh_type; + +struct LSH512_SSSE3_Context +{ + LSH512_SSSE3_Context(word64* state, word64 algType, word64& remainingBitLength) : + cv_l(state+0), cv_r(state+8), sub_msgs(state+16), + last_block(reinterpret_cast(state+48)), + remain_databitlen(remainingBitLength), + alg_type(static_cast(algType)) {} + + lsh_u64* cv_l; // start of our state block + lsh_u64* cv_r; + lsh_u64* sub_msgs; + lsh_u8* last_block; + lsh_u64& remain_databitlen; + lsh_type alg_type; +}; + +struct LSH512_SSSE3_Internal +{ + LSH512_SSSE3_Internal(word64* state) : + submsg_e_l(state+16), submsg_e_r(state+24), + submsg_o_l(state+32), submsg_o_r(state+40) { } + + lsh_u64* submsg_e_l; /* even left sub-message */ + lsh_u64* submsg_e_r; /* even right sub-message */ + lsh_u64* submsg_o_l; /* odd left sub-message */ + lsh_u64* submsg_o_r; /* odd right sub-message */ +}; + +// const lsh_u32 g_gamma512[8] = { 0, 16, 32, 48, 8, 24, 40, 56 }; + +/* LSH AlgType Macro */ + +inline bool LSH_IS_LSH512(lsh_uint val) { + return (val & 0xf0000) == 0x10000; +} + +inline lsh_uint LSH_GET_SMALL_HASHBIT(lsh_uint val) { + return val >> 24; +} + +inline lsh_uint LSH_GET_HASHBYTE(lsh_uint val) { + return val & 0xffff; +} + +inline lsh_uint LSH_GET_HASHBIT(lsh_uint val) { + return (LSH_GET_HASHBYTE(val) << 3) - LSH_GET_SMALL_HASHBIT(val); +} + +inline lsh_u64 loadLE64(lsh_u64 v) { + return ConditionalByteReverse(LITTLE_ENDIAN_ORDER, v); +} + +lsh_u64 ROTL64(lsh_u64 x, lsh_u32 r) { + return rotlFixed(x, r); +} + +// Original code relied upon unaligned lsh_u64 buffer +inline void load_msg_blk(LSH512_SSSE3_Internal* i_state, const lsh_u8 msgblk[LSH512_MSG_BLK_BYTE_LEN]) +{ + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + _mm_storeu_si128(M128_CAST(submsg_e_l+0), + _mm_loadu_si128(CONST_M128_CAST(msgblk+0))); + _mm_storeu_si128(M128_CAST(submsg_e_l+2), + _mm_loadu_si128(CONST_M128_CAST(msgblk+16))); + _mm_storeu_si128(M128_CAST(submsg_e_l+4), + _mm_loadu_si128(CONST_M128_CAST(msgblk+32))); + _mm_storeu_si128(M128_CAST(submsg_e_l+6), + _mm_loadu_si128(CONST_M128_CAST(msgblk+48))); + + _mm_storeu_si128(M128_CAST(submsg_e_r+0), + _mm_loadu_si128(CONST_M128_CAST(msgblk+64))); + _mm_storeu_si128(M128_CAST(submsg_e_r+2), + _mm_loadu_si128(CONST_M128_CAST(msgblk+80))); + _mm_storeu_si128(M128_CAST(submsg_e_r+4), + _mm_loadu_si128(CONST_M128_CAST(msgblk+96))); + _mm_storeu_si128(M128_CAST(submsg_e_r+6), + _mm_loadu_si128(CONST_M128_CAST(msgblk+112))); + + _mm_storeu_si128(M128_CAST(submsg_o_l+0), + _mm_loadu_si128(CONST_M128_CAST(msgblk+128))); + _mm_storeu_si128(M128_CAST(submsg_o_l+2), + _mm_loadu_si128(CONST_M128_CAST(msgblk+144))); + _mm_storeu_si128(M128_CAST(submsg_o_l+4), + _mm_loadu_si128(CONST_M128_CAST(msgblk+160))); + _mm_storeu_si128(M128_CAST(submsg_o_l+6), + _mm_loadu_si128(CONST_M128_CAST(msgblk+176))); + + _mm_storeu_si128(M128_CAST(submsg_o_r+0), + _mm_loadu_si128(CONST_M128_CAST(msgblk+192))); + _mm_storeu_si128(M128_CAST(submsg_o_r+2), + _mm_loadu_si128(CONST_M128_CAST(msgblk+208))); + _mm_storeu_si128(M128_CAST(submsg_o_r+4), + _mm_loadu_si128(CONST_M128_CAST(msgblk+224))); + _mm_storeu_si128(M128_CAST(submsg_o_r+6), + _mm_loadu_si128(CONST_M128_CAST(msgblk+240))); +} + +inline void msg_exp_even(LSH512_SSSE3_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + __m128i temp; + _mm_storeu_si128(M128_CAST(submsg_e_l+2), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+2)), _MM_SHUFFLE(1,0,3,2))); + + temp = _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+0)); + _mm_storeu_si128(M128_CAST(submsg_e_l+0), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+2))); + _mm_storeu_si128(M128_CAST(submsg_e_l+2), temp); + _mm_storeu_si128(M128_CAST(submsg_e_l+6), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+6)), _MM_SHUFFLE(1,0,3,2))); + + temp = _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+4)); + _mm_storeu_si128(M128_CAST(submsg_e_l+4), _mm_unpacklo_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+4)))); + _mm_storeu_si128(M128_CAST(submsg_e_l+6), _mm_unpackhi_epi64( + temp, _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+6)))); + _mm_storeu_si128(M128_CAST(submsg_e_r+2), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+2)), _MM_SHUFFLE(1,0,3,2))); + + temp = _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+0)); + _mm_storeu_si128(M128_CAST(submsg_e_r+0), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+2))); + _mm_storeu_si128(M128_CAST(submsg_e_r+2), temp); + _mm_storeu_si128(M128_CAST(submsg_e_r+6), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+6)), _MM_SHUFFLE(1,0,3,2))); + + temp = _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+4)); + _mm_storeu_si128(M128_CAST(submsg_e_r+4), _mm_unpacklo_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+4)))); + _mm_storeu_si128(M128_CAST(submsg_e_r+6), _mm_unpackhi_epi64( + temp, _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+6)))); + + _mm_storeu_si128(M128_CAST(submsg_e_l+0), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+0)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+0)))); + _mm_storeu_si128(M128_CAST(submsg_e_l+2), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+2)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+2)))); + _mm_storeu_si128(M128_CAST(submsg_e_l+4), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+4)))); + _mm_storeu_si128(M128_CAST(submsg_e_l+6), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+6)))); + + _mm_storeu_si128(M128_CAST(submsg_e_r+0), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+0)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+0)))); + _mm_storeu_si128(M128_CAST(submsg_e_r+2), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+2)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+2)))); + _mm_storeu_si128(M128_CAST(submsg_e_r+4), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+4)))); + _mm_storeu_si128(M128_CAST(submsg_e_r+6), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+6)))); +} + +inline void msg_exp_odd(LSH512_SSSE3_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + __m128i temp; + _mm_storeu_si128(M128_CAST(submsg_o_l+2), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+2)), _MM_SHUFFLE(1,0,3,2))); + + temp = _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+0)); + _mm_storeu_si128(M128_CAST(submsg_o_l+0), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+2))); + _mm_storeu_si128(M128_CAST(submsg_o_l+2), temp); + _mm_storeu_si128(M128_CAST(submsg_o_l+6), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+6)), _MM_SHUFFLE(1,0,3,2))); + + temp = _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+4)); + _mm_storeu_si128(M128_CAST(submsg_o_l+4), _mm_unpacklo_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+4)))); + _mm_storeu_si128(M128_CAST(submsg_o_l+6), _mm_unpackhi_epi64( + temp, _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+6)))); + _mm_storeu_si128(M128_CAST(submsg_o_r+2), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+2)), _MM_SHUFFLE(1,0,3,2))); + + temp = _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+0)); + _mm_storeu_si128(M128_CAST(submsg_o_r+0), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+2))); + _mm_storeu_si128(M128_CAST(submsg_o_r+2), temp); + _mm_storeu_si128(M128_CAST(submsg_o_r+6), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+6)), _MM_SHUFFLE(1,0,3,2))); + + temp = _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+4)); + _mm_storeu_si128(M128_CAST(submsg_o_r+4), _mm_unpacklo_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+4)))); + _mm_storeu_si128(M128_CAST(submsg_o_r+6), _mm_unpackhi_epi64( + temp, _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+6)))); + + _mm_storeu_si128(M128_CAST(submsg_o_l+0), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+0)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+0)))); + _mm_storeu_si128(M128_CAST(submsg_o_l+2), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+2)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+2)))); + _mm_storeu_si128(M128_CAST(submsg_o_l+4), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+4)))); + _mm_storeu_si128(M128_CAST(submsg_o_l+6), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+6)))); + + _mm_storeu_si128(M128_CAST(submsg_o_r+0), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+0)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+0)))); + _mm_storeu_si128(M128_CAST(submsg_o_r+2), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+2)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+2)))); + _mm_storeu_si128(M128_CAST(submsg_o_r+4), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+4)))); + _mm_storeu_si128(M128_CAST(submsg_o_r+6), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+6)))); +} + +inline void load_sc(const lsh_u64** p_const_v, size_t i) +{ + *p_const_v = &LSH512_StepConstants[i]; +} + +inline void msg_add_even(lsh_u64 cv_l[8], lsh_u64 cv_r[8], LSH512_SSSE3_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_e_l = i_state->submsg_e_l; + lsh_u64* submsg_e_r = i_state->submsg_e_r; + + _mm_storeu_si128(M128_CAST(cv_l), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l)))); + _mm_storeu_si128(M128_CAST(cv_r), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r)))); + _mm_storeu_si128(M128_CAST(cv_l+2), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+2)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+2)))); + _mm_storeu_si128(M128_CAST(cv_r+2), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r+2)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+2)))); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+4)))); + _mm_storeu_si128(M128_CAST(cv_r+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+4)))); + _mm_storeu_si128(M128_CAST(cv_l+6), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_l+6)))); + _mm_storeu_si128(M128_CAST(cv_r+6), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_e_r+6)))); +} + +inline void msg_add_odd(lsh_u64 cv_l[8], lsh_u64 cv_r[8], LSH512_SSSE3_Internal* i_state) +{ + CRYPTOPP_ASSERT(i_state != NULLPTR); + + lsh_u64* submsg_o_l = i_state->submsg_o_l; + lsh_u64* submsg_o_r = i_state->submsg_o_r; + + _mm_storeu_si128(M128_CAST(cv_l), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l)))); + _mm_storeu_si128(M128_CAST(cv_r), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r)))); + _mm_storeu_si128(M128_CAST(cv_l+2), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+2)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+2)))); + _mm_storeu_si128(M128_CAST(cv_r+2), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r+2)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+2)))); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+4)))); + _mm_storeu_si128(M128_CAST(cv_r+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r+4)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+4)))); + _mm_storeu_si128(M128_CAST(cv_l+6), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_l+6)))); + _mm_storeu_si128(M128_CAST(cv_r+6), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_r+6)), + _mm_loadu_si128(CONST_M128_CAST(submsg_o_r+6)))); +} + +inline void add_blk(lsh_u64 cv_l[8], lsh_u64 cv_r[8]) +{ + _mm_storeu_si128(M128_CAST(cv_l), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_l)), + _mm_loadu_si128(CONST_M128_CAST(cv_r)))); + _mm_storeu_si128(M128_CAST(cv_l+2), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_l+2)), + _mm_loadu_si128(CONST_M128_CAST(cv_r+2)))); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(cv_r+4)))); + _mm_storeu_si128(M128_CAST(cv_l+6), _mm_add_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_l+6)), + _mm_loadu_si128(CONST_M128_CAST(cv_r+6)))); +} + +template +inline void rotate_blk(lsh_u64 cv[8]) +{ +#if defined(CRYPTOPP_XOP_AVAILABLE) + _mm_storeu_si128(M128_CAST(cv), + _mm_roti_epi64(_mm_loadu_si128(CONST_M128_CAST(cv)), R)); + _mm_storeu_si128(M128_CAST(cv+2), + _mm_roti_epi64(_mm_loadu_si128(CONST_M128_CAST(cv+2)), R)); + _mm_storeu_si128(M128_CAST(cv+4), + _mm_roti_epi64(_mm_loadu_si128(CONST_M128_CAST(cv+4)), R)); + _mm_storeu_si128(M128_CAST(cv+6), + _mm_roti_epi64(_mm_loadu_si128(CONST_M128_CAST(cv+6)), R)); + +#else + _mm_storeu_si128(M128_CAST(cv), _mm_or_si128( + _mm_slli_epi64(_mm_loadu_si128(CONST_M128_CAST(cv)), R), + _mm_srli_epi64(_mm_loadu_si128(CONST_M128_CAST(cv)), 64-R))); + _mm_storeu_si128(M128_CAST(cv+2), _mm_or_si128( + _mm_slli_epi64(_mm_loadu_si128(CONST_M128_CAST(cv+2)), R), + _mm_srli_epi64(_mm_loadu_si128(CONST_M128_CAST(cv+2)), 64-R))); + _mm_storeu_si128(M128_CAST(cv+4), _mm_or_si128( + _mm_slli_epi64(_mm_loadu_si128(CONST_M128_CAST(cv+4)), R), + _mm_srli_epi64(_mm_loadu_si128(CONST_M128_CAST(cv+4)), 64-R))); + _mm_storeu_si128(M128_CAST(cv+6), _mm_or_si128( + _mm_slli_epi64(_mm_loadu_si128(CONST_M128_CAST(cv+6)), R), + _mm_srli_epi64(_mm_loadu_si128(CONST_M128_CAST(cv+6)), 64-R))); +#endif +} + +inline void xor_with_const(lsh_u64 cv_l[8], const lsh_u64 const_v[8]) +{ + _mm_storeu_si128(M128_CAST(cv_l), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l)), + _mm_loadu_si128(CONST_M128_CAST(const_v)))); + _mm_storeu_si128(M128_CAST(cv_l+2), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+2)), + _mm_loadu_si128(CONST_M128_CAST(const_v+2)))); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(const_v+4)))); + _mm_storeu_si128(M128_CAST(cv_l+6), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(cv_l+6)), + _mm_loadu_si128(CONST_M128_CAST(const_v+6)))); +} + +inline void rotate_msg_gamma(lsh_u64 cv_r[8]) +{ + // g_gamma512[8] = { 0, 16, 32, 48, 8, 24, 40, 56 }; + _mm_storeu_si128(M128_CAST(cv_r+0), + _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(cv_r+0)), + _mm_set_epi8(13,12,11,10, 9,8,15,14, 7,6,5,4, 3,2,1,0))); + _mm_storeu_si128(M128_CAST(cv_r+2), + _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(cv_r+2)), + _mm_set_epi8(9,8,15,14, 13,12,11,10, 3,2,1,0, 7,6,5,4))); + + _mm_storeu_si128(M128_CAST(cv_r+4), + _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(cv_r+4)), + _mm_set_epi8(12,11,10,9, 8,15,14,13, 6,5,4,3, 2,1,0,7))); + _mm_storeu_si128(M128_CAST(cv_r+6), + _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(cv_r+6)), + _mm_set_epi8(8,15,14,13, 12,11,10,9, 2,1,0,7, 6,5,4,3))); +} + +inline void word_perm(lsh_u64 cv_l[8], lsh_u64 cv_r[8]) +{ + __m128i temp[2]; + temp[0] = _mm_loadu_si128(CONST_M128_CAST(cv_l+0)); + _mm_storeu_si128(M128_CAST(cv_l+0), _mm_unpacklo_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_l+2)), + _mm_loadu_si128(CONST_M128_CAST(cv_l+0)))); + _mm_storeu_si128(M128_CAST(cv_l+2), _mm_unpackhi_epi64( + temp[0], _mm_loadu_si128(CONST_M128_CAST(cv_l+2)))); + + temp[0] = _mm_loadu_si128(CONST_M128_CAST(cv_l+4)); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_unpacklo_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_l+6)), + _mm_loadu_si128(CONST_M128_CAST(cv_l+4)))); + _mm_storeu_si128(M128_CAST(cv_l+6), _mm_unpackhi_epi64( + temp[0], _mm_loadu_si128(CONST_M128_CAST(cv_l+6)))); + _mm_storeu_si128(M128_CAST(cv_r+2), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(cv_r+2)), _MM_SHUFFLE(1,0,3,2))); + + temp[0] = _mm_loadu_si128(CONST_M128_CAST(cv_r+0)); + _mm_storeu_si128(M128_CAST(cv_r+0), _mm_unpacklo_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_r+0)), + _mm_loadu_si128(CONST_M128_CAST(cv_r+2)))); + _mm_storeu_si128(M128_CAST(cv_r+2), _mm_unpackhi_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_r+2)), temp[0])); + _mm_storeu_si128(M128_CAST(cv_r+6), _mm_shuffle_epi32( + _mm_loadu_si128(CONST_M128_CAST(cv_r+6)), _MM_SHUFFLE(1,0,3,2))); + + temp[0] = _mm_loadu_si128(CONST_M128_CAST(cv_r+4)); + _mm_storeu_si128(M128_CAST(cv_r+4), _mm_unpacklo_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_r+4)), + _mm_loadu_si128(CONST_M128_CAST(cv_r+6)))); + _mm_storeu_si128(M128_CAST(cv_r+6), _mm_unpackhi_epi64( + _mm_loadu_si128(CONST_M128_CAST(cv_r+6)), temp[0])); + + temp[0] = _mm_loadu_si128(CONST_M128_CAST(cv_l+0)); + temp[1] = _mm_loadu_si128(CONST_M128_CAST(cv_l+2)); + + _mm_storeu_si128(M128_CAST(cv_l+0), + _mm_loadu_si128(CONST_M128_CAST(cv_l+4))); + _mm_storeu_si128(M128_CAST(cv_l+2), + _mm_loadu_si128(CONST_M128_CAST(cv_l+6))); + _mm_storeu_si128(M128_CAST(cv_l+4), + _mm_loadu_si128(CONST_M128_CAST(cv_r+4))); + _mm_storeu_si128(M128_CAST(cv_l+6), + _mm_loadu_si128(CONST_M128_CAST(cv_r+6))); + _mm_storeu_si128(M128_CAST(cv_r+4), + _mm_loadu_si128(CONST_M128_CAST(cv_r+0))); + _mm_storeu_si128(M128_CAST(cv_r+6), + _mm_loadu_si128(CONST_M128_CAST(cv_r+2))); + + _mm_storeu_si128(M128_CAST(cv_r+0), temp[0]); + _mm_storeu_si128(M128_CAST(cv_r+2), temp[1]); +}; + +/* -------------------------------------------------------- * +* step function +* -------------------------------------------------------- */ + +template +inline void mix(lsh_u64 cv_l[8], lsh_u64 cv_r[8], const lsh_u64 const_v[8]) +{ + add_blk(cv_l, cv_r); + rotate_blk(cv_l); + xor_with_const(cv_l, const_v); + add_blk(cv_r, cv_l); + rotate_blk(cv_r); + add_blk(cv_l, cv_r); + rotate_msg_gamma(cv_r); +} + +/* -------------------------------------------------------- * +* compression function +* -------------------------------------------------------- */ + +inline void compress(LSH512_SSSE3_Context* ctx, const lsh_u8 pdMsgBlk[LSH512_MSG_BLK_BYTE_LEN]) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + LSH512_SSSE3_Internal s_state(ctx->cv_l); + LSH512_SSSE3_Internal* i_state = &s_state; + + const lsh_u64* const_v = NULL; + lsh_u64 *cv_l = ctx->cv_l; + lsh_u64 *cv_r = ctx->cv_r; + + load_msg_blk(i_state, pdMsgBlk); + + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 0); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + for (size_t i = 1; i < NUM_STEPS / 2; i++) + { + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + msg_exp_odd(i_state); + msg_add_odd(cv_l, cv_r, i_state); + load_sc(&const_v, 16 * i + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + msg_exp_even(i_state); + msg_add_even(cv_l, cv_r, i_state); +} + +/* -------------------------------------------------------- */ + +inline void load_iv(word64 cv_l[8], word64 cv_r[8], const word64 iv[16]) +{ + // The IV's are 32-byte aligned so we can use aligned loads. + _mm_storeu_si128(M128_CAST(cv_l+0), + _mm_load_si128(CONST_M128_CAST(iv+0))); + _mm_storeu_si128(M128_CAST(cv_l+2), + _mm_load_si128(CONST_M128_CAST(iv+2))); + _mm_storeu_si128(M128_CAST(cv_l+4), + _mm_load_si128(CONST_M128_CAST(iv+4))); + _mm_storeu_si128(M128_CAST(cv_l+6), + _mm_load_si128(CONST_M128_CAST(iv+6))); + _mm_storeu_si128(M128_CAST(cv_r+0), + _mm_load_si128(CONST_M128_CAST(iv+8))); + _mm_storeu_si128(M128_CAST(cv_r+2), + _mm_load_si128(CONST_M128_CAST(iv+10))); + _mm_storeu_si128(M128_CAST(cv_r+4), + _mm_load_si128(CONST_M128_CAST(iv+12))); + _mm_storeu_si128(M128_CAST(cv_r+6), + _mm_load_si128(CONST_M128_CAST(iv+14))); +} + +inline void zero_iv(lsh_u64 cv_l[8], lsh_u64 cv_r[8]) +{ + _mm_storeu_si128(M128_CAST(cv_l+0), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_l+2), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_l+4), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_l+6), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_r+0), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_r+2), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_r+4), _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(cv_r+6), _mm_setzero_si128()); +} + +inline void zero_submsgs(LSH512_SSSE3_Context* ctx) +{ + lsh_u64* sub_msgs = ctx->sub_msgs; + + _mm_storeu_si128(M128_CAST(sub_msgs+ 0), + _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+ 2), + _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+ 4), + _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+ 6), + _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+ 8), + _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+10), + _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+12), + _mm_setzero_si128()); + _mm_storeu_si128(M128_CAST(sub_msgs+14), + _mm_setzero_si128()); +} + +inline void init224(LSH512_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV224); +} + +inline void init256(LSH512_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV256); +} + +inline void init384(LSH512_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV384); +} + +inline void init512(LSH512_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + zero_submsgs(ctx); + load_iv(ctx->cv_l, ctx->cv_r, LSH512_IV512); +} + +/* -------------------------------------------------------- */ + +inline void fin(LSH512_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + + _mm_storeu_si128(M128_CAST(ctx->cv_l+0), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_l+0)), + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_r+0)))); + _mm_storeu_si128(M128_CAST(ctx->cv_l+2), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_l+2)), + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_r+2)))); + _mm_storeu_si128(M128_CAST(ctx->cv_l+4), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_l+4)), + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_r+4)))); + _mm_storeu_si128(M128_CAST(ctx->cv_l+6), _mm_xor_si128( + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_l+6)), + _mm_loadu_si128(CONST_M128_CAST(ctx->cv_r+6)))); +} + +/* -------------------------------------------------------- */ + +inline void get_hash(LSH512_SSSE3_Context* ctx, lsh_u8* pbHashVal) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + CRYPTOPP_ASSERT(pbHashVal != NULLPTR); + + lsh_uint alg_type = ctx->alg_type; + lsh_uint hash_val_byte_len = LSH_GET_HASHBYTE(alg_type); + lsh_uint hash_val_bit_len = LSH_GET_SMALL_HASHBIT(alg_type); + + // Multiplying by sizeof(lsh_u8) looks odd... + memcpy(pbHashVal, ctx->cv_l, hash_val_byte_len); + if (hash_val_bit_len){ + pbHashVal[hash_val_byte_len-1] &= (((lsh_u8)0xff) << hash_val_bit_len); + } +} + +/* -------------------------------------------------------- */ + +lsh_err lsh512_init_ssse3(LSH512_SSSE3_Context* ctx) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + lsh_u32 alg_type = ctx->alg_type; + const lsh_u64* const_v = NULL; + ctx->remain_databitlen = 0; + + switch (alg_type){ + case LSH_TYPE_512_512: + init512(ctx); + return LSH_SUCCESS; + case LSH_TYPE_512_384: + init384(ctx); + return LSH_SUCCESS; + case LSH_TYPE_512_256: + init256(ctx); + return LSH_SUCCESS; + case LSH_TYPE_512_224: + init224(ctx); + return LSH_SUCCESS; + default: + break; + } + + lsh_u64* cv_l = ctx->cv_l; + lsh_u64* cv_r = ctx->cv_r; + + zero_iv(cv_l, cv_r); + cv_l[0] = LSH512_HASH_VAL_MAX_BYTE_LEN; + cv_l[1] = LSH_GET_HASHBIT(alg_type); + + for (size_t i = 0; i < NUM_STEPS / 2; i++) + { + //Mix + load_sc(&const_v, i * 16); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + + load_sc(&const_v, i * 16 + 8); + mix(cv_l, cv_r, const_v); + word_perm(cv_l, cv_r); + } + + return LSH_SUCCESS; +} + +lsh_err lsh512_update_ssse3(LSH512_SSSE3_Context* ctx, const lsh_u8* data, size_t databitlen) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(data != NULLPTR); + CRYPTOPP_ASSERT(databitlen % 8 == 0); + CRYPTOPP_ASSERT(ctx->alg_type != 0); + + if (databitlen == 0){ + return LSH_SUCCESS; + } + + // We are byte oriented. tail bits will always be 0. + size_t databytelen = databitlen >> 3; + // lsh_uint pos2 = databitlen & 0x7; + const size_t pos2 = 0; + + size_t remain_msg_byte = static_cast(ctx->remain_databitlen >> 3); + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH512_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + if (remain_msg_bit > 0){ + return LSH_ERR_INVALID_DATABITLEN; + } + + if (databytelen + remain_msg_byte < LSH512_MSG_BLK_BYTE_LEN){ + memcpy(ctx->last_block + remain_msg_byte, data, databytelen); + ctx->remain_databitlen += (lsh_uint)databitlen; + remain_msg_byte += (lsh_uint)databytelen; + if (pos2){ + ctx->last_block[remain_msg_byte] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + } + return LSH_SUCCESS; + } + + if (remain_msg_byte > 0){ + size_t more_byte = LSH512_MSG_BLK_BYTE_LEN - remain_msg_byte; + memcpy(ctx->last_block + remain_msg_byte, data, more_byte); + compress(ctx, ctx->last_block); + data += more_byte; + databytelen -= more_byte; + remain_msg_byte = 0; + ctx->remain_databitlen = 0; + } + + while (databytelen >= LSH512_MSG_BLK_BYTE_LEN) + { + // This call to compress caused some trouble. + // The data pointer can become unaligned in the + // previous block. + compress(ctx, data); + data += LSH512_MSG_BLK_BYTE_LEN; + databytelen -= LSH512_MSG_BLK_BYTE_LEN; + } + + if (databytelen > 0){ + memcpy(ctx->last_block, data, databytelen); + ctx->remain_databitlen = (lsh_uint)(databytelen << 3); + } + + if (pos2){ + ctx->last_block[databytelen] = data[databytelen] & ((0xff >> pos2) ^ 0xff); + ctx->remain_databitlen += pos2; + } + return LSH_SUCCESS; +} + +lsh_err lsh512_final_ssse3(LSH512_SSSE3_Context* ctx, lsh_u8* hashval) +{ + CRYPTOPP_ASSERT(ctx != NULLPTR); + CRYPTOPP_ASSERT(hashval != NULLPTR); + + // We are byte oriented. tail bits will always be 0. + size_t remain_msg_byte = static_cast(ctx->remain_databitlen >> 3); + // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7; + const size_t remain_msg_bit = 0; + + if (remain_msg_byte >= LSH512_MSG_BLK_BYTE_LEN){ + return LSH_ERR_INVALID_STATE; + } + + if (remain_msg_bit){ + ctx->last_block[remain_msg_byte] |= (0x1 << (7 - remain_msg_bit)); + } + else{ + ctx->last_block[remain_msg_byte] = 0x80; + } + memset(ctx->last_block + remain_msg_byte + 1, 0, LSH512_MSG_BLK_BYTE_LEN - remain_msg_byte - 1); + + compress(ctx, ctx->last_block); + + fin(ctx); + get_hash(ctx, hashval); + + return LSH_SUCCESS; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +extern +void LSH512_Base_Restart_SSSE3(word64* state) +{ + state[RemainingBits] = 0; + LSH512_SSSE3_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh512_init_ssse3(&ctx); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH512_Base: lsh512_init_ssse3 failed"); +} + +extern +void LSH512_Base_Update_SSSE3(word64* state, const byte *input, size_t size) +{ + LSH512_SSSE3_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh512_update_ssse3(&ctx, input, 8*size); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH512_Base: lsh512_update_ssse3 failed"); +} + +extern +void LSH512_Base_TruncatedFinal_SSSE3(word64* state, byte *hash, size_t) +{ + LSH512_SSSE3_Context ctx(state, state[AlgorithmType], state[RemainingBits]); + lsh_err err = lsh512_final_ssse3(&ctx, hash); + + if (err != LSH_SUCCESS) + throw Exception(Exception::OTHER_ERROR, "LSH512_Base: lsh512_final_ssse3 failed"); +} + +NAMESPACE_END + +#endif // CRYPTOPP_SSSE3_AVAILABLE diff --git a/external/ours/library/crypto/src/shared/original/lubyrack.h b/external/ours/library/crypto/src/shared/original/lubyrack.h new file mode 100755 index 000000000..a5d6a18db --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 + 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/external/ours/library/crypto/src/shared/original/luc.cpp b/external/ours/library/crypto/src/shared/original/luc.cpp new file mode 100755 index 000000000..9a25662c3 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/luc.cpp @@ -0,0 +1,231 @@ +// luc.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "luc.h" +#include "asn.h" +#include "sha.h" +#include "integer.h" +#include "nbtheory.h" +#include "algparam.h" +#include "pkcspad.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void LUC_TestInstantiations() +{ + LUC_HMP::Signer t1; + LUCFunction t2; + InvertibleLUCFunction t3; +} +#endif + +void DL_Algorithm_LUC_HMP::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 = params.ExponentiateBase(k); + s = (k + x*(r+e)) % q; +} + +bool DL_Algorithm_LUC_HMP::Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const +{ + const Integer p = params.GetGroupOrder()-1; + const Integer &q = params.GetSubgroupOrder(); + + Integer Vsg = params.ExponentiateBase(s); + Integer Vry = publicKey.ExponentiatePublicElement((r+e)%q); + return (Vsg*Vsg + Vry*Vry + r*r) % p == (Vsg * Vry * r + 4) % p; +} + +Integer DL_BasePrecomputation_LUC::Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const +{ + return Lucas(exponent, m_g, static_cast(group).GetModulus()); +} + +void DL_GroupParameters_LUC::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const +{ + for (unsigned int i=0; i Integer::One() && m_n.IsOdd(); + CRYPTOPP_ASSERT(pass); + pass = pass && m_e > Integer::One() && m_e.IsOdd() && m_e < m_n; + CRYPTOPP_ASSERT(pass); + return pass; +} + +bool LUCFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent) + ; +} + +void LUCFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent) + ; +} + +// ***************************************************************************** +// private key operations: + +class LUCPrimeSelector : public PrimeSelector +{ +public: + LUCPrimeSelector(const Integer &e) : m_e(e) {} + bool IsAcceptable(const Integer &candidate) const + { + return RelativelyPrime(m_e, candidate+1) && RelativelyPrime(m_e, candidate-1); + } + Integer m_e; +}; + +void InvertibleLUCFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + int modulusSize = 2048; + alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize); + + if (modulusSize < 16) + throw InvalidArgument("InvertibleLUCFunction: specified modulus size is too small"); + + m_e = alg.GetValueWithDefault("PublicExponent", Integer(17)); + + if (m_e < 5 || m_e.IsEven()) + throw InvalidArgument("InvertibleLUCFunction: invalid public exponent"); + + LUCPrimeSelector selector(m_e); + AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize) + ("PointerToPrimeSelector", selector.GetSelectorPointer()); + m_p.GenerateRandom(rng, primeParam); + m_q.GenerateRandom(rng, primeParam); + + m_n = m_p * m_q; + m_u = m_q.InverseMod(m_p); +} + +void InvertibleLUCFunction::Initialize(RandomNumberGenerator &rng, unsigned int keybits, const Integer &e) +{ + GenerateRandom(rng, MakeParameters("ModulusSize", (int)keybits)("PublicExponent", e)); +} + +void InvertibleLUCFunction::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + + Integer version(seq); + if (!!version) // make sure version is 0 + BERDecodeError(); + + m_n.BERDecode(seq); + m_e.BERDecode(seq); + m_p.BERDecode(seq); + m_q.BERDecode(seq); + m_u.BERDecode(seq); + seq.MessageEnd(); +} + +void InvertibleLUCFunction::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + + const byte version[] = {INTEGER, 1, 0}; + seq.Put(version, sizeof(version)); + m_n.DEREncode(seq); + m_e.DEREncode(seq); + m_p.DEREncode(seq); + m_q.DEREncode(seq); + m_u.DEREncode(seq); + seq.MessageEnd(); +} + +Integer InvertibleLUCFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const +{ + // not clear how to do blinding with LUC + CRYPTOPP_UNUSED(rng); + DoQuickSanityCheck(); + return InverseLucas(m_e, x, m_q, m_p, m_u); +} + +bool InvertibleLUCFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = LUCFunction::Validate(rng, level); + CRYPTOPP_ASSERT(pass); + pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_u.IsPositive() && m_u < m_p; + CRYPTOPP_ASSERT(pass); + if (level >= 1) + { + pass = pass && m_p * m_q == m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && RelativelyPrime(m_e, m_p+1); + CRYPTOPP_ASSERT(pass); + pass = pass && RelativelyPrime(m_e, m_p-1); + CRYPTOPP_ASSERT(pass); + pass = pass && RelativelyPrime(m_e, m_q+1); + CRYPTOPP_ASSERT(pass); + pass = pass && RelativelyPrime(m_e, m_q-1); + CRYPTOPP_ASSERT(pass); + pass = pass && m_u * m_q % m_p == 1; + CRYPTOPP_ASSERT(pass); + } + if (level >= 2) + { + pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2); + CRYPTOPP_ASSERT(pass); + } + return pass; +} + +bool InvertibleLUCFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_GET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; +} + +void InvertibleLUCFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/luc.h b/external/ours/library/crypto/src/shared/original/luc.h new file mode 100755 index 000000000..9483a6d81 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/mars.cpp b/external/ours/library/crypto/src/shared/original/mars.cpp new file mode 100755 index 000000000..a8d69439f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/mars.cpp @@ -0,0 +1,154 @@ +// mars.cpp - originally written and placed in the public domain by Wei Dai + +// includes IBM's key setup "tweak" proposed in August 1999 (http://www.research.ibm.com/security/key-setup.txt) + +#include "pch.h" +#include "mars.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +void MARS::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + // Initialize T[] with the key data + FixedSizeSecBlock T; + GetUserKey(LITTLE_ENDIAN_ORDER, T.begin(), 15, userKey, length); + T[length/4] = length/4; + + for (unsigned int j=0; j<4; j++) // compute 10 words of K[] in each iteration + { + unsigned int i; + // Do linear transformation + for (i=0; i<15; i++) + T[i] = T[i] ^ rotlConstant<3>(T[(i + 8) % 15] ^ T[(i + 13) % 15]) ^ (4 * i + j); + + // Do four rounds of stirring + for (unsigned int k=0; k<4; k++) + for (i=0; i<15; i++) + T[i] = rotlConstant<9>(T[i] + Sbox[T[(i + 14) % 15] % 512]); + + // Store next 10 key words into K[] + for (i=0; i<10; i++) + m_k[10*j+i] = T[4*i%15]; + } + + // Modify multiplication key-words + for(unsigned int i = 5; i < 37; i += 2) + { + word32 m, w = m_k[i] | 3; + m = (~w ^ (w<<1)) & (~w ^ (w>>1)) & 0x7ffffffe; + m &= m>>1; m &= m>>2; m &= m>>4; + m |= m<<1; m |= m<<2; m |= m<<4; + m &= 0x7ffffffc; + w ^= rotlMod(Sbox[265 + (m_k[i] & 3)], m_k[i-1]) & m; + m_k[i] = w; + } +} + +#define S(a) Sbox[(a)&0x1ff] +#define S0(a) Sbox[(a)&0xff] +#define S1(a) Sbox[((a)&0xff) + 256] + +typedef BlockGetAndPut Block; + +void MARS::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + unsigned int i; + word32 a, b, c, d, l, m, r, t; + const word32 *k = m_k; + + Block::Get(inBlock)(a)(b)(c)(d); + + a += k[0]; b += k[1]; c += k[2]; d += k[3]; + + for (i=0; i<8; i++) + { + b = (b ^ S0(a)) + S1(a>>8); + c += S0(a>>16); + a = rotrConstant<24>(a); + d ^= S1(a); + a += (i%4==0) ? d : 0; + a += (i%4==1) ? b : 0; + t = a; a = b; b = c; c = d; d = t; + } + + for (i=0; i<16; i++) + { + t = rotlConstant<13>(a); + r = rotlConstant<10>(t * k[2 * i + 5]); + m = a + k[2*i+4]; + l = rotlMod((S(m) ^ rotrConstant<5>(r) ^ r), r); + c += rotlMod(m, rotrConstant<5>(r)); + (i<8 ? b : d) += l; + (i<8 ? d : b) ^= r; + a = b; b = c; c = d; d = t; + } + + for (i=0; i<8; i++) + { + a -= (i%4==2) ? d : 0; + a -= (i%4==3) ? b : 0; + b ^= S1(a); + c -= S0(a>>24); + t = rotlConstant<24>(a); + d = (d - S1(a>>16)) ^ S0(t); + a = b; b = c; c = d; d = t; + } + + a -= k[36]; b -= k[37]; c -= k[38]; d -= k[39]; + + Block::Put(xorBlock, outBlock)(a)(b)(c)(d); +} + +void MARS::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + unsigned int i; + word32 a, b, c, d, l, m, r, t; + const word32 *k = m_k; + + Block::Get(inBlock)(d)(c)(b)(a); + + d += k[36]; c += k[37]; b += k[38]; a += k[39]; + + for (i=0; i<8; i++) + { + b = (b ^ S0(a)) + S1(a>>8); + c += S0(a>>16); + a = rotrConstant<24>(a); + d ^= S1(a); + a += (i%4==0) ? d : 0; + a += (i%4==1) ? b : 0; + t = a; a = b; b = c; c = d; d = t; + } + + for (i=0; i<16; i++) + { + t = rotrConstant<13>(a); + r = rotlConstant<10>(a * k[35 - 2 * i]); + m = t + k[34-2*i]; + l = rotlMod((S(m) ^ rotrConstant<5>(r) ^ r), r); + c -= rotlMod(m, rotrConstant<5>(r)); + (i<8 ? b : d) -= l; + (i<8 ? d : b) ^= r; + a = b; b = c; c = d; d = t; + } + + for (i=0; i<8; i++) + { + a -= (i%4==2) ? d : 0; + a -= (i%4==3) ? b : 0; + b ^= S1(a); + c -= S0(a>>24); + t = rotlConstant<24>(a); + d = (d - S1(a>>16)) ^ S0(t); + a = b; b = c; c = d; d = t; + } + + d -= k[0]; c -= k[1]; b -= k[2]; a -= k[3]; + + Block::Put(xorBlock, outBlock)(d)(c)(b)(a); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/mars.h b/external/ours/library/crypto/src/shared/original/mars.h new file mode 100755 index 000000000..1a1f20191 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/marss.cpp b/external/ours/library/crypto/src/shared/original/marss.cpp new file mode 100755 index 000000000..25c40d6cd --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/marss.cpp @@ -0,0 +1,140 @@ +// MARS S-Box + +#include "pch.h" +#include "mars.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +const word32 MARS::Base::Sbox[512] = { + 0x09d0c479, 0x28c8ffe0, 0x84aa6c39, 0x9dad7287, + 0x7dff9be3, 0xd4268361, 0xc96da1d4, 0x7974cc93, + 0x85d0582e, 0x2a4b5705, 0x1ca16a62, 0xc3bd279d, + 0x0f1f25e5, 0x5160372f, 0xc695c1fb, 0x4d7ff1e4, + 0xae5f6bf4, 0x0d72ee46, 0xff23de8a, 0xb1cf8e83, + 0xf14902e2, 0x3e981e42, 0x8bf53eb6, 0x7f4bf8ac, + 0x83631f83, 0x25970205, 0x76afe784, 0x3a7931d4, + 0x4f846450, 0x5c64c3f6, 0x210a5f18, 0xc6986a26, + 0x28f4e826, 0x3a60a81c, 0xd340a664, 0x7ea820c4, + 0x526687c5, 0x7eddd12b, 0x32a11d1d, 0x9c9ef086, + 0x80f6e831, 0xab6f04ad, 0x56fb9b53, 0x8b2e095c, + 0xb68556ae, 0xd2250b0d, 0x294a7721, 0xe21fb253, + 0xae136749, 0xe82aae86, 0x93365104, 0x99404a66, + 0x78a784dc, 0xb69ba84b, 0x04046793, 0x23db5c1e, + 0x46cae1d6, 0x2fe28134, 0x5a223942, 0x1863cd5b, + 0xc190c6e3, 0x07dfb846, 0x6eb88816, 0x2d0dcc4a, + 0xa4ccae59, 0x3798670d, 0xcbfa9493, 0x4f481d45, + 0xeafc8ca8, 0xdb1129d6, 0xb0449e20, 0x0f5407fb, + 0x6167d9a8, 0xd1f45763, 0x4daa96c3, 0x3bec5958, + 0xababa014, 0xb6ccd201, 0x38d6279f, 0x02682215, + 0x8f376cd5, 0x092c237e, 0xbfc56593, 0x32889d2c, + 0x854b3e95, 0x05bb9b43, 0x7dcd5dcd, 0xa02e926c, + 0xfae527e5, 0x36a1c330, 0x3412e1ae, 0xf257f462, + 0x3c4f1d71, 0x30a2e809, 0x68e5f551, 0x9c61ba44, + 0x5ded0ab8, 0x75ce09c8, 0x9654f93e, 0x698c0cca, + 0x243cb3e4, 0x2b062b97, 0x0f3b8d9e, 0x00e050df, + 0xfc5d6166, 0xe35f9288, 0xc079550d, 0x0591aee8, + 0x8e531e74, 0x75fe3578, 0x2f6d829a, 0xf60b21ae, + 0x95e8eb8d, 0x6699486b, 0x901d7d9b, 0xfd6d6e31, + 0x1090acef, 0xe0670dd8, 0xdab2e692, 0xcd6d4365, + 0xe5393514, 0x3af345f0, 0x6241fc4d, 0x460da3a3, + 0x7bcf3729, 0x8bf1d1e0, 0x14aac070, 0x1587ed55, + 0x3afd7d3e, 0xd2f29e01, 0x29a9d1f6, 0xefb10c53, + 0xcf3b870f, 0xb414935c, 0x664465ed, 0x024acac7, + 0x59a744c1, 0x1d2936a7, 0xdc580aa6, 0xcf574ca8, + 0x040a7a10, 0x6cd81807, 0x8a98be4c, 0xaccea063, + 0xc33e92b5, 0xd1e0e03d, 0xb322517e, 0x2092bd13, + 0x386b2c4a, 0x52e8dd58, 0x58656dfb, 0x50820371, + 0x41811896, 0xe337ef7e, 0xd39fb119, 0xc97f0df6, + 0x68fea01b, 0xa150a6e5, 0x55258962, 0xeb6ff41b, + 0xd7c9cd7a, 0xa619cd9e, 0xbcf09576, 0x2672c073, + 0xf003fb3c, 0x4ab7a50b, 0x1484126a, 0x487ba9b1, + 0xa64fc9c6, 0xf6957d49, 0x38b06a75, 0xdd805fcd, + 0x63d094cf, 0xf51c999e, 0x1aa4d343, 0xb8495294, + 0xce9f8e99, 0xbffcd770, 0xc7c275cc, 0x378453a7, + 0x7b21be33, 0x397f41bd, 0x4e94d131, 0x92cc1f98, + 0x5915ea51, 0x99f861b7, 0xc9980a88, 0x1d74fd5f, + 0xb0a495f8, 0x614deed0, 0xb5778eea, 0x5941792d, + 0xfa90c1f8, 0x33f824b4, 0xc4965372, 0x3ff6d550, + 0x4ca5fec0, 0x8630e964, 0x5b3fbbd6, 0x7da26a48, + 0xb203231a, 0x04297514, 0x2d639306, 0x2eb13149, + 0x16a45272, 0x532459a0, 0x8e5f4872, 0xf966c7d9, + 0x07128dc0, 0x0d44db62, 0xafc8d52d, 0x06316131, + 0xd838e7ce, 0x1bc41d00, 0x3a2e8c0f, 0xea83837e, + 0xb984737d, 0x13ba4891, 0xc4f8b949, 0xa6d6acb3, + 0xa215cdce, 0x8359838b, 0x6bd1aa31, 0xf579dd52, + 0x21b93f93, 0xf5176781, 0x187dfdde, 0xe94aeb76, + 0x2b38fd54, 0x431de1da, 0xab394825, 0x9ad3048f, + 0xdfea32aa, 0x659473e3, 0x623f7863, 0xf3346c59, + 0xab3ab685, 0x3346a90b, 0x6b56443e, 0xc6de01f8, + 0x8d421fc0, 0x9b0ed10c, 0x88f1a1e9, 0x54c1f029, + 0x7dead57b, 0x8d7ba426, 0x4cf5178a, 0x551a7cca, + 0x1a9a5f08, 0xfcd651b9, 0x25605182, 0xe11fc6c3, + 0xb6fd9676, 0x337b3027, 0xb7c8eb14, 0x9e5fd030, + 0x6b57e354, 0xad913cf7, 0x7e16688d, 0x58872a69, + 0x2c2fc7df, 0xe389ccc6, 0x30738df1, 0x0824a734, + 0xe1797a8b, 0xa4a8d57b, 0x5b5d193b, 0xc8a8309b, + 0x73f9a978, 0x73398d32, 0x0f59573e, 0xe9df2b03, + 0xe8a5b6c8, 0x848d0704, 0x98df93c2, 0x720a1dc3, + 0x684f259a, 0x943ba848, 0xa6370152, 0x863b5ea3, + 0xd17b978b, 0x6d9b58ef, 0x0a700dd4, 0xa73d36bf, + 0x8e6a0829, 0x8695bc14, 0xe35b3447, 0x933ac568, + 0x8894b022, 0x2f511c27, 0xddfbcc3c, 0x006662b6, + 0x117c83fe, 0x4e12b414, 0xc2bca766, 0x3a2fec10, + 0xf4562420, 0x55792e2a, 0x46f5d857, 0xceda25ce, + 0xc3601d3b, 0x6c00ab46, 0xefac9c28, 0xb3c35047, + 0x611dfee3, 0x257c3207, 0xfdd58482, 0x3b14d84f, + 0x23becb64, 0xa075f3a3, 0x088f8ead, 0x07adf158, + 0x7796943c, 0xfacabf3d, 0xc09730cd, 0xf7679969, + 0xda44e9ed, 0x2c854c12, 0x35935fa3, 0x2f057d9f, + 0x690624f8, 0x1cb0bafd, 0x7b0dbdc6, 0x810f23bb, + 0xfa929a1a, 0x6d969a17, 0x6742979b, 0x74ac7d05, + 0x010e65c4, 0x86a3d963, 0xf907b5a0, 0xd0042bd3, + 0x158d7d03, 0x287a8255, 0xbba8366f, 0x096edc33, + 0x21916a7b, 0x77b56b86, 0x951622f9, 0xa6c5e650, + 0x8cea17d1, 0xcd8c62bc, 0xa3d63433, 0x358a68fd, + 0x0f9b9d3c, 0xd6aa295b, 0xfe33384a, 0xc000738e, + 0xcd67eb2f, 0xe2eb6dc2, 0x97338b02, 0x06c9f246, + 0x419cf1ad, 0x2b83c045, 0x3723f18a, 0xcb5b3089, + 0x160bead7, 0x5d494656, 0x35f8a74b, 0x1e4e6c9e, + 0x000399bd, 0x67466880, 0xb4174831, 0xacf423b2, + 0xca815ab3, 0x5a6395e7, 0x302a67c5, 0x8bdb446b, + 0x108f8fa4, 0x10223eda, 0x92b8b48b, 0x7f38d0ee, + 0xab2701d4, 0x0262d415, 0xaf224a30, 0xb3d88aba, + 0xf8b2c3af, 0xdaf7ef70, 0xcc97d3b7, 0xe9614b6c, + 0x2baebff4, 0x70f687cf, 0x386c9156, 0xce092ee5, + 0x01e87da6, 0x6ce91e6a, 0xbb7bcc84, 0xc7922c20, + 0x9d3b71fd, 0x060e41c6, 0xd7590f15, 0x4e03bb47, + 0x183c198e, 0x63eeb240, 0x2ddbf49a, 0x6d5cba54, + 0x923750af, 0xf9e14236, 0x7838162b, 0x59726c72, + 0x81b66760, 0xbb2926c1, 0x48a0ce0d, 0xa6c0496d, + 0xad43507b, 0x718d496a, 0x9df057af, 0x44b1bde6, + 0x054356dc, 0xde7ced35, 0xd51a138b, 0x62088cc9, + 0x35830311, 0xc96efca2, 0x686f86ec, 0x8e77cb68, + 0x63e1d6b8, 0xc80f9778, 0x79c491fd, 0x1b4c67f2, + 0x72698d7d, 0x5e368c31, 0xf7d95e2e, 0xa1d3493f, + 0xdcd9433e, 0x896f1552, 0x4bc4ca7a, 0xa6d1baf4, + 0xa5a96dcc, 0x0bef8b46, 0xa169fda7, 0x74df40b7, + 0x4e208804, 0x9a756607, 0x038e87c8, 0x20211e44, + 0x8b7ad4bf, 0xc6403f35, 0x1848e36d, 0x80bdb038, + 0x1e62891c, 0x643d2107, 0xbf04d6f8, 0x21092c8c, + 0xf644f389, 0x0778404e, 0x7b78adb8, 0xa2c52d53, + 0x42157abe, 0xa2253e2e, 0x7bf3f4ae, 0x80f594f9, + 0x953194e7, 0x77eb92ed, 0xb3816930, 0xda8d9336, + 0xbf447469, 0xf26d9483, 0xee6faed5, 0x71371235, + 0xde425f73, 0xb4e59f43, 0x7dbe2d4e, 0x2d37b185, + 0x49dc9a63, 0x98c39d98, 0x1301c9a2, 0x389b1bbf, + 0x0c18588d, 0xa421c1ba, 0x7aa3865c, 0x71e08558, + 0x3c5cfcaa, 0x7d239ca4, 0x0297d9dd, 0xd7dc2830, + 0x4b37802b, 0x7428ab54, 0xaeee0347, 0x4b3fbb85, + 0x692f2f08, 0x134e578e, 0x36d9e0bf, 0xae8b5fcf, + 0xedb93ecf, 0x2b27248e, 0x170eb1ef, 0x7dc57fd6, + 0x1e760f16, 0xb1136601, 0x864e1b9b, 0xd7ea7319, + 0x3ab871bd, 0xcfa4d76f, 0xe31bd782, 0x0dbeb469, + 0xabb96061, 0x5370f85d, 0xffb07e37, 0xda30d0fb, + 0xebc977b6, 0x0b98b40f, 0x3a4d0fe6, 0xdf4fc26b, + 0x159cf22a, 0xc298d6e2, 0x2b78ef6a, 0x61a94ac0, + 0xab561187, 0x14eea0f0, 0xdf0d4164, 0x19af70ee +}; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/md2.cpp b/external/ours/library/crypto/src/shared/original/md2.cpp new file mode 100755 index 000000000..b0dc7e8b0 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/md2.cpp @@ -0,0 +1,120 @@ +// md2.cpp - modified by Wei Dai from Andrew M. Kuchling's md2.c +// The original code and all modifications are in the public domain. + +// This is the original introductory comment: + +/* + * md2.c : MD2 hash algorithm. + * + * Part of the Python Cryptography Toolkit, version 1.1 + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +#include "pch.h" +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 +#include "md2.h" + +NAMESPACE_BEGIN(CryptoPP) +namespace Weak1 { + +MD2::MD2() + : m_X(48), m_C(16), m_buf(16) +{ + Init(); +} + +void MD2::Init() +{ + memset(m_X, 0, 48); + memset(m_C, 0, 16); + memset(m_buf, 0, 16); + m_count = 0; +} + +void MD2::Update(const byte *buf, size_t len) +{ + static const byte S[256] = { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 + }; + + while (len) + { + unsigned int L = UnsignedMin(16U-m_count, len); + memcpy(m_buf+m_count, buf, L); + m_count+=L; + buf+=L; + len-=L; + if (m_count==16) + { + byte t; + int i,j; + + m_count=0; + memcpy(m_X+16, m_buf, 16); + t=m_C[15]; + for(i=0; i<16; i++) + { + m_X[32+i]=m_X[16+i]^m_X[i]; + t=m_C[i]^=S[m_buf[i]^t]; + } + + t=0; + for(i=0; i<18; i++) + { + for(j=0; j<48; j+=8) + { + t=m_X[j+0]^=S[t]; + t=m_X[j+1]^=S[t]; + t=m_X[j+2]^=S[t]; + t=m_X[j+3]^=S[t]; + t=m_X[j+4]^=S[t]; + t=m_X[j+5]^=S[t]; + t=m_X[j+6]^=S[t]; + t=m_X[j+7]^=S[t]; + } + t = byte((t+i) & 0xFF); + } + } + } +} + +void MD2::TruncatedFinal(byte *hash, size_t size) +{ + ThrowIfInvalidTruncatedSize(size); + + byte padding[16]; + word32 padlen; + unsigned int i; + + padlen= 16-m_count; + for(i=0; iMD2 +/// \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/external/ours/library/crypto/src/shared/original/md4.cpp b/external/ours/library/crypto/src/shared/original/md4.cpp new file mode 100755 index 000000000..f14588cc3 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/md4.cpp @@ -0,0 +1,110 @@ +// md4.cpp - modified by Wei Dai from Andrew M. Kuchling's md4.c +// The original code and all modifications are in the public domain. + +// This is the original introductory comment: + +/* + * md4.c : MD4 hash algorithm. + * + * Part of the Python Cryptography Toolkit, version 1.1 + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +#include "pch.h" +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 +#include "md4.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) +namespace Weak1 { + +void MD4::InitState(HashWordType *state) +{ + state[0] = 0x67452301L; + state[1] = 0xefcdab89L; + state[2] = 0x98badcfeL; + state[3] = 0x10325476L; +} + +void MD4::Transform (word32 *digest, const word32 *in) +{ +// #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + + word32 A, B, C, D; + + A=digest[0]; + B=digest[1]; + C=digest[2]; + D=digest[3]; + +#define function(a,b,c,d,k,s) a=rotlVariable(a+F(b,c,d)+in[k],s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 1, 7); + function(C,D,A,B, 2,11); + function(B,C,D,A, 3,19); + function(A,B,C,D, 4, 3); + function(D,A,B,C, 5, 7); + function(C,D,A,B, 6,11); + function(B,C,D,A, 7,19); + function(A,B,C,D, 8, 3); + function(D,A,B,C, 9, 7); + function(C,D,A,B,10,11); + function(B,C,D,A,11,19); + function(A,B,C,D,12, 3); + function(D,A,B,C,13, 7); + function(C,D,A,B,14,11); + function(B,C,D,A,15,19); + +#undef function +#define function(a,b,c,d,k,s) a=rotlVariable(a+G(b,c,d)+in[k]+0x5a827999,s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 4, 5); + function(C,D,A,B, 8, 9); + function(B,C,D,A,12,13); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 5, 5); + function(C,D,A,B, 9, 9); + function(B,C,D,A,13,13); + function(A,B,C,D, 2, 3); + function(D,A,B,C, 6, 5); + function(C,D,A,B,10, 9); + function(B,C,D,A,14,13); + function(A,B,C,D, 3, 3); + function(D,A,B,C, 7, 5); + function(C,D,A,B,11, 9); + function(B,C,D,A,15,13); + +#undef function +#define function(a,b,c,d,k,s) a=rotlVariable(a+H(b,c,d)+in[k]+0x6ed9eba1,s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 8, 9); + function(C,D,A,B, 4,11); + function(B,C,D,A,12,15); + function(A,B,C,D, 2, 3); + function(D,A,B,C,10, 9); + function(C,D,A,B, 6,11); + function(B,C,D,A,14,15); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 9, 9); + function(C,D,A,B, 5,11); + function(B,C,D,A,13,15); + function(A,B,C,D, 3, 3); + function(D,A,B,C,11, 9); + function(C,D,A,B, 7,11); + function(B,C,D,A,15,15); + + digest[0]+=A; + digest[1]+=B; + digest[2]+=C; + digest[3]+=D; +} + +} +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/md4.h b/external/ours/library/crypto/src/shared/original/md4.h new file mode 100755 index 000000000..8edb166db --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/md5.cpp b/external/ours/library/crypto/src/shared/original/md5.cpp index 68f60925a..99a0e34b9 100755 --- a/external/ours/library/crypto/src/shared/original/md5.cpp +++ b/external/ours/library/crypto/src/shared/original/md5.cpp @@ -1,109 +1,124 @@ -// md5.cpp - modified by Wei Dai from Colin Plumb's public domain md5.c -// any modifications are placed in the public domain - -#include "FirstCrypto.h" -#include "md5.h" - -NAMESPACE_BEGIN(CryptoPP) - -void MD5::Init() -{ - digest[0u] = 0x67452301L; - digest[1u] = 0xefcdab89L; - digest[2u] = 0x98badcfeL; - digest[3u] = 0x10325476L; -} - -void MD5::Transform (word32 *digest, const word32 *in) -{ -// #define F1(x, y, z) (x & y | ~x & z) -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -#define MD5STEP(f, w, x, y, z, data, s) \ - w = rotlFixed(w + f(x, y, z) + data, s) + x - - word32 a, b, c, d; - - a=digest[0]; - b=digest[1]; - c=digest[2]; - d=digest[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - digest[0]+=a; - digest[1]+=b; - digest[2]+=c; - digest[3]+=d; -} - -NAMESPACE_END +// md5.cpp - modified by Wei Dai from Colin Plumb's public domain md5.c +// any modifications are placed in the public domain + +#include "pch.h" + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 +#include "md5.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Weak1) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void MD5_TestInstantiations() +{ + MD5 x; +} +#endif + +void MD5::InitState(HashWordType *state) +{ + state[0] = 0x67452301L; + state[1] = 0xefcdab89L; + state[2] = 0x98badcfeL; + state[3] = 0x10325476L; +} + +void MD5::Transform (word32 *digest, const word32 *data) +{ + CRYPTOPP_ASSERT(digest); + CRYPTOPP_ASSERT(data); + +// #define F1(x, y, z) (x & y | ~x & z) +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, data, s) \ + w = rotlFixed(w + f(x, y, z) + data, s) + x + + word32 a, b, c, d; + + a=digest[0]; + b=digest[1]; + c=digest[2]; + d=digest[3]; + + MD5STEP(F1, a, b, c, d, data[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, data[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, data[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, data[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, data[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, data[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, data[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, data[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, data[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, data[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, data[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, data[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, data[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, data[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, data[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, data[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, data[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, data[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, data[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, data[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, data[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, data[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, data[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, data[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, data[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, data[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, data[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, data[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, data[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, data[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, data[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, data[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, data[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, data[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, data[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, data[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, data[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, data[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, data[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, data[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, data[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, data[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, data[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, data[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, data[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, data[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, data[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, data[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, data[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, data[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, data[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, data[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, data[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, data[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, data[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, data[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, data[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, data[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, data[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, data[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, data[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, data[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, data[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, data[9] + 0xeb86d391, 21); + + digest[0]+=a; + digest[1]+=b; + digest[2]+=c; + digest[3]+=d; +} + +NAMESPACE_END // Weak +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/md5.h b/external/ours/library/crypto/src/shared/original/md5.h index d58d6eabd..b64c83044 100755 --- a/external/ours/library/crypto/src/shared/original/md5.h +++ b/external/ours/library/crypto/src/shared/original/md5.h @@ -1,24 +1,35 @@ -#ifndef CRYPTOPP_MD5_H -#define CRYPTOPP_MD5_H - -#include "iterhash.h" - -NAMESPACE_BEGIN(CryptoPP) - -/// MD5 -/** 128 Bit Hash */ -class MD5 : public IteratedHash -{ -public: - enum {DIGESTSIZE = 16}; - MD5() : IteratedHash(DIGESTSIZE) {Init();} - static void Transform(word32 *digest, const word32 *data); - -protected: - void Init(); - void vTransform(const word32 *data) {Transform(digest, data);} -}; - -NAMESPACE_END - -#endif +#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/external/ours/library/crypto/src/shared/original/mdc.h b/external/ours/library/crypto/src/shared/original/mdc.h new file mode 100755 index 000000000..e6926fcc9 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/mersenne.h b/external/ours/library/crypto/src/shared/original/mersenne.h new file mode 100755 index 000000000..3ec6f4c60 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 distrubuted +/// 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 distrubuted 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(); + 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 operaton 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/external/ours/library/crypto/src/shared/original/misc.cpp b/external/ours/library/crypto/src/shared/original/misc.cpp index 5e49edfc0..5ff76b713 100755 --- a/external/ours/library/crypto/src/shared/original/misc.cpp +++ b/external/ours/library/crypto/src/shared/original/misc.cpp @@ -1,77 +1,394 @@ -// misc.cpp - written and placed in the public domain by Wei Dai - -#include "FirstCrypto.h" -#include "misc.h" -#include "words.h" - -NAMESPACE_BEGIN(CryptoPP) - -byte OAEP_P_DEFAULT[1]; - -void xorbuf(byte *buf, const byte *mask, unsigned int count) -{ - if (((unsigned int)buf | (unsigned int)mask | count) % WORD_SIZE == 0) - XorWords((word *)buf, (const word *)mask, count/WORD_SIZE); - else - { - for (unsigned int i=0; i0; i/=2) - value ^= value >> i; - return (unsigned int)value&1; -} - -unsigned int BytePrecision(unsigned long value) -{ - unsigned int i; - for (i=sizeof(value); i; --i) - if (value >> (i-1)*8) - break; - - return i; -} - -unsigned int BitPrecision(unsigned long 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; -} - -unsigned long Crop(unsigned long value, unsigned int size) -{ - if (size < 8*sizeof(value)) - return (value & ((1L << size) - 1)); - else - return value; -} - -NAMESPACE_END +// misc.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4189) +# if (CRYPTOPP_MSC_VERSION >= 1400) +# pragma warning(disable: 6237) +# endif +#endif + +#ifndef CRYPTOPP_IMPORTS + +#include "misc.h" +#include "trap.h" +#include "words.h" +#include "stdcpp.h" +#include "integer.h" +#include "secblock.h" + +// Hack for OpenBSD and GCC 4.2.1. I believe they are stuck at 4.2.1 due to GPLv3. +#if defined(__OpenBSD__) +# if defined (CRYPTOPP_GCC_VERSION) && (CRYPTOPP_GCC_VERSION < 43000) +# undef CRYPTOPP_DISABLE_ASM +# define CRYPTOPP_DISABLE_ASM 1 +# endif +#endif + +#ifndef CRYPTOPP_DISABLE_ASM +# if defined(__SSE2__) +# include +# endif +# if defined(__AVX__) +# include +# endif + +# if defined(__aarch64__) || defined(__aarch32__) || defined(_M_ARM64) +# if defined(CRYPTOPP_ARM_NEON_HEADER) +# include +# endif +# endif +#endif // CRYPTOPP_DISABLE_ASM + +NAMESPACE_BEGIN(CryptoPP) + +byte* BytePtr(SecByteBlock& str) +{ + // Caller wants a writeable pointer + CRYPTOPP_ASSERT(str.empty() == false); + + if (str.empty()) + return NULLPTR; + return reinterpret_cast(str.data()); +} + +const byte* ConstBytePtr(const SecByteBlock& str) +{ + if (str.empty()) + return NULLPTR; + return reinterpret_cast(str.data()); +} + +size_t BytePtrSize(const SecByteBlock& str) +{ + return str.size(); +} + +// xorbuf simplified at https://github.com/weidai11/cryptopp/issues/1020 +void xorbuf(byte *buf, const byte *mask, size_t count) +{ + CRYPTOPP_ASSERT(buf != NULLPTR); + CRYPTOPP_ASSERT(mask != NULLPTR); + CRYPTOPP_ASSERT(count > 0); + +#ifndef CRYPTOPP_DISABLE_ASM +# if defined(__AVX__) + while (count >= 32) + { + __m256i b = _mm256_loadu_si256(reinterpret_cast(buf)); + __m256i m = _mm256_loadu_si256(reinterpret_cast(mask)); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(buf), _mm256_castps_si256( + _mm256_xor_ps(_mm256_castsi256_ps(b), _mm256_castsi256_ps(m)))); + buf += 32; mask += 32; count -= 32; + } + // https://software.intel.com/en-us/articles/avoiding-avx-sse-transition-penalties + _mm256_zeroupper(); +# endif +# if defined(__SSE2__) + while (count >= 16) + { + __m128i b = _mm_loadu_si128(reinterpret_cast(buf)); + __m128i m = _mm_loadu_si128(reinterpret_cast(mask)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(buf), _mm_castps_si128( + _mm_xor_ps(_mm_castsi128_ps(b), _mm_castsi128_ps(m)))); + buf += 16; mask += 16; count -= 16; + } +# endif +# if defined(__aarch64__) || defined(__aarch32__) || defined(_M_ARM64) + while (count >= 16) + { + vst1q_u8(buf, veorq_u8(vld1q_u8(buf), vld1q_u8(mask))); + buf += 16; mask += 16; count -= 16; + } +# endif +#endif // CRYPTOPP_DISABLE_ASM + +#if CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64 + // word64 and stride of 8 slows things down on x86_64. + // word64 and stride of 8 makes no difference on ARM. + // word64 and stride of 16 benefits PowerPC. + while (count >= 16) + { + word64 r[2], b[2], m[2]; + memcpy(&b, buf, 16); memcpy(&m, mask, 16); + + r[0] = b[0] ^ m[0]; + r[1] = b[1] ^ m[1]; + memcpy(buf, &r, 16); + + buf += 16; mask += 16; count -= 16; + } +#endif + + // One of the arch specific xor's may have cleared the request + if (count == 0) return; + + while (count >= 4) + { + word32 r, b, m; + memcpy(&b, buf, 4); memcpy(&m, mask, 4); + + r = b ^ m; + memcpy(buf, &r, 4); + + buf += 4; mask += 4; count -= 4; + } + + for (size_t i=0; i 0); + +#ifndef CRYPTOPP_DISABLE_ASM +# if defined(__AVX__) + while (count >= 32) + { + __m256i b = _mm256_loadu_si256(reinterpret_cast(input)); + __m256i m = _mm256_loadu_si256(reinterpret_cast(mask)); + _mm256_storeu_si256(reinterpret_cast<__m256i*>(output), _mm256_castps_si256( + _mm256_xor_ps(_mm256_castsi256_ps(b), _mm256_castsi256_ps(m)))); + output += 32; input += 32; mask += 32; count -= 32; + } + // https://software.intel.com/en-us/articles/avoiding-avx-sse-transition-penalties + _mm256_zeroupper(); +# endif +# if defined(__SSE2__) + while (count >= 16) + { + __m128i b = _mm_loadu_si128(reinterpret_cast(input)); + __m128i m = _mm_loadu_si128(reinterpret_cast(mask)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(output), _mm_castps_si128( + _mm_xor_ps(_mm_castsi128_ps(b), _mm_castsi128_ps(m)))); + output += 16; input += 16; mask += 16; count -= 16; + } +# endif +# if defined(__aarch64__) || defined(__aarch32__) || defined(_M_ARM64) + while (count >= 16) + { + vst1q_u8(output, veorq_u8(vld1q_u8(input), vld1q_u8(mask))); + output += 16; input += 16; mask += 16; count -= 16; + } +# endif +#endif // CRYPTOPP_DISABLE_ASM + +#if CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64 + // word64 and stride of 8 slows things down on x86_64. + // word64 and stride of 8 makes no difference on ARM. + // word64 and stride of 16 benefits PowerPC. + while (count >= 16) + { + word64 b[2], m[2], r[2]; + memcpy(&b, input, 16); memcpy(&m, mask, 16); + + r[0] = b[0] ^ m[0]; + r[1] = b[1] ^ m[1]; + memcpy(output, &r, 16); + + output += 16; input += 16; mask += 16; count -= 16; + } +#endif + + // One of the arch specific xor's may have cleared the request + if (count == 0) return; + + while (count >= 4) + { + word32 b, m, r; + memcpy(&b, input, 4); memcpy(&m, mask, 4); + + r = b ^ m; + memcpy(output, &r, 4); + + output += 4; input += 4; mask += 4; count -= 4; + } + + for (size_t i=0; i 0); + +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_ARM64 || CRYPTOPP_BOOL_PPC64 || CRYPTOPP_BOOL_MIPS64 || CRYPTOPP_BOOL_SPARC64 + word64 acc64 = 0; + while (count >= 8) + { + word64 b, m; + memcpy(&b, buf, 8); memcpy(&m, mask, 8); + acc64 |= b ^ m; + + buf += 8; mask += 8; count -= 8; + } + + word32 acc8 = (acc64 >> 32) | (acc64 & 0xffffffff); + acc8 = static_cast(acc8) | static_cast(acc8 >> 8) | + static_cast(acc8 >> 16) | static_cast(acc8 >> 24); +#else + word32 acc32 = 0; + while (count >= 4) + { + word32 b, m; + memcpy(&b, buf, 4); memcpy(&m, mask, 4); + acc32 |= b ^ m; + + buf += 4; mask += 4; count -= 4; + } + + word32 acc8 = acc32; + acc8 = static_cast(acc8) | static_cast(acc8 >> 8) | + static_cast(acc8 >> 16) | static_cast(acc8 >> 24); +#endif + + for (size_t i=0; i= 1400) + size_t len=0, size=0; + errno_t err = 0; + + //const wchar_t* ptr = str; + //while (*ptr++) len++; + len = wcslen(str)+1; + + err = wcstombs_s(&size, NULLPTR, 0, str, len*sizeof(wchar_t)); + CRYPTOPP_ASSERT(err == 0); + if (err != 0) + { + if (throwOnError) + throw InvalidArgument("StringNarrow: wcstombs_s() failed with error " + IntToString(err)); + else + return std::string(); + } + + result.resize(size); + err = wcstombs_s(&size, &result[0], size, str, len*sizeof(wchar_t)); + CRYPTOPP_ASSERT(err == 0); + if (err != 0) + { + if (throwOnError) + throw InvalidArgument("StringNarrow: wcstombs_s() failed with error " + IntToString(err)); + else + return std::string(); + } + + // The safe routine's size includes the NULL. + if (!result.empty() && result[size - 1] == '\0') + result.erase(size - 1); +#else + size_t size = wcstombs(NULLPTR, str, 0); + CRYPTOPP_ASSERT(size != (size_t)-1); + if (size == (size_t)-1) + { + if (throwOnError) + throw InvalidArgument("StringNarrow: wcstombs() failed"); + else + return std::string(); + } + + result.resize(size); + size = wcstombs(&result[0], str, size); + CRYPTOPP_ASSERT(size != (size_t)-1); + if (size == (size_t)-1) + { + if (throwOnError) + throw InvalidArgument("StringNarrow: wcstombs() failed"); + else + return std::string(); + } +#endif + + return result; +} + +std::wstring StringWiden(const char *str, bool throwOnError) +{ + CRYPTOPP_ASSERT(str); + std::wstring result; + + // Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55 +#if (CRYPTOPP_MSC_VERSION >= 1400) + size_t len=0, size=0; + errno_t err = 0; + + //const char* ptr = str; + //while (*ptr++) len++; + len = std::strlen(str)+1; + + err = mbstowcs_s(&size, NULLPTR, 0, str, len); + CRYPTOPP_ASSERT(err == 0); + if (err != 0) + { + if (throwOnError) + throw InvalidArgument("StringWiden: wcstombs_s() failed with error " + IntToString(err)); + else + return std::wstring(); + } + + result.resize(size); + err = mbstowcs_s(&size, &result[0], size, str, len); + CRYPTOPP_ASSERT(err == 0); + if (err != 0) + { + if (throwOnError) + throw InvalidArgument("StringWiden: wcstombs_s() failed with error " + IntToString(err)); + else + return std::wstring(); + } + + // The safe routine's size includes the NULL. + if (!result.empty() && result[size - 1] == '\0') + result.erase(size - 1); +#else + size_t size = mbstowcs(NULLPTR, str, 0); + CRYPTOPP_ASSERT(size != (size_t)-1); + if (size == (size_t)-1) + { + if (throwOnError) + throw InvalidArgument("StringWiden: mbstowcs() failed"); + else + return std::wstring(); + } + + result.resize(size); + size = mbstowcs(&result[0], str, size); + CRYPTOPP_ASSERT(size != (size_t)-1); + if (size == (size_t)-1) + { + if (throwOnError) + throw InvalidArgument("StringWiden: mbstowcs() failed"); + else + return std::wstring(); + } +#endif + + return result; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/misc.h b/external/ours/library/crypto/src/shared/original/misc.h index 8eb15e2e0..87cc877d3 100755 --- a/external/ours/library/crypto/src/shared/original/misc.h +++ b/external/ours/library/crypto/src/shared/original/misc.h @@ -1,689 +1,2776 @@ -#ifndef CRYPTOPP_MISC_H -#define CRYPTOPP_MISC_H - -#include "config.h" -#include -#include // CodeWarrior doesn't have memory.h -#include -#include - -#ifdef INTEL_INTRINSICS -#include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -// ************** misc functions *************** - -#define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255) -// this one may be faster on a Pentium -// #define GETBYTE(x, y) (((byte *)&(x))[y]) - -unsigned int Parity(unsigned long); -unsigned int BytePrecision(unsigned long); -unsigned int BitPrecision(unsigned long); -unsigned long Crop(unsigned long, unsigned int size); - -inline unsigned int bitsToBytes(unsigned int bitCount) -{ - return ((bitCount+7)/(8)); -} - -inline unsigned int bytesToWords(unsigned int byteCount) -{ - return ((byteCount+WORD_SIZE-1)/WORD_SIZE); -} - -inline unsigned int bitsToWords(unsigned int bitCount) -{ - return ((bitCount+WORD_BITS-1)/(WORD_BITS)); -} - -void xorbuf(byte *buf, const byte *mask, unsigned int count); -void xorbuf(byte *output, const byte *input, const byte *mask, unsigned int count); - -inline unsigned int RoundDownToMultipleOf(unsigned int n, unsigned int m) -{ - return n - n%m; -} - -inline unsigned int RoundUpToMultipleOf(unsigned int n, unsigned int m) -{ - return RoundDownToMultipleOf(n+m-1, m); -} - -template -inline bool IsAligned(const void *p) -{ - return (uintptr_t)p % sizeof(T) == 0; -} - -inline bool CheckEndianess(bool highFirst) -{ -#ifdef IS_LITTLE_ENDIAN - return !highFirst; -#else - return highFirst; -#endif -} - -template // can't use because GCC 2.95.2 doesn't have it -std::string IntToString(T a) -{ - if (a == 0) - return "0"; - bool negate = false; - if (a < 0) - { - negate = true; - a = -a; - } - std::string result; - while (a > 0) - { - result = char('0' + a % 10) + result; - a = a / 10; - } - if (negate) - result = "-" + result; - return result; -} - -// ************** rotate functions *************** - -template inline T rotlFixed(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return (x<>(sizeof(T)*8-y)); -} - -template inline T rotrFixed(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return (x>>y) | (x<<(sizeof(T)*8-y)); -} - -template inline T rotlVariable(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return (x<>(sizeof(T)*8-y)); -} - -template inline T rotrVariable(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return (x>>y) | (x<<(sizeof(T)*8-y)); -} - -template inline T rotlMod(T x, unsigned int y) -{ - y %= sizeof(T)*8; - return (x<>(sizeof(T)*8-y)); -} - -template inline T rotrMod(T x, unsigned int y) -{ - y %= sizeof(T)*8; - return (x>>y) | (x<<(sizeof(T)*8-y)); -} - -#ifdef INTEL_INTRINSICS - -template<> inline word32 rotlFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? _lrotl(x, y) : x; -} - -template<> inline word32 rotrFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? _lrotr(x, y) : x; -} - -template<> inline word32 rotlVariable(word32 x, unsigned int y) -{ - assert(y < 32); - return _lrotl(x, y); -} - -template<> inline word32 rotrVariable(word32 x, unsigned int y) -{ - assert(y < 32); - return _lrotr(x, y); -} - -template<> inline word32 rotlMod(word32 x, unsigned int y) -{ - return _lrotl(x, y); -} - -template<> inline word32 rotrMod(word32 x, unsigned int y) -{ - return _lrotr(x, y); -} - -#endif // #ifdef INTEL_INTRINSICS - -#ifdef PPC_INTRINSICS - -template<> inline word32 rotlFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? __rlwinm(x,y,0,31) : x; -} - -template<> inline word32 rotrFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? __rlwinm(x,32-y,0,31) : x; -} - -template<> inline word32 rotlVariable(word32 x, unsigned int y) -{ - assert(y < 32); - return (__rlwnm(x,y,0,31)); -} - -template<> inline word32 rotrVariable(word32 x, unsigned int y) -{ - 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 // #ifdef PPC_INTRINSICS - -// ************** endian reversal *************** - -inline word16 byteReverse(word16 value) -{ - return rotlFixed(value, 8U); -} - -inline word32 byteReverse(word32 value) -{ -#ifdef PPC_INTRINSICS - // PPC: load reverse indexed instruction - return (word32)__lwbrx(&value,0); -#elif defined(FAST_ROTATE) - // 5 instructions with rotate instruction, 9 without - return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff); -#else - // 6 instructions with rotate instruction, 8 without - value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); - return rotlFixed(value, 16U); -#endif -} - -#ifdef WORD64_AVAILABLE -inline word64 byteReverse(word64 value) -{ -#ifdef SLOW_WORD64 - return (word64(byteReverse(word32(value))) << 32) | byteReverse(word32(value>>32)); -#else - value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); - value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16); - return rotlFixed(value, 32U); -#endif -} -#endif - -inline byte bitReverse(byte value) -{ - value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1); - value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2); - return rotlFixed(value, 4); -} - -inline word16 bitReverse(word16 value) -{ - value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1); - value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2); - value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4); - return byteReverse(value); -} - -inline word32 bitReverse(word32 value) -{ - value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1); - value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2); - value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4); - return byteReverse(value); -} - -#ifdef WORD64_AVAILABLE -inline word64 bitReverse(word64 value) -{ -#ifdef SLOW_WORD64 - return (word64(bitReverse(word32(value))) << 32) | bitReverse(word32(value>>32)); -#else - value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1); - value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2); - value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4); - return byteReverse(value); -#endif -} -#endif - -template -inline T bitReverse(T value) -{ - if (sizeof(T) == 1) - return bitReverse((byte)value); - else if (sizeof(T) == 2) - return bitReverse((word16)value); - else if (sizeof(T) == 4) - return bitReverse((word32)value); - else - { -#ifdef WORD64_AVAILABLE - assert(sizeof(T) == 8); - return bitReverse((word64)value); -#else - assert(false); - return 0; -#endif - } -} - -template -void byteReverse(T *out, const T *in, unsigned int byteCount) -{ - unsigned int count = (byteCount+sizeof(T)-1)/sizeof(T); - for (unsigned int i=0; i -inline void GetUserKeyLittleEndian(T *out, unsigned int outlen, const byte *in, unsigned int inlen) -{ - const unsigned int U = sizeof(T); - assert(inlen <= outlen*U); - memcpy(out, in, inlen); - memset((byte *)out+inlen, 0, outlen*U-inlen); -#ifndef IS_LITTLE_ENDIAN - byteReverse(out, out, inlen); -#endif -} - -template -inline void GetUserKeyBigEndian(T *out, unsigned int outlen, const byte *in, unsigned int inlen) -{ - const unsigned int U = sizeof(T); - assert(inlen <= outlen*U); - memcpy(out, in, inlen); - memset((byte *)out+inlen, 0, outlen*U-inlen); -#ifdef IS_LITTLE_ENDIAN - byteReverse(out, out, inlen); -#endif -} - -// Fetch 2 words from user's buffer into "a", "b" in LITTLE-endian order -template -inline void GetBlockLittleEndian(const byte *block, T &a, T &b) -{ -#ifdef IS_LITTLE_ENDIAN - a = ((T *)block)[0]; - b = ((T *)block)[1]; -#else - a = byteReverse(((T *)block)[0]); - b = byteReverse(((T *)block)[1]); -#endif -} - -// Put 2 words back into user's buffer in LITTLE-endian order -template -inline void PutBlockLittleEndian(byte *block, T a, T b) -{ -#ifdef IS_LITTLE_ENDIAN - ((T *)block)[0] = a; - ((T *)block)[1] = b; -#else - ((T *)block)[0] = byteReverse(a); - ((T *)block)[1] = byteReverse(b); -#endif -} - -// Fetch 4 words from user's buffer into "a", "b", "c", "d" in LITTLE-endian order -template -inline void GetBlockLittleEndian(const byte *block, T &a, T &b, T &c, T &d) -{ -#ifdef IS_LITTLE_ENDIAN - a = ((T *)block)[0]; - b = ((T *)block)[1]; - c = ((T *)block)[2]; - d = ((T *)block)[3]; -#else - a = byteReverse(((T *)block)[0]); - b = byteReverse(((T *)block)[1]); - c = byteReverse(((T *)block)[2]); - d = byteReverse(((T *)block)[3]); -#endif -} - -// Put 4 words back into user's buffer in LITTLE-endian order -template -inline void PutBlockLittleEndian(byte *block, T a, T b, T c, T d) -{ -#ifdef IS_LITTLE_ENDIAN - ((T *)block)[0] = a; - ((T *)block)[1] = b; - ((T *)block)[2] = c; - ((T *)block)[3] = d; -#else - ((T *)block)[0] = byteReverse(a); - ((T *)block)[1] = byteReverse(b); - ((T *)block)[2] = byteReverse(c); - ((T *)block)[3] = byteReverse(d); -#endif -} - -// Fetch 2 words from user's buffer into "a", "b" in BIG-endian order -template -inline void GetBlockBigEndian(const byte *block, T &a, T &b) -{ -#ifndef IS_LITTLE_ENDIAN - a = ((T *)block)[0]; - b = ((T *)block)[1]; -#else - a = byteReverse(((T *)block)[0]); - b = byteReverse(((T *)block)[1]); -#endif -} - -// Put 2 words back into user's buffer in BIG-endian order -template -inline void PutBlockBigEndian(byte *block, T a, T b) -{ -#ifndef IS_LITTLE_ENDIAN - ((T *)block)[0] = a; - ((T *)block)[1] = b; -#else - ((T *)block)[0] = byteReverse(a); - ((T *)block)[1] = byteReverse(b); -#endif -} - -// Fetch 4 words from user's buffer into "a", "b", "c", "d" in BIG-endian order -template -inline void GetBlockBigEndian(const byte *block, T &a, T &b, T &c, T &d) -{ -#ifndef IS_LITTLE_ENDIAN - a = ((T *)block)[0]; - b = ((T *)block)[1]; - c = ((T *)block)[2]; - d = ((T *)block)[3]; -#else - a = byteReverse(((T *)block)[0]); - b = byteReverse(((T *)block)[1]); - c = byteReverse(((T *)block)[2]); - d = byteReverse(((T *)block)[3]); -#endif -} - -// Put 4 words back into user's buffer in BIG-endian order -template -inline void PutBlockBigEndian(byte *block, T a, T b, T c, T d) -{ -#ifndef IS_LITTLE_ENDIAN - ((T *)block)[0] = a; - ((T *)block)[1] = b; - ((T *)block)[2] = c; - ((T *)block)[3] = d; -#else - ((T *)block)[0] = byteReverse(a); - ((T *)block)[1] = byteReverse(b); - ((T *)block)[2] = byteReverse(c); - ((T *)block)[3] = byteReverse(d); -#endif -} - -template -std::string WordToString(T value, bool highFirst = true) -{ - if (!CheckEndianess(highFirst)) - value = byteReverse(value); - - return std::string((char *)&value, sizeof(value)); -} - -template -T StringToWord(const std::string &str, bool highFirst = true) -{ - T value = 0; - memcpy(&value, str.data(), STDMIN(sizeof(value), str.size())); - return CheckEndianess(highFirst) ? value : byteReverse(value); -} - -// ************** key length query *************** - -/// support query of fixed key length -template -class FixedKeyLength -{ -public: - enum {KEYLENGTH=N, MIN_KEYLENGTH=N, MAX_KEYLENGTH=N, DEFAULT_KEYLENGTH=N}; - /// returns the key length - static unsigned int KeyLength(unsigned int) {return KEYLENGTH;} -}; - -/// support query of variable key length, template parameters are default, min, max, multiple (default multiple 1) -template -class VariableKeyLength -{ -public: - enum {MIN_KEYLENGTH=N, MAX_KEYLENGTH=M, DEFAULT_KEYLENGTH=D, KEYLENGTH_MULTIPLE=Q}; - /// returns the smallest valid key length in bytes that is >= min(n, MAX_KEYLENGTH) - static unsigned int KeyLength(unsigned int n) - { - assert(KEYLENGTH_MULTIPLE > 0 && MIN_KEYLENGTH % KEYLENGTH_MULTIPLE == 0 && MAX_KEYLENGTH % KEYLENGTH_MULTIPLE == 0); - if (n < MIN_KEYLENGTH) - return MIN_KEYLENGTH; - else if (n > MAX_KEYLENGTH) - return MAX_KEYLENGTH; - else - return RoundUpToMultipleOf(n, KEYLENGTH_MULTIPLE); - } -}; - -/// support query of key length that's the same as another class -template -class SameKeyLengthAs -{ -public: - enum {MIN_KEYLENGTH=T::MIN_KEYLENGTH, MAX_KEYLENGTH=T::MAX_KEYLENGTH, DEFAULT_KEYLENGTH=T::DEFAULT_KEYLENGTH}; - /// returns the smallest valid key length in bytes that is >= min(n, MAX_KEYLENGTH) - static unsigned int KeyLength(unsigned int keylength) - {return T::KeyLength(keylength);} -}; - -// ************** secure memory allocation *************** - -#ifdef SECALLOC_DEFAULT -#define SecAlloc(type, number) (new type[(number)]) -#define SecFree(ptr, number) (memset((ptr), 0, (number)*sizeof(*(ptr))), delete [] (ptr)) -#else -#define SecAlloc(type, number) (new type[(number)]) -#define SecFree(ptr, number) (delete [] (ptr)) -#endif - -//! a block of memory allocated using SecAlloc -template struct SecBlock -{ - explicit SecBlock(unsigned int size=0) - : size(size) {ptr = SecAlloc(T, size);} - SecBlock(const SecBlock &t) - : size(t.size) {ptr = SecAlloc(T, size); memcpy(ptr, t.ptr, size*sizeof(T));} - SecBlock(const T *t, unsigned int len) - : size(len) {ptr = SecAlloc(T, len); memcpy(ptr, t, len*sizeof(T));} - ~SecBlock() - {SecFree(ptr, size);} - -#if defined(__GNUC__) || defined(__BCPLUSPLUS__) - operator const void *() const - {return ptr;} - operator void *() - {return ptr;} -#endif -#if defined(__GNUC__) // reduce warnings - operator const void *() - {return ptr;} -#endif - - operator const T *() const - {return ptr;} - operator T *() - {return ptr;} -#if defined(__GNUC__) // reduce warnings - operator const T *() - {return ptr;} -#endif - -// CodeWarrior defines _MSC_VER -#if !defined(_MSC_VER) || defined(__MWERKS__) - T *operator +(unsigned int offset) - {return ptr+offset;} - const T *operator +(unsigned int offset) const - {return ptr+offset;} - T& operator[](unsigned int index) - {assert(index &t) - { - New(t.size); - memcpy(ptr, t.ptr, size*sizeof(T)); - } - - SecBlock& operator=(const SecBlock &t) - { - Assign(t); - return *this; - } - - bool operator==(const SecBlock &t) const - { - return size == t.size && memcmp(ptr, t.ptr, size*sizeof(T)) == 0; - } - - bool operator!=(const SecBlock &t) const - { - return !operator==(t); - } - - void New(unsigned int newSize) - { - if (newSize != size) - { - T *newPtr = SecAlloc(T, newSize); - SecFree(ptr, size); - ptr = newPtr; - size = newSize; - } - } - - void CleanNew(unsigned int newSize) - { - if (newSize != size) - { - T *newPtr = SecAlloc(T, newSize); - SecFree(ptr, size); - ptr = newPtr; - size = newSize; - } - memset(ptr, 0, size*sizeof(T)); - } - - void Grow(unsigned int newSize) - { - if (newSize > size) - { - T *newPtr = SecAlloc(T, newSize); - memcpy(newPtr, ptr, size*sizeof(T)); - SecFree(ptr, size); - ptr = newPtr; - size = newSize; - } - } - - void CleanGrow(unsigned int newSize) - { - if (newSize > size) - { - T *newPtr = SecAlloc(T, newSize); - memcpy(newPtr, ptr, size*sizeof(T)); - memset(newPtr+size, 0, (newSize-size)*sizeof(T)); - SecFree(ptr, size); - ptr = newPtr; - size = newSize; - } - } - - void Resize(unsigned int newSize) - { - if (newSize != size) - { - T *newPtr = SecAlloc(T, newSize); - memcpy(newPtr, ptr, STDMIN(newSize, size)*sizeof(T)); - SecFree(ptr, size); - ptr = newPtr; - size = newSize; - } - } - - void swap(SecBlock &b); - - unsigned int size; - T *ptr; -}; - -template void SecBlock::swap(SecBlock &b) -{ - std::swap(size, b.size); - std::swap(ptr, b.ptr); -} - -typedef SecBlock SecByteBlock; -typedef SecBlock SecWordBlock; - -NAMESPACE_END - -NAMESPACE_BEGIN(std) -template -inline void swap(CryptoPP::SecBlock &a, CryptoPP::SecBlock &b) -{ - a.swap(b); -} - -NAMESPACE_END - -#endif // MISC_H +// 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 _MSC_VER + #if _MSC_VER >= 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 _MSC_VER >= 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__) +# include +# include +#endif // GCC and 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(_MSC_VER) && (_MSC_VER >= 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 (_MSC_VER >= 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(); + s_pObject.store(newObject, std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_release); + + 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 std::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 std::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 std::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 std::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 "-Wsign-compare" +# 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 a's 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)); + if (sizeof(T1)<=sizeof(T2)) + return b < (T2)a ? (T1)b : a; + else + return (T1)b < a ? (T1)b : a; +} + +/// \brief Tests whether a conversion from -> to is safe to perform +/// \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 into to, false otherwise. +template +inline bool SafeConvert(T1 from, T2 &to) +{ + to = static_cast(from); + if (from != to || (from > 0) != (to > 0)) + return false; + 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(_MSC_VER) && (_MSC_VER >= 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(_MSC_VER) && (_MSC_VER >= 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() +{ + return (static_cast(LWORD_MAX) << 64U) | LWORD_MAX; +} +#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) + 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 (_MSC_VER >= 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) && \ + (_MSC_VER >= 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) && (_MSC_VER >= 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 _MSC_VER + +/// \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 _MSC_VER + +#if (_MSC_VER >= 1400) || (defined(_MSC_VER) && !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 _MSC_VER >= 1310 + +#if _MSC_VER >= 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 _MSC_VER >= 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 (_MSC_VER >= 1400) || (defined(_MSC_VER) && !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 (_MSC_VER >= 1400) || (defined(_MSC_VER) && !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 (_MSC_VER >= 1400) || (defined(_MSC_VER) && !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 +} + +/// \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. +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); + 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); +} + +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)); +} + +inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const byte *) +{ + CRYPTOPP_UNUSED(order); + return block[0]; +} + +inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word16 *) +{ + return (order == BIG_ENDIAN_ORDER) + ? block[1] | (block[0] << 8) + : block[0] | (block[1] << 8); +} + +inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word32 *) +{ + 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); +} + +inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word64 *) +{ + 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)); +} + +inline void UnalignedbyteNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock) +{ + CRYPTOPP_UNUSED(order); + block[0] = static_cast(xorBlock ? (value ^ xorBlock[0]) : value); +} + +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); + } + } +} + +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); + } + } +} + +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); + } + } +} + +/// \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/external/ours/library/crypto/src/shared/original/modarith.h b/external/ours/library/crypto/src/shared/original/modarith.h new file mode 100755 index 000000000..a92aafe97 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/modes.cpp b/external/ours/library/crypto/src/shared/original/modes.cpp new file mode 100755 index 000000000..a95e7a952 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/modes.cpp @@ -0,0 +1,306 @@ +// modes.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "modes.h" +#include "misc.h" + +#if defined(CRYPTOPP_DEBUG) +#include "des.h" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void Modes_TestInstantiations() +{ + CFB_Mode::Encryption m0; + CFB_Mode::Decryption m1; + OFB_Mode::Encryption m2; + CTR_Mode::Encryption m3; + ECB_Mode::Encryption m4; + CBC_Mode::Encryption m5; +} +#endif + +void CipherModeBase::ResizeBuffers() +{ + m_register.New(m_cipher->BlockSize()); +} + +void CFB_ModePolicy::Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) +{ + CRYPTOPP_ASSERT(input); CRYPTOPP_ASSERT(output); + CRYPTOPP_ASSERT(m_cipher->IsForwardTransformation()); + CRYPTOPP_ASSERT(m_register.size() == BlockSize()); + CRYPTOPP_ASSERT(m_temp.size() == BlockSize()); + CRYPTOPP_ASSERT(iterationCount > 0); + + const unsigned int s = BlockSize(); + if (dir == ENCRYPTION) + { + m_cipher->ProcessAndXorBlock(m_register, input, output); + if (iterationCount > 1) + m_cipher->AdvancedProcessBlocks(output, PtrAdd(input,s), PtrAdd(output,s), (iterationCount-1)*s, 0); + memcpy(m_register, PtrAdd(output,(iterationCount-1)*s), s); + } + else + { + // make copy first in case of in-place decryption + memcpy(m_temp, PtrAdd(input,(iterationCount-1)*s), s); + if (iterationCount > 1) + m_cipher->AdvancedProcessBlocks(input, PtrAdd(input,s), PtrAdd(output,s), (iterationCount-1)*s, BlockTransformation::BT_ReverseDirection); + m_cipher->ProcessAndXorBlock(m_register, input, output); + memcpy(m_register, m_temp, s); + } +} + +void CFB_ModePolicy::TransformRegister() +{ + CRYPTOPP_ASSERT(m_cipher->IsForwardTransformation()); + CRYPTOPP_ASSERT(m_register.size() == BlockSize()); + CRYPTOPP_ASSERT(m_temp.size() == BlockSize()); + + const ptrdiff_t updateSize = BlockSize()-m_feedbackSize; + m_cipher->ProcessBlock(m_register, m_temp); + memmove_s(m_register, m_register.size(), PtrAdd(m_register.begin(),m_feedbackSize), updateSize); + memcpy_s(PtrAdd(m_register.begin(),updateSize), m_register.size()-updateSize, m_temp, m_feedbackSize); +} + +void CFB_ModePolicy::CipherResynchronize(const byte *iv, size_t length) +{ + CRYPTOPP_ASSERT(length == BlockSize()); + CRYPTOPP_ASSERT(m_register.size() == BlockSize()); + + CopyOrZero(m_register, m_register.size(), iv, length); + TransformRegister(); +} + +void CFB_ModePolicy::SetFeedbackSize(unsigned int feedbackSize) +{ + if (feedbackSize > BlockSize()) + throw InvalidArgument("CFB_Mode: invalid feedback size"); + m_feedbackSize = feedbackSize ? feedbackSize : BlockSize(); +} + +void CFB_ModePolicy::ResizeBuffers() +{ + CipherModeBase::ResizeBuffers(); + m_temp.New(BlockSize()); +} + +byte* CFB_ModePolicy::GetRegisterBegin() +{ + CRYPTOPP_ASSERT(!m_register.empty()); + CRYPTOPP_ASSERT(BlockSize() >= m_feedbackSize); + return PtrAdd(m_register.begin(), BlockSize() - m_feedbackSize); +} + +void OFB_ModePolicy::WriteKeystream(byte *keystreamBuffer, size_t iterationCount) +{ + CRYPTOPP_ASSERT(m_cipher->IsForwardTransformation()); + CRYPTOPP_ASSERT(m_register.size() == BlockSize()); + CRYPTOPP_ASSERT(iterationCount > 0); + + const unsigned int s = BlockSize(); + m_cipher->ProcessBlock(m_register, keystreamBuffer); + if (iterationCount > 1) + m_cipher->AdvancedProcessBlocks(keystreamBuffer, NULLPTR, PtrAdd(keystreamBuffer, s), s*(iterationCount-1), 0); + memcpy(m_register, PtrAdd(keystreamBuffer, (iterationCount-1)*s), s); +} + +void OFB_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(m_register.size() == BlockSize()); + CRYPTOPP_ASSERT(length == BlockSize()); + + CopyOrZero(m_register, m_register.size(), iv, length); +} + +void CTR_ModePolicy::SeekToIteration(lword iterationCount) +{ + int carry=0; + for (int i=BlockSize()-1; i>=0; i--) + { + unsigned int sum = m_register[i] + (byte)iterationCount + carry; + m_counterArray[i] = byte(sum & 0xff); + carry = sum >> 8; + iterationCount >>= 8; + } +} + +void CTR_ModePolicy::IncrementCounterBy256() +{ + IncrementCounterByOne(m_counterArray, BlockSize()-1); +} + +void CTR_ModePolicy::OperateKeystream(KeystreamOperation /*operation*/, byte *output, const byte *input, size_t iterationCount) +{ + CRYPTOPP_ASSERT(m_cipher->IsForwardTransformation()); + CRYPTOPP_ASSERT(m_counterArray.size() == BlockSize()); + + const unsigned int s = BlockSize(); + const unsigned int inputIncrement = input ? s : 0; + + while (iterationCount) + { + const byte lsb = m_counterArray[s-1]; + const size_t blocks = UnsignedMin(iterationCount, 256U-lsb); + + m_cipher->AdvancedProcessBlocks(m_counterArray, input, output, blocks*s, BlockTransformation::BT_InBlockIsCounter|BlockTransformation::BT_AllowParallel); + if ((m_counterArray[s-1] = byte(lsb + blocks)) == 0) + IncrementCounterBy256(); + + output = PtrAdd(output, blocks*s); + input = PtrAdd(input, blocks*inputIncrement); + iterationCount -= blocks; + } +} + +void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(m_register.size() == BlockSize()); + CRYPTOPP_ASSERT(length == BlockSize()); + + CopyOrZero(m_register, m_register.size(), iv, length); + m_counterArray.Assign(m_register.begin(), m_register.size()); +} + +void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + m_cipher->SetKey(key, length, params); + ResizeBuffers(); + if (IsResynchronizable()) + { + size_t ivLength; + const byte *iv = GetIVAndThrowIfInvalid(params, ivLength); + Resynchronize(iv, (int)ivLength); + } +} + +void BlockOrientedCipherModeBase::ResizeBuffers() +{ + CipherModeBase::ResizeBuffers(); + m_buffer.New(BlockSize()); +} + +void ECB_OneWay::ProcessData(byte *outString, const byte *inString, size_t length) +{ + CRYPTOPP_ASSERT(length%BlockSize()==0); + m_cipher->AdvancedProcessBlocks(inString, NULLPTR, outString, length, BlockTransformation::BT_AllowParallel); +} + +void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t length) +{ + CRYPTOPP_ASSERT(length%BlockSize()==0); + CRYPTOPP_ASSERT(m_register.size() == BlockSize()); + if (!length) return; + + const unsigned int blockSize = BlockSize(); + m_cipher->AdvancedProcessBlocks(inString, m_register, outString, blockSize, BlockTransformation::BT_XorInput); + if (length > blockSize) + m_cipher->AdvancedProcessBlocks(PtrAdd(inString,blockSize), outString, PtrAdd(outString,blockSize), length-blockSize, BlockTransformation::BT_XorInput); + memcpy(m_register, PtrAdd(outString, length - blockSize), blockSize); +} + +size_t CBC_CTS_Encryption::ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength) +{ + CRYPTOPP_UNUSED(outLength); + const size_t used = inLength; + const unsigned int blockSize = BlockSize(); + + if (inLength <= blockSize) + { + if (!m_stolenIV) + throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing"); + + // steal from IV + memcpy(outString, m_register, inLength); + outString = m_stolenIV; + } + else + { + // steal from next to last block + xorbuf(m_register, inString, blockSize); + m_cipher->ProcessBlock(m_register); + inString = PtrAdd(inString, blockSize); + inLength -= blockSize; + memcpy(PtrAdd(outString, blockSize), m_register, inLength); + } + + // output last full ciphertext block + xorbuf(m_register, inString, inLength); + m_cipher->ProcessBlock(m_register); + memcpy(outString, m_register, blockSize); + + return used; +} + +void CBC_Decryption::ResizeBuffers() +{ + BlockOrientedCipherModeBase::ResizeBuffers(); + m_temp.New(BlockSize()); +} + +void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t length) +{ + CRYPTOPP_ASSERT(length%BlockSize()==0); + if (!length) {return;} + + // save copy now in case of in-place decryption + const unsigned int blockSize = BlockSize(); + memcpy(m_temp, PtrAdd(inString, length-blockSize), blockSize); + if (length > blockSize) + m_cipher->AdvancedProcessBlocks(PtrAdd(inString,blockSize), inString, PtrAdd(outString,blockSize), length-blockSize, BlockTransformation::BT_ReverseDirection|BlockTransformation::BT_AllowParallel); + m_cipher->ProcessAndXorBlock(inString, m_register, outString); + m_register.swap(m_temp); +} + +size_t CBC_CTS_Decryption::ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength) +{ + CRYPTOPP_UNUSED(outLength); + const byte *pn1, *pn2; + const size_t used = inLength; + const bool stealIV = inLength <= BlockSize(); + const unsigned int blockSize = BlockSize(); + + if (stealIV) + { + pn1 = inString; + pn2 = m_register; + } + else + { + pn1 = PtrAdd(inString, blockSize); + pn2 = inString; + inLength -= blockSize; + } + + // decrypt last partial plaintext block + memcpy(m_temp, pn2, blockSize); + m_cipher->ProcessBlock(m_temp); + xorbuf(m_temp, pn1, inLength); + + if (stealIV) + { + memcpy(outString, m_temp, inLength); + } + else + { + memcpy(PtrAdd(outString, blockSize), m_temp, inLength); + // decrypt next to last plaintext block + memcpy(m_temp, pn1, inLength); + m_cipher->ProcessBlock(m_temp); + xorbuf(outString, m_temp, m_register, blockSize); + } + + return used; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/modes.h b/external/ours/library/crypto/src/shared/original/modes.h new file mode 100755 index 000000000..0bf1131d4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 + 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/external/ours/library/crypto/src/shared/original/modexppc.h b/external/ours/library/crypto/src/shared/original/modexppc.h new file mode 100755 index 000000000..5e8dd6760 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/mqueue.cpp b/external/ours/library/crypto/src/shared/original/mqueue.cpp index 314d6f758..814c459d6 100755 --- a/external/ours/library/crypto/src/shared/original/mqueue.cpp +++ b/external/ours/library/crypto/src/shared/original/mqueue.cpp @@ -1,44 +1,175 @@ -// mqueue.cpp - written and placed in the public domain by Wei Dai - -#include "FirstCrypto.h" -#include "mqueue.h" - -NAMESPACE_BEGIN(CryptoPP) - -MessageQueue::MessageQueue(unsigned int nodeSize) - : m_queue(nodeSize), m_lengths(1, 0) -{ -} - -bool MessageQueue::RetrieveNextMessage() -{ - if (NumberOfMessages() > 0 && !AnyRetrievable()) - { - m_lengths.pop_front(); - return true; - } - else - return false; -} - -unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count) const -{ - ByteQueue::Walker walker(m_queue); - std::deque::const_iterator it = m_lengths.begin(); - unsigned int i; - for (i=0; i= MaxRetrievable()) + return 0; + + return m_queue.CopyRangeTo2(target, begin, STDMIN(MaxRetrievable(), end), channel, blocking); +} + +size_t MessageQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + transferBytes = STDMIN(MaxRetrievable(), transferBytes); + size_t blockedBytes = m_queue.TransferTo2(target, transferBytes, channel, blocking); + m_lengths.front() -= transferBytes; + return blockedBytes; +} + +bool MessageQueue::GetNextMessage() +{ + if (NumberOfMessages() > 0 && !AnyRetrievable()) + { + m_lengths.pop_front(); + if (m_messageCounts[0] == 0 && m_messageCounts.size() > 1) + m_messageCounts.pop_front(); + return true; + } + else + return false; +} + +unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const +{ + ByteQueue::Walker walker(m_queue); + std::deque::const_iterator it = m_lengths.begin(); + unsigned int i; + for (i=0; i 0 && q2.AnyRetrievable()) + { + size_t len = length; + const byte *data = q2.Spy(len); + len = STDMIN(len, length); + if (memcmp(inString, data, len) != 0) + goto mismatch; + inString += len; + length -= len; + q2.Skip(len); + } + + q1.Put(inString, length); + + if (messageEnd) + { + if (q2.AnyRetrievable()) + goto mismatch; + else if (q2.AnyMessages()) + q2.GetNextMessage(); + else if (q2.NumberOfMessageSeries() > 0) + goto mismatch; + else + q1.MessageEnd(); + } + + return 0; + +mismatch: + return HandleMismatchDetected(blocking); + } +} + +bool EqualityComparisonFilter::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) +{ + unsigned int i = MapChannel(channel); + + if (i == 2) + { + OutputMessageSeriesEnd(4, propagation, blocking, channel); + return false; + } + else if (m_mismatchDetected) + return false; + else + { + MessageQueue &q1 = m_q[i], &q2 = m_q[1-i]; + + if (q2.AnyRetrievable() || q2.AnyMessages()) + goto mismatch; + else if (q2.NumberOfMessageSeries() > 0) + return Output(2, (const byte *)"\1", 1, 0, blocking) != 0; + else + q1.MessageSeriesEnd(); + + return false; + +mismatch: + return HandleMismatchDetected(blocking); + } +} + +bool EqualityComparisonFilter::HandleMismatchDetected(bool blocking) +{ + m_mismatchDetected = true; + if (m_throwIfNotEqual) + throw MismatchDetected(); + const byte b[1] = {0}; + return Output(1, b, 1, 0, blocking) != 0; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/mqueue.h b/external/ours/library/crypto/src/shared/original/mqueue.h index 822df8003..a724286fe 100755 --- a/external/ours/library/crypto/src/shared/original/mqueue.h +++ b/external/ours/library/crypto/src/shared/original/mqueue.h @@ -1,61 +1,145 @@ -#ifndef CRYPTOPP_MQUEUE_H -#define CRYPTOPP_MQUEUE_H - -#include "queue.h" -#include "filters.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -//! Message Queue -class MessageQueue : public BufferedTransformationWithAutoSignal -{ -public: - MessageQueue(unsigned int nodeSize=256); - - void Put(byte inByte) - {m_queue.Put(inByte); m_lengths.back()++;} - void Put(const byte *inString, unsigned int length) - {m_queue.Put(inString, length); m_lengths.back()+=length;} - - unsigned long MaxRetrievable() const - {return m_lengths.front();} - bool AnyRetrievable() const - {return m_lengths.front() > 0;} - - unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX) - {return Got(m_queue.TransferTo(target, STDMIN(MaxRetrievable(), transferMax)));} - unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const - {return m_queue.CopyTo(target, STDMIN(MaxRetrievable(), copyMax));} - - void MessageEnd(int=-1) - {m_lengths.push_back(0);} - - unsigned long TotalBytesRetrievable() const - {return m_queue.MaxRetrievable();} - unsigned int NumberOfMessages() const - {return m_lengths.size()-1;} - bool RetrieveNextMessage(); - - unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX) const; - - void swap(MessageQueue &rhs); - -private: - unsigned long Got(unsigned long length) - {assert(m_lengths.front() >= length); m_lengths.front() -= length; return length;} - - ByteQueue m_queue; - std::deque m_lengths; -}; - -NAMESPACE_END - -NAMESPACE_BEGIN(std) -template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b) -{ - a.swap(b); -} -NAMESPACE_END - -#endif +// 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/external/ours/library/crypto/src/shared/original/mqv.cpp b/external/ours/library/crypto/src/shared/original/mqv.cpp new file mode 100755 index 000000000..ef886251e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/mqv.cpp @@ -0,0 +1,46 @@ +// mqv.cpp - originally written and placed in the public domain by Wei Dai +// HMQV provided by Jeffrey Walton, Ray Clayton and Uri Blumenthal. +// FHMQV provided by Uri Blumenthal. + +#include "pch.h" +#include "config.h" +#include "mqv.h" +#include "hmqv.h" +#include "fhmqv.h" +#include "eccrypto.h" + +// Squash MS LNK4221 and libtool warnings +extern const char MQV_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void TestInstantiations_MQV() +{ + MQV mqv; + ECMQV ecmqv; + + CRYPTOPP_UNUSED(mqv); + CRYPTOPP_UNUSED(ecmqv); +} + +void TestInstantiations_HMQV() +{ + HMQV hmqv; + ECHMQV echmqv; + + CRYPTOPP_UNUSED(hmqv); + CRYPTOPP_UNUSED(echmqv); +} + +void TestInstantiations_FHMQV() +{ + FHMQV fhmqv; + ECFHMQV ecfhmqv; + + CRYPTOPP_UNUSED(fhmqv); + CRYPTOPP_UNUSED(ecfhmqv); +} +#endif + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/mqv.h b/external/ours/library/crypto/src/shared/original/mqv.h new file mode 100755 index 000000000..7ab18e55b --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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); + 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/external/ours/library/crypto/src/shared/original/naclite.h b/external/ours/library/crypto/src/shared/original/naclite.h new file mode 100755 index 000000000..586897209 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/nbtheory.cpp b/external/ours/library/crypto/src/shared/original/nbtheory.cpp new file mode 100755 index 000000000..a6087a0be --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/nbtheory.cpp @@ -0,0 +1,1141 @@ +// nbtheory.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "nbtheory.h" +#include "integer.h" +#include "modarith.h" +#include "algparam.h" +#include "smartptr.h" +#include "misc.h" +#include "stdcpp.h" + +#ifdef _OPENMP +# include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +const word s_lastSmallPrime = 32719; + +struct NewPrimeTable +{ + std::vector * operator()() const + { + const unsigned int maxPrimeTableSize = 3511; + + member_ptr > pPrimeTable(new std::vector); + std::vector &primeTable = *pPrimeTable; + primeTable.reserve(maxPrimeTableSize); + + primeTable.push_back(2); + unsigned int testEntriesEnd = 1; + + for (unsigned int p=3; p<=s_lastSmallPrime; p+=2) + { + unsigned int j; + for (j=1; j &primeTable = Singleton, NewPrimeTable>().Ref(); + size = (unsigned int)primeTable.size(); + return &primeTable[0]; +} + +bool IsSmallPrime(const Integer &p) +{ + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + if (p.IsPositive() && p <= primeTable[primeTableSize-1]) + return std::binary_search(primeTable, primeTable+primeTableSize, (word16)p.ConvertToLong()); + else + return false; +} + +bool TrialDivision(const Integer &p, unsigned bound) +{ + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + CRYPTOPP_ASSERT(primeTable[primeTableSize-1] >= bound); + + unsigned int i; + for (i = 0; primeTable[i]3 && b>1 && b3 && b>1 && b>a; + + Integer z = a_exp_b_mod_c(b, m, n); + if (z==1 || z==nminus1) + return true; + for (unsigned j=1; j3); + + Integer b; + for (unsigned int i=0; i2); + + Integer b=3; + unsigned int i=0; + int j; + + while ((j=Jacobi(b.Squared()-4, n)) == 1) + { + if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square + return false; + ++b; ++b; + } + + if (j==0) + return false; + else + return Lucas(n+1, b, n)==2; +} + +bool IsStrongLucasProbablePrime(const Integer &n) +{ + if (n <= 1) + return false; + + if (n.IsEven()) + return n==2; + + CRYPTOPP_ASSERT(n>2); + + Integer b=3; + unsigned int i=0; + int j; + + while ((j=Jacobi(b.Squared()-4, n)) == 1) + { + if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square + return false; + ++b; ++b; + } + + if (j==0) + return false; + + Integer n1 = n+1; + unsigned int a; + + // calculate a = largest power of 2 that divides n1 + for (a=0; ; a++) + if (n1.GetBit(a)) + break; + Integer m = n1>>a; + + Integer z = Lucas(m, b, n); + if (z==2 || z==n-2) + return true; + for (i=1; i().Ref()) + return SmallDivisorsTest(p); + else + return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p); +} + +bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level) +{ + bool pass = IsPrime(p) && RabinMillerTest(rng, p, 1); + if (level >= 1) + pass = pass && RabinMillerTest(rng, p, 10); + return pass; +} + +unsigned int PrimeSearchInterval(const Integer &max) +{ + return max.BitCount(); +} + +static inline bool FastProbablePrimeTest(const Integer &n) +{ + return IsStrongProbablePrime(n,2); +} + +AlgorithmParameters MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength) +{ + if (productBitLength < 16) + throw InvalidArgument("invalid bit length"); + + Integer minP, maxP; + + if (productBitLength%2==0) + { + minP = Integer(182) << (productBitLength/2-8); + maxP = Integer::Power2(productBitLength/2)-1; + } + else + { + minP = Integer::Power2((productBitLength-1)/2); + maxP = Integer(181) << ((productBitLength+1)/2-8); + } + + return MakeParameters("RandomNumberType", Integer::PRIME)("Min", minP)("Max", maxP); +} + +class PrimeSieve +{ +public: + // delta == 1 or -1 means double sieve with p = 2*q + delta + PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta=0); + bool NextCandidate(Integer &c); + + void DoSieve(); + static void SieveSingle(std::vector &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv); + + Integer m_first, m_last, m_step; + signed int m_delta; + word m_next; + std::vector m_sieve; +}; + +PrimeSieve::PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta) + : m_first(first), m_last(last), m_step(step), m_delta(delta), m_next(0) +{ + DoSieve(); +} + +bool PrimeSieve::NextCandidate(Integer &c) +{ + bool safe = SafeConvert(std::find(m_sieve.begin()+m_next, m_sieve.end(), false) - m_sieve.begin(), m_next); + CRYPTOPP_UNUSED(safe); CRYPTOPP_ASSERT(safe); + if (m_next == m_sieve.size()) + { + m_first += long(m_sieve.size())*m_step; + if (m_first > m_last) + return false; + else + { + m_next = 0; + DoSieve(); + return NextCandidate(c); + } + } + else + { + c = m_first + long(m_next)*m_step; + ++m_next; + return true; + } +} + +void PrimeSieve::SieveSingle(std::vector &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv) +{ + if (stepInv) + { + size_t sieveSize = sieve.size(); + size_t j = (word32(p-(first%p))*stepInv) % p; + // if the first multiple of p is p, skip it + if (first.WordCount() <= 1 && first + step*long(j) == p) + j += p; + for (; j < sieveSize; j += p) + sieve[j] = true; + } +} + +void PrimeSieve::DoSieve() +{ + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + const unsigned int maxSieveSize = 32768; + unsigned int sieveSize = STDMIN(Integer(maxSieveSize), (m_last-m_first)/m_step+1).ConvertToLong(); + + m_sieve.clear(); + m_sieve.resize(sieveSize, false); + + if (m_delta == 0) + { + for (unsigned int i = 0; i < primeTableSize; ++i) + SieveSingle(m_sieve, primeTable[i], m_first, m_step, (word16)m_step.InverseMod(primeTable[i])); + } + else + { + CRYPTOPP_ASSERT(m_step%2==0); + Integer qFirst = (m_first-m_delta) >> 1; + Integer halfStep = m_step >> 1; + for (unsigned int i = 0; i < primeTableSize; ++i) + { + word16 p = primeTable[i]; + word16 stepInv = (word16)m_step.InverseMod(p); + SieveSingle(m_sieve, p, m_first, m_step, stepInv); + + word16 halfStepInv = 2*stepInv < p ? 2*stepInv : 2*stepInv-p; + SieveSingle(m_sieve, p, qFirst, halfStep, halfStepInv); + } + } +} + +bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector) +{ + CRYPTOPP_ASSERT(!equiv.IsNegative() && equiv < mod); + + Integer gcd = GCD(equiv, mod); + if (gcd != Integer::One()) + { + // the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv) + if (p <= gcd && gcd <= max && IsPrime(gcd) && (!pSelector || pSelector->IsAcceptable(gcd))) + { + p = gcd; + return true; + } + else + return false; + } + + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + if (p <= primeTable[primeTableSize-1]) + { + const word16 *pItr; + + --p; + if (p.IsPositive()) + pItr = std::upper_bound(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong()); + else + pItr = primeTable; + + while (pItr < primeTable+primeTableSize && !(*pItr%mod == equiv && (!pSelector || pSelector->IsAcceptable(*pItr)))) + ++pItr; + + if (pItr < primeTable+primeTableSize) + { + p = *pItr; + return p <= max; + } + + p = primeTable[primeTableSize-1]+1; + } + + CRYPTOPP_ASSERT(p > primeTable[primeTableSize-1]); + + if (mod.IsOdd()) + return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1, pSelector); + + p += (equiv-p)%mod; + + if (p>max) + return false; + + PrimeSieve sieve(p, max, mod); + + while (sieve.NextCandidate(p)) + { + if ((!pSelector || pSelector->IsAcceptable(p)) && FastProbablePrimeTest(p) && IsPrime(p)) + return true; + } + + return false; +} + +// the following two functions are based on code and comments provided by Preda Mihailescu +static bool ProvePrime(const Integer &p, const Integer &q) +{ + CRYPTOPP_ASSERT(p < q*q*q); + CRYPTOPP_ASSERT(p % q == 1); + +// this is the Quisquater test. Numbers p having passed the Lucas - Lehmer test +// for q and verifying p < q^3 can only be built up of two factors, both = 1 mod q, +// or be prime. The next two lines build the discriminant of a quadratic equation +// which holds iff p is built up of two factors (exercise ... ) + + Integer r = (p-1)/q; + if (((r%q).Squared()-4*(r/q)).IsSquare()) + return false; + + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + CRYPTOPP_ASSERT(primeTableSize >= 50); + for (int i=0; i<50; i++) + { + Integer b = a_exp_b_mod_c(primeTable[i], r, p); + if (b != 1) + return a_exp_b_mod_c(b, q, p) == 1; + } + return false; +} + +Integer MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int pbits) +{ + Integer p; + Integer minP = Integer::Power2(pbits-1); + Integer maxP = Integer::Power2(pbits) - 1; + + if (maxP <= Integer(s_lastSmallPrime).Squared()) + { + // Randomize() will generate a prime provable by trial division + p.Randomize(rng, minP, maxP, Integer::PRIME); + return p; + } + + unsigned int qbits = (pbits+2)/3 + 1 + rng.GenerateWord32(0, pbits/36); + Integer q = MihailescuProvablePrime(rng, qbits); + Integer q2 = q<<1; + + while (true) + { + // this initializes the sieve to search in the arithmetic + // progression p = p_0 + \lambda * q2 = p_0 + 2 * \lambda * q, + // with q the recursively generated prime above. We will be able + // to use Lucas tets for proving primality. A trick of Quisquater + // allows taking q > cubic_root(p) rather than square_root: this + // decreases the recursion. + + p.Randomize(rng, minP, maxP, Integer::ANY, 1, q2); + PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*q2, maxP), q2); + + while (sieve.NextCandidate(p)) + { + if (FastProbablePrimeTest(p) && ProvePrime(p, q)) + return p; + } + } + + // not reached + return p; +} + +Integer MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits) +{ + const unsigned smallPrimeBound = 29, c_opt=10; + Integer p; + + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + if (bits < smallPrimeBound) + { + do + p.Randomize(rng, Integer::Power2(bits-1), Integer::Power2(bits)-1, Integer::ANY, 1, 2); + while (TrialDivision(p, 1 << ((bits+1)/2))); + } + else + { + const unsigned margin = bits > 50 ? 20 : (bits-10)/2; + double relativeSize; + do + relativeSize = std::pow(2.0, double(rng.GenerateWord32())/0xffffffff - 1); + while (bits * relativeSize >= bits - margin); + + Integer a,b; + Integer q = MaurerProvablePrime(rng, unsigned(bits*relativeSize)); + Integer I = Integer::Power2(bits-2)/q; + Integer I2 = I << 1; + unsigned int trialDivisorBound = (unsigned int)STDMIN((unsigned long)primeTable[primeTableSize-1], (unsigned long)bits*bits/c_opt); + bool success = false; + while (!success) + { + p.Randomize(rng, I, I2, Integer::ANY); + p *= q; p <<= 1; ++p; + if (!TrialDivision(p, trialDivisorBound)) + { + a.Randomize(rng, 2, p-1, Integer::ANY); + b = a_exp_b_mod_c(a, (p-1)/q, p); + success = (GCD(b-1, p) == 1) && (a_exp_b_mod_c(b, q, p) == 1); + } + } + } + return p; +} + +Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u) +{ + // isn't operator overloading great? + return p * (u * (xq-xp) % q) + xp; +/* + Integer t1 = xq-xp; + cout << hex << t1 << endl; + Integer t2 = u * t1; + cout << hex << t2 << endl; + Integer t3 = t2 % q; + cout << hex << t3 << endl; + Integer t4 = p * t3; + cout << hex << t4 << endl; + Integer t5 = t4 + xp; + cout << hex << t5 << endl; + return t5; +*/ +} + +Integer ModularSquareRoot(const Integer &a, const Integer &p) +{ + if (p%4 == 3) + return a_exp_b_mod_c(a, (p+1)/4, p); + + Integer q=p-1; + unsigned int r=0; + while (q.IsEven()) + { + r++; + q >>= 1; + } + + Integer n=2; + while (Jacobi(n, p) != -1) + ++n; + + Integer y = a_exp_b_mod_c(n, q, p); + Integer x = a_exp_b_mod_c(a, (q-1)/2, p); + Integer b = (x.Squared()%p)*a%p; + x = a*x%p; + Integer tempb, t; + + while (b != 1) + { + unsigned m=0; + tempb = b; + do + { + m++; + b = b.Squared()%p; + if (m==r) + return Integer::Zero(); + } + while (b != 1); + + t = y; + for (unsigned i=0; i>= 1; + b >>= 1; + k++; + } + + while (a[0]==0) + a >>= 1; + + while (b[0]==0) + b >>= 1; + + while (1) + { + switch (a.Compare(b)) + { + case -1: + b -= a; + while (b[0]==0) + b >>= 1; + break; + + case 0: + return (a <<= k); + + case 1: + a -= b; + while (a[0]==0) + a >>= 1; + break; + + default: + CRYPTOPP_ASSERT(false); + } + } +} + +Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b) +{ + CRYPTOPP_ASSERT(b.Positive()); + + if (a.Negative()) + return EuclideanMultiplicativeInverse(a%b, b); + + if (b[0]==0) + { + if (!b || a[0]==0) + return Integer::Zero(); // no inverse + if (a==1) + return 1; + Integer u = EuclideanMultiplicativeInverse(b, a); + if (!u) + return Integer::Zero(); // no inverse + else + return (b*(a-u)+1)/a; + } + + Integer u=1, d=a, v1=b, v3=b, t1, t3, b2=(b+1)>>1; + + if (a[0]) + { + t1 = Integer::Zero(); + t3 = -b; + } + else + { + t1 = b2; + t3 = a>>1; + } + + while (!!t3) + { + while (t3[0]==0) + { + t3 >>= 1; + if (t1[0]==0) + t1 >>= 1; + else + { + t1 >>= 1; + t1 += b2; + } + } + if (t3.Positive()) + { + u = t1; + d = t3; + } + else + { + v1 = b-t1; + v3 = -t3; + } + t1 = u-v1; + t3 = d-v3; + if (t1.Negative()) + t1 += b; + } + if (d==1) + return u; + else + return Integer::Zero(); // no inverse +} +*/ + +int Jacobi(const Integer &aIn, const Integer &bIn) +{ + CRYPTOPP_ASSERT(bIn.IsOdd()); + + Integer b = bIn, a = aIn%bIn; + int result = 1; + + while (!!a) + { + unsigned i=0; + while (a.GetBit(i)==0) + i++; + a>>=i; + + if (i%2==1 && (b%8==3 || b%8==5)) + result = -result; + + if (a%4==3 && b%4==3) + result = -result; + + std::swap(a, b); + a %= b; + } + + return (b==1) ? result : 0; +} + +Integer Lucas(const Integer &e, const Integer &pIn, const Integer &n) +{ + unsigned i = e.BitCount(); + if (i==0) + return Integer::Two(); + + MontgomeryRepresentation m(n); + Integer p=m.ConvertIn(pIn%n), two=m.ConvertIn(Integer::Two()); + Integer v=p, v1=m.Subtract(m.Square(p), two); + + i--; + while (i--) + { + if (e.GetBit(i)) + { + // v = (v*v1 - p) % m; + v = m.Subtract(m.Multiply(v,v1), p); + // v1 = (v1*v1 - 2) % m; + v1 = m.Subtract(m.Square(v1), two); + } + else + { + // v1 = (v*v1 - p) % m; + v1 = m.Subtract(m.Multiply(v,v1), p); + // v = (v*v - 2) % m; + v = m.Subtract(m.Square(v), two); + } + } + return m.ConvertOut(v); +} + +// This is Peter Montgomery's unpublished Lucas sequence evalutation algorithm. +// The total number of multiplies and squares used is less than the binary +// algorithm (see above). Unfortunately I can't get it to run as fast as +// the binary algorithm because of the extra overhead. +/* +Integer Lucas(const Integer &n, const Integer &P, const Integer &modulus) +{ + if (!n) + return 2; + +#define f(A, B, C) m.Subtract(m.Multiply(A, B), C) +#define X2(A) m.Subtract(m.Square(A), two) +#define X3(A) m.Multiply(A, m.Subtract(m.Square(A), three)) + + MontgomeryRepresentation m(modulus); + Integer two=m.ConvertIn(2), three=m.ConvertIn(3); + Integer A=m.ConvertIn(P), B, C, p, d=n, e, r, t, T, U; + + while (d!=1) + { + p = d; + unsigned int b = WORD_BITS * p.WordCount(); + Integer alpha = (Integer(5)<<(2*b-2)).SquareRoot() - Integer::Power2(b-1); + r = (p*alpha)>>b; + e = d-r; + B = A; + C = two; + d = r; + + while (d!=e) + { + if (d>2)) + if ((dm3+em3==0 || dm3+em3==3) && (t = e, t >>= 2, t += e, d <= t)) + { + // #1 +// t = (d+d-e)/3; +// t = d; t += d; t -= e; t /= 3; +// e = (e+e-d)/3; +// e += e; e -= d; e /= 3; +// d = t; + +// t = (d+e)/3 + t = d; t += e; t /= 3; + e -= t; + d -= t; + + T = f(A, B, C); + U = f(T, A, B); + B = f(T, B, A); + A = U; + continue; + } + +// if (dm6 == em6 && d <= e + (e>>2)) + if (dm3 == em3 && dm2 == em2 && (t = e, t >>= 2, t += e, d <= t)) + { + // #2 +// d = (d-e)>>1; + d -= e; d >>= 1; + B = f(A, B, C); + A = X2(A); + continue; + } + +// if (d <= (e<<2)) + if (d <= (t = e, t <<= 2)) + { + // #3 + d -= e; + C = f(A, B, C); + swap(B, C); + continue; + } + + if (dm2 == em2) + { + // #4 +// d = (d-e)>>1; + d -= e; d >>= 1; + B = f(A, B, C); + A = X2(A); + continue; + } + + if (dm2 == 0) + { + // #5 + d >>= 1; + C = f(A, C, B); + A = X2(A); + continue; + } + + if (dm3 == 0) + { + // #6 +// d = d/3 - e; + d /= 3; d -= e; + T = X2(A); + C = f(T, f(A, B, C), C); + swap(B, C); + A = f(T, A, A); + continue; + } + + if (dm3+em3==0 || dm3+em3==3) + { + // #7 +// d = (d-e-e)/3; + d -= e; d -= e; d /= 3; + T = f(A, B, C); + B = f(T, A, B); + A = X3(A); + continue; + } + + if (dm3 == em3) + { + // #8 +// d = (d-e)/3; + d -= e; d /= 3; + T = f(A, B, C); + C = f(A, C, B); + B = T; + A = X3(A); + continue; + } + + CRYPTOPP_ASSERT(em2 == 0); + // #9 + e >>= 1; + C = f(C, B, A); + B = X2(B); + } + + A = f(A, B, C); + } + +#undef f +#undef X2 +#undef X3 + + return m.ConvertOut(A); +} +*/ + +Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u) +{ + + // GCC warning bug, https://stackoverflow.com/q/12842306/608639 +#ifdef _OPENMP + Integer d = (m*m-4), p2, q2; + #pragma omp parallel + #pragma omp sections + { + #pragma omp section + { + p2 = p-Jacobi(d,p); + p2 = Lucas(EuclideanMultiplicativeInverse(e,p2), m, p); + } + #pragma omp section + { + q2 = q-Jacobi(d,q); + q2 = Lucas(EuclideanMultiplicativeInverse(e,q2), m, q); + } + } +#else + const Integer d = (m*m-4); + const Integer t1 = p-Jacobi(d,p); + const Integer p2 = Lucas(EuclideanMultiplicativeInverse(e,t1), m, p); + + const Integer t2 = q-Jacobi(d,q); + const Integer q2 = Lucas(EuclideanMultiplicativeInverse(e,t2), m, q); +#endif + + return CRT(p2, p, q2, q, u); +} + +unsigned int FactoringWorkFactor(unsigned int n) +{ + // extrapolated from the table in Odlyzko's "The Future of Integer Factorization" + // updated to reflect the factoring of RSA-130 + if (n<5) return 0; + else return (unsigned int)(2.4 * std::pow((double)n, 1.0/3.0) * std::pow(log(double(n)), 2.0/3.0) - 5); +} + +unsigned int DiscreteLogWorkFactor(unsigned int n) +{ + // assuming discrete log takes about the same time as factoring + if (n<5) return 0; + else return (unsigned int)(2.4 * std::pow((double)n, 1.0/3.0) * std::pow(log(double(n)), 2.0/3.0) - 5); +} + +// ******************************************************** + +void PrimeAndGenerator::Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits) +{ + // no prime exists for delta = -1, qbits = 4, and pbits = 5 + CRYPTOPP_ASSERT(qbits > 4); + CRYPTOPP_ASSERT(pbits > qbits); + + if (qbits+1 == pbits) + { + Integer minP = Integer::Power2(pbits-1); + Integer maxP = Integer::Power2(pbits) - 1; + bool success = false; + + while (!success) + { + p.Randomize(rng, minP, maxP, Integer::ANY, 6+5*delta, 12); + PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*12, maxP), 12, delta); + + while (sieve.NextCandidate(p)) + { + CRYPTOPP_ASSERT(IsSmallPrime(p) || SmallDivisorsTest(p)); + q = (p-delta) >> 1; + CRYPTOPP_ASSERT(IsSmallPrime(q) || SmallDivisorsTest(q)); + if (FastProbablePrimeTest(q) && FastProbablePrimeTest(p) && IsPrime(q) && IsPrime(p)) + { + success = true; + break; + } + } + } + + if (delta == 1) + { + // find g such that g is a quadratic residue mod p, then g has order q + // g=4 always works, but this way we get the smallest quadratic residue (other than 1) + for (g=2; Jacobi(g, p) != 1; ++g) {} + // contributed by Walt Tuvell: g should be the following according to the Law of Quadratic Reciprocity + CRYPTOPP_ASSERT((p%8==1 || p%8==7) ? g==2 : (p%12==1 || p%12==11) ? g==3 : g==4); + } + else + { + CRYPTOPP_ASSERT(delta == -1); + // find g such that g*g-4 is a quadratic non-residue, + // and such that g has order q + for (g=3; ; ++g) + if (Jacobi(g*g-4, p)==-1 && Lucas(q, g, p)==2) + break; + } + } + else + { + Integer minQ = Integer::Power2(qbits-1); + Integer maxQ = Integer::Power2(qbits) - 1; + Integer minP = Integer::Power2(pbits-1); + Integer maxP = Integer::Power2(pbits) - 1; + + do + { + q.Randomize(rng, minQ, maxQ, Integer::PRIME); + } while (!p.Randomize(rng, minP, maxP, Integer::PRIME, delta%q, q)); + + // find a random g of order q + if (delta==1) + { + do + { + Integer h(rng, 2, p-2, Integer::ANY); + g = a_exp_b_mod_c(h, (p-1)/q, p); + } while (g <= 1); + CRYPTOPP_ASSERT(a_exp_b_mod_c(g, q, p)==1); + } + else + { + CRYPTOPP_ASSERT(delta==-1); + do + { + Integer h(rng, 3, p-1, Integer::ANY); + if (Jacobi(h*h-4, p)==1) + continue; + g = Lucas((p+1)/q, h, p); + } while (g <= 2); + CRYPTOPP_ASSERT(Lucas(q, g, p) == 2); + } + } +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/nbtheory.h b/external/ours/library/crypto/src/shared/original/nbtheory.h new file mode 100755 index 000000000..a396ab462 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/nbtheory.h @@ -0,0 +1,317 @@ +// 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 +/// \details GetPrimeTable obtains pointer to small prime table and provides the size of the table. +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/external/ours/library/crypto/src/shared/original/neon_simd.cpp b/external/ours/library/crypto/src/shared/original/neon_simd.cpp new file mode 100755 index 000000000..602ba0e97 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/neon_simd.cpp @@ -0,0 +1,197 @@ + +// crc_simd.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// +// This source file uses intrinsics to gain access to ARMv7a and +// ARMv8a NEON instructions. A separate source file is needed +// because additional CXXFLAGS are required to enable the +// appropriate instructions sets in some build configurations. +// For Linux and Unix additional flags are not required. + +#include "pch.h" +#include "config.h" +#include "stdcpp.h" + +#if (CRYPTOPP_ARM_NEON_HEADER) +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#ifndef EXCEPTION_EXECUTE_HANDLER +# define EXCEPTION_EXECUTE_HANDLER 1 +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char NEON_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); + + static jmp_buf s_jmpSIGILL; + static void SigIllHandler(int) + { + longjmp(s_jmpSIGILL, 1); + } +} +#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY + +bool CPU_ProbeARMv7() +{ +#if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64) + return false; +#elif defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif CRYPTOPP_ARM_NEON_AVAILABLE +# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) + volatile bool result = true; + __try + { + // Modern MS hardware is ARMv7 + result = true; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + return result; +# else + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + +#if 0 + // ARMv7 added movt and movw + int a; + asm volatile("movw %0,%1 \n" + "movt %0,%1 \n" + : "=r"(a) : "i"(0x1234)); + +00000010 <_Z5test2v>: // ARM + 10: e3010234 movw r0, #4660 ; 0x1234 + 14: e3410234 movt r0, #4660 ; 0x1234 + 18: e12fff1e bx lr + +0000001c <_Z5test3v>: // Thumb + 1c: f241 2034 movw r0, #4660 ; 0x1234 + 20: f2c1 2034 movt r0, #4660 ; 0x1234 + 24: e12fff1e bx lr +#endif + + unsigned int a; + asm volatile ( +#if defined(__thumb__) + ".inst.n 0xf241, 0x2034 \n\t" // movw r0, 0x1234 + ".inst.n 0xf2c1, 0x2034 \n\t" // movt r0, 0x1234 + "mov %0, r0 \n\t" // mov [a], r0 +#else + ".inst 0xe3010234 \n\t" // movw r0, 0x1234 + ".inst 0xe3410234 \n\t" // movt r0, 0x1234 + "mov %0, r0 \n\t" // mov [a], r0 +#endif + : "=r" (a) : : "r0"); + + result = (a == 0x12341234); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_ARM_NEON_AVAILABLE +} + +bool CPU_ProbeNEON() +{ +#if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64) + return true; +#elif defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif CRYPTOPP_ARM_NEON_AVAILABLE +# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) + volatile bool result = true; + __try + { + uint32x4_t x = vdupq_n_u32(1); + uint32x4_t y = vshlq_n_u32(x, 4); + + word32 z[4]; vst1q_u32(z, y); + return (z[0] & z[1] & z[2] & z[3]) == 16; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + return result; +# else + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + // This is risky... When we hand encode the instructions + // for vmov.u32 and vshl.u32 we get a SIGILL. Apparently + // we need more than just the instructions. Using + // intrinsics introduces the risk because the whole + // file gets built with ISA options, and the higher ISA + // may escape the try block with the SIGILL guard. + uint32x4_t x = vdupq_n_u32(1); + uint32x4_t y = vshlq_n_u32(x, 4); + + word32 z[4]; vst1q_u32(z, y); + result = (z[0] & z[1] & z[2] & z[3]) == 16; + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_ARM_NEON_AVAILABLE +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/nr.h b/external/ours/library/crypto/src/shared/original/nr.h new file mode 100755 index 000000000..101f9106e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/oaep.cpp b/external/ours/library/crypto/src/shared/original/oaep.cpp new file mode 100755 index 000000000..fb9e31a0c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/oaep.cpp @@ -0,0 +1,98 @@ +// oaep.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "oaep.h" +#include "stdcpp.h" +#include "smartptr.h" + +NAMESPACE_BEGIN(CryptoPP) + +// ******************************************************** + +size_t OAEP_Base::MaxUnpaddedLength(size_t paddedLength) const +{ + return SaturatingSubtract(paddedLength/8, 1+2*DigestSize()); +} + +void OAEP_Base::Pad(RandomNumberGenerator &rng, const byte *input, size_t inputLength, byte *oaepBlock, size_t oaepBlockLen, const NameValuePairs ¶meters) const +{ + CRYPTOPP_ASSERT (inputLength <= MaxUnpaddedLength(oaepBlockLen)); + + // convert from bit length to byte length + if (oaepBlockLen % 8 != 0) + { + oaepBlock[0] = 0; + oaepBlock++; + } + oaepBlockLen /= 8; + + member_ptr pHash(NewHash()); + const size_t hLen = pHash->DigestSize(); + const size_t seedLen = hLen, dbLen = oaepBlockLen-seedLen; + byte *const maskedSeed = oaepBlock; + byte *const maskedDB = oaepBlock+seedLen; + + ConstByteArrayParameter encodingParameters; + parameters.GetValue(Name::EncodingParameters(), encodingParameters); + + // DB = pHash || 00 ... || 01 || M + pHash->CalculateDigest(maskedDB, encodingParameters.begin(), encodingParameters.size()); + memset(maskedDB+hLen, 0, dbLen-hLen-inputLength-1); + maskedDB[dbLen-inputLength-1] = 0x01; + memcpy(maskedDB+dbLen-inputLength, input, inputLength); + + rng.GenerateBlock(maskedSeed, seedLen); + member_ptr pMGF(NewMGF()); + pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen); + pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen); +} + +DecodingResult OAEP_Base::Unpad(const byte *oaepBlock, size_t oaepBlockLen, byte *output, const NameValuePairs ¶meters) const +{ + bool invalid = false; + + // convert from bit length to byte length + if (oaepBlockLen % 8 != 0) + { + invalid = (oaepBlock[0] != 0) || invalid; + oaepBlock++; + } + oaepBlockLen /= 8; + + member_ptr pHash(NewHash()); + const size_t hLen = pHash->DigestSize(); + const size_t seedLen = hLen, dbLen = oaepBlockLen-seedLen; + + invalid = (oaepBlockLen < 2*hLen+1) || invalid; + + SecByteBlock t(oaepBlock, oaepBlockLen); + byte *const maskedSeed = t; + byte *const maskedDB = t+seedLen; + + member_ptr pMGF(NewMGF()); + pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen); + pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen); + + ConstByteArrayParameter encodingParameters; + parameters.GetValue(Name::EncodingParameters(), encodingParameters); + + // DB = pHash' || 00 ... || 01 || M + byte *M = std::find(maskedDB+hLen, maskedDB+dbLen, 0x01); + invalid = (M == maskedDB+dbLen) || invalid; + invalid = (FindIfNot(maskedDB+hLen, M, byte(0)) != M) || invalid; + invalid = !pHash->VerifyDigest(maskedDB, encodingParameters.begin(), encodingParameters.size()) || invalid; + + if (invalid) + return DecodingResult(); + + M++; + memcpy(output, M, maskedDB+dbLen-M); + return DecodingResult(maskedDB+dbLen-M); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/oaep.h b/external/ours/library/crypto/src/shared/original/oaep.h new file mode 100755 index 000000000..76be7f244 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/oids.h b/external/ours/library/crypto/src/shared/original/oids.h new file mode 100755 index 000000000..016d218ac --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 algorthms 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/external/ours/library/crypto/src/shared/original/osrng.cpp b/external/ours/library/crypto/src/shared/original/osrng.cpp new file mode 100755 index 000000000..5121ac1ed --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/osrng.cpp @@ -0,0 +1,300 @@ +// osrng.cpp - originally written and placed in the public domain by Wei Dai + +// Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool. + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS + +// Win32 has CryptoAPI and . Windows 10 and Windows Store 10 have CNG and . +// There's a hole for Windows Phone 8 and Windows Store 8. There is no userland RNG available. +// Also see http://www.drdobbs.com/windows/using-c-and-com-with-winrt/240168150 and +// http://stackoverflow.com/questions/36974545/random-numbers-for-windows-phone-8-and-windows-store-8 and +// https://social.msdn.microsoft.com/Forums/vstudio/en-US/25b83e13-c85f-4aa1-a057-88a279ea3fd6/what-crypto-random-generator-c-code-could-use-on-wp81 +#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(OS_RNG_AVAILABLE) +# pragma message("WARNING: Compiling for Windows but an OS RNG is not available. This is likely a Windows Phone 8 or Windows Store 8 app.") +#endif + +#if !defined(NO_OS_DEPENDENCE) && defined(OS_RNG_AVAILABLE) + +#include "osrng.h" +#include "rng.h" + +#ifdef CRYPTOPP_WIN32_AVAILABLE +#define WIN32_LEAN_AND_MEAN +#include +#ifndef ERROR_INCORRECT_SIZE +# define ERROR_INCORRECT_SIZE 0x000005B6 +#endif +#if defined(USE_MS_CRYPTOAPI) +#include +#ifndef CRYPT_NEWKEYSET +# define CRYPT_NEWKEYSET 0x00000008 +#endif +#ifndef CRYPT_MACHINE_KEYSET +# define CRYPT_MACHINE_KEYSET 0x00000020 +#endif +#elif defined(USE_MS_CNGAPI) +#include +#ifndef BCRYPT_SUCCESS +# define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif +#ifndef STATUS_INVALID_PARAMETER +# define STATUS_INVALID_PARAMETER 0xC000000D +#endif +#ifndef STATUS_INVALID_HANDLE +# define STATUS_INVALID_HANDLE 0xC0000008 +#endif +#endif +#endif // Win32 + +#ifdef CRYPTOPP_UNIX_AVAILABLE +#include +#include +#include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE) +OS_RNG_Err::OS_RNG_Err(const std::string &operation) + : Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " + +#ifdef CRYPTOPP_WIN32_AVAILABLE + "0x" + IntToString(GetLastError(), 16) +#else + IntToString(errno) +#endif + ) +{ +} +#endif + +#ifdef NONBLOCKING_RNG_AVAILABLE + +#ifdef CRYPTOPP_WIN32_AVAILABLE + +#if defined(USE_MS_CNGAPI) +inline DWORD NtStatusToErrorCode(NTSTATUS status) +{ + if (status == STATUS_INVALID_PARAMETER) + return ERROR_INVALID_PARAMETER; + else if (status == STATUS_INVALID_HANDLE) + return ERROR_INVALID_HANDLE; + else + return (DWORD)status; +} +#endif + +#if defined(UNICODE) || defined(_UNICODE) +# define CRYPTOPP_CONTAINER L"Crypto++ RNG" +#else +# define CRYPTOPP_CONTAINER "Crypto++ RNG" +#endif + +MicrosoftCryptoProvider::MicrosoftCryptoProvider() : m_hProvider(0) +{ +#if defined(USE_MS_CRYPTOAPI) + // See http://support.microsoft.com/en-us/kb/238187 for CRYPT_NEWKEYSET fallback strategy + if (!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + { + const DWORD firstErr = GetLastError(); + if (!CryptAcquireContext(&m_hProvider, CRYPTOPP_CONTAINER, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET /*user*/) && + !CryptAcquireContext(&m_hProvider, CRYPTOPP_CONTAINER, 0, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET|CRYPT_NEWKEYSET)) + { + // Set original error with original code + SetLastError(firstErr); + throw OS_RNG_Err("CryptAcquireContext"); + } + } +#elif defined(USE_MS_CNGAPI) + NTSTATUS ret = BCryptOpenAlgorithmProvider(&m_hProvider, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); + if (!(BCRYPT_SUCCESS(ret))) + { + // Hack... OS_RNG_Err calls GetLastError() + SetLastError(NtStatusToErrorCode(ret)); + throw OS_RNG_Err("BCryptOpenAlgorithmProvider"); + } +#endif +} + +MicrosoftCryptoProvider::~MicrosoftCryptoProvider() +{ +#if defined(USE_MS_CRYPTOAPI) + if (m_hProvider) + CryptReleaseContext(m_hProvider, 0); +#elif defined(USE_MS_CNGAPI) + if (m_hProvider) + BCryptCloseAlgorithmProvider(m_hProvider, 0); +#endif +} + +#endif // CRYPTOPP_WIN32_AVAILABLE + +NonblockingRng::NonblockingRng() +{ +#ifndef CRYPTOPP_WIN32_AVAILABLE + m_fd = open("/dev/urandom",O_RDONLY); + if (m_fd == -1) + throw OS_RNG_Err("open /dev/urandom"); + + // Do some OSes return -NNN instead of -1? + CRYPTOPP_ASSERT(m_fd >= 0); +#endif +} + +NonblockingRng::~NonblockingRng() +{ +#ifndef CRYPTOPP_WIN32_AVAILABLE + close(m_fd); +#endif +} + +void NonblockingRng::GenerateBlock(byte *output, size_t size) +{ +#ifdef CRYPTOPP_WIN32_AVAILABLE + // Acquiring a provider is expensive. Do it once and retain the reference. +# if defined(CRYPTOPP_CXX11_STATIC_INIT) + static const MicrosoftCryptoProvider hProvider = MicrosoftCryptoProvider(); +# else + const MicrosoftCryptoProvider &hProvider = Singleton().Ref(); +# endif +# if defined(USE_MS_CRYPTOAPI) + DWORD dwSize; + CRYPTOPP_ASSERT(SafeConvert(size, dwSize)); + if (!SafeConvert(size, dwSize)) + { + SetLastError(ERROR_INCORRECT_SIZE); + throw OS_RNG_Err("GenerateBlock size"); + } + BOOL ret = CryptGenRandom(hProvider.GetProviderHandle(), dwSize, output); + CRYPTOPP_ASSERT(ret != FALSE); + if (ret == FALSE) + throw OS_RNG_Err("CryptGenRandom"); +# elif defined(USE_MS_CNGAPI) + ULONG ulSize; + CRYPTOPP_ASSERT(SafeConvert(size, ulSize)); + if (!SafeConvert(size, ulSize)) + { + SetLastError(ERROR_INCORRECT_SIZE); + throw OS_RNG_Err("GenerateBlock size"); + } + NTSTATUS ret = BCryptGenRandom(hProvider.GetProviderHandle(), output, ulSize, 0); + CRYPTOPP_ASSERT(BCRYPT_SUCCESS(ret)); + if (!(BCRYPT_SUCCESS(ret))) + { + // Hack... OS_RNG_Err calls GetLastError() + SetLastError(NtStatusToErrorCode(ret)); + throw OS_RNG_Err("BCryptGenRandom"); + } +# endif +#else + while (size) + { + ssize_t len = read(m_fd, output, size); + if (len < 0) + { + // /dev/urandom reads CAN give EAGAIN errors! (maybe EINTR as well) + if (errno != EINTR && errno != EAGAIN) + throw OS_RNG_Err("read /dev/urandom"); + + continue; + } + + output += len; + size -= len; + } +#endif // CRYPTOPP_WIN32_AVAILABLE +} + +#endif // NONBLOCKING_RNG_AVAILABLE + +// ************************************************************* + +#ifdef BLOCKING_RNG_AVAILABLE + +#ifndef CRYPTOPP_BLOCKING_RNG_FILENAME +#ifdef __OpenBSD__ +#define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/srandom" +#else +#define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/random" +#endif +#endif + +BlockingRng::BlockingRng() +{ + m_fd = open(CRYPTOPP_BLOCKING_RNG_FILENAME,O_RDONLY); + if (m_fd == -1) + throw OS_RNG_Err("open " CRYPTOPP_BLOCKING_RNG_FILENAME); + + // Do some OSes return -NNN instead of -1? + CRYPTOPP_ASSERT(m_fd >= 0); +} + +BlockingRng::~BlockingRng() +{ + close(m_fd); +} + +void BlockingRng::GenerateBlock(byte *output, size_t size) +{ + while (size) + { + // on some systems /dev/random will block until all bytes + // are available, on others it returns immediately + ssize_t len = read(m_fd, output, size); + if (len < 0) + { + // /dev/random reads CAN give EAGAIN errors! (maybe EINTR as well) + if (errno != EINTR && errno != EAGAIN) + throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME); + + continue; + } + + size -= len; + output += len; + if (size) + sleep(1); + } +} + +#endif // BLOCKING_RNG_AVAILABLE + +// ************************************************************* + +void OS_GenerateRandomBlock(bool blocking, byte *output, size_t size) +{ +#ifdef NONBLOCKING_RNG_AVAILABLE + if (blocking) +#endif + { +#ifdef BLOCKING_RNG_AVAILABLE + BlockingRng rng; + rng.GenerateBlock(output, size); +#endif + } + +#ifdef BLOCKING_RNG_AVAILABLE + if (!blocking) +#endif + { +#ifdef NONBLOCKING_RNG_AVAILABLE + NonblockingRng rng; + rng.GenerateBlock(output, size); +#endif + } +} + +void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize) +{ + SecByteBlock seed(seedSize); + OS_GenerateRandomBlock(blocking, seed, seedSize); + IncorporateEntropy(seed, seedSize); +} + +NAMESPACE_END + +#endif // OS_RNG_AVAILABLE + +#endif // CRYPTOPP_IMPORTS diff --git a/external/ours/library/crypto/src/shared/original/osrng.h b/external/ours/library/crypto/src/shared/original/osrng.h new file mode 100755 index 000000000..bd534d585 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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(_MSC_VER) && defined(USE_MS_CRYPTOAPI) +# pragma comment(lib, "advapi32.lib") +#endif + +#if defined(_MSC_VER) && 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 (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/external/ours/library/crypto/src/shared/original/ossig.h b/external/ours/library/crypto/src/shared/original/ossig.h new file mode 100755 index 000000000..ce9789b7d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/padlkrng.cpp b/external/ours/library/crypto/src/shared/original/padlkrng.cpp new file mode 100755 index 000000000..2c776c539 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/padlkrng.cpp @@ -0,0 +1,105 @@ +// via-rng.cpp - written and placed in public domain by Jeffrey Walton and Uri Blumenthal. + +#include "pch.h" +#include "config.h" +#include "cryptlib.h" +#include "secblock.h" +#include "padlkrng.h" +#include "cpu.h" + +// The Padlock Security Engine RNG has a few items to be aware of. You can +// find copies of the Programmer's manual, Cryptography Research Inc audit +// report, and other goodies at http://www.cryptopp.com/wiki/VIA_Padlock. + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4702) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +std::string PadlockRNG::AlgorithmProvider() const +{ + return "Padlock"; +} + +PadlockRNG::PadlockRNG(word32 divisor) + : m_divisor(DivisorHelper(divisor)), m_msr(0) +{ +#if defined(CRYPTOPP_X86_ASM_AVAILABLE) + if (!HasPadlockRNG()) +#endif + throw PadlockRNG_Err("PadlockRNG", "PadlockRNG generator not available"); +} + +void PadlockRNG::GenerateBlock(byte *output, size_t size) +{ + CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(size); +#if defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__GNUC__) + while (size) + { + __asm__ __volatile__ + ( +#if (CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + "mov %1, %%rdi ;\n" + "movl %2, %%edx ;\n" +#else + "mov %1, %%edi ;\n" + "movl %2, %%edx ;\n" +#endif + + // xstore-rng + ".byte 0x0f, 0xa7, 0xc0 ;\n" + "movl %%eax, %0 ;\n" + + : "=g" (m_msr) : "g" (m_buffer.data()), "g" (m_divisor) +#if (CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + : "rax", "rdx", "rdi", "cc" +#else + : "eax", "edx", "edi", "cc" +#endif + ); + + const size_t ret = m_msr & 0x1f; + const size_t rem = STDMIN(ret, STDMIN(size, 16U /*buffer size*/)); + std::memcpy(output, m_buffer, rem); + size -= rem; output += rem; + } +#elif defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(_MSC_VER) && defined(_M_IX86) + while (size) + { + word32 result, divisor = m_divisor; + byte *buffer = reinterpret_cast(m_buffer.data()); + __asm { + mov edi, buffer + mov edx, divisor + _emit 0x0f + _emit 0xa7 + _emit 0xc0 + mov result, eax + } + + const size_t ret = (m_msr = result) & 0x1f; + const size_t rem = STDMIN(ret, STDMIN(size, 16U /*buffer size*/)); + std::memcpy(output, buffer, rem); + size -= rem; output += rem; + } +#else + throw PadlockRNG_Err("GenerateBlock", "PadlockRNG generator not available"); +#endif // CRYPTOPP_X86_ASM_AVAILABLE +} + +void PadlockRNG::DiscardBytes(size_t n) +{ + FixedSizeSecBlock discard; + n = RoundUpToMultipleOf(n, sizeof(word32)); + + size_t count = STDMIN(n, discard.SizeInBytes()); + while (count) + { + GenerateBlock(discard.BytePtr(), count); + n -= count; + count = STDMIN(n, discard.SizeInBytes()); + } +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/padlkrng.h b/external/ours/library/crypto/src/shared/original/padlkrng.h new file mode 100755 index 000000000..fda1d66b2 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/panama.cpp b/external/ours/library/crypto/src/shared/original/panama.cpp new file mode 100755 index 000000000..b6d6a0b63 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/panama.cpp @@ -0,0 +1,533 @@ +// panama.cpp - originally written and placed in the public domain by Wei Dai + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM panama.cpp" to generate MASM code + +#include "pch.h" + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#include "panama.h" +#include "secblock.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4731) +#endif + +template +std::string Panama::AlgorithmProvider() const +{ +#ifndef CRYPTOPP_DISABLE_PANAMA_ASM +# if CRYPTOPP_SSSE3_ASM_AVAILABLE + if(HasSSSE3()) + return "SSSE3"; +# elif CRYPTOPP_SSE2_ASM_AVAILABLE + if(HasSSE2()) + return "SSE2"; +# endif +#endif + return "C++"; +} + +template +void Panama::Reset() +{ + memset(m_state, 0, m_state.SizeInBytes()); +#if CRYPTOPP_SSSE3_ASM_AVAILABLE && !defined(CRYPTOPP_DISABLE_PANAMA_ASM) + m_state[17] = HasSSSE3(); +#endif +} + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void Panama_SSE2_Pull(size_t count, word32 *state, word32 *z, const word32 *y); +} +#elif CRYPTOPP_SSE2_ASM_AVAILABLE && !defined(CRYPTOPP_DISABLE_PANAMA_ASM) + +#ifdef CRYPTOPP_GENERATE_X64_MASM + Panama_SSE2_Pull PROC FRAME + rex_push_reg rdi + alloc_stack(2*16) + save_xmm128 xmm6, 0h + save_xmm128 xmm7, 10h + .endprolog +#else +void CRYPTOPP_NOINLINE Panama_SSE2_Pull(size_t count, word32 *state, word32 *z, const word32 *y) +{ +#if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + asm __volatile__ + ( + INTEL_NOPREFIX + AS_PUSH_IF86( bx) +#else + AS2( mov AS_REG_1, count) + AS2( mov AS_REG_2, state) + AS2( mov AS_REG_3, z) + AS2( mov AS_REG_4, y) +#endif +#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM + +#if CRYPTOPP_BOOL_X86 + #define REG_loopEnd [esp] +#elif defined(CRYPTOPP_GENERATE_X64_MASM) + #define REG_loopEnd rdi +#else + #define REG_loopEnd r8 +#endif + + AS2( shl AS_REG_1, 5) + ASJ( jz, 5, f) + AS2( mov AS_REG_6d, [AS_REG_2+4*17]) + AS2( add AS_REG_1, AS_REG_6) + + #if CRYPTOPP_BOOL_X64 + AS2( mov REG_loopEnd, AS_REG_1) + #else + AS_PUSH_IF86( bp) + AS1( push AS_REG_1) + #endif + + AS2( movdqa xmm0, XMMWORD_PTR [AS_REG_2+0*16]) + AS2( movdqa xmm1, XMMWORD_PTR [AS_REG_2+1*16]) + AS2( movdqa xmm2, XMMWORD_PTR [AS_REG_2+2*16]) + AS2( movdqa xmm3, XMMWORD_PTR [AS_REG_2+3*16]) + AS2( mov eax, dword ptr [AS_REG_2+4*16]) + + ASL(4) + // gamma and pi +#if CRYPTOPP_SSSE3_ASM_AVAILABLE + AS2( test AS_REG_6, 1) + ASJ( jnz, 6, f) +#endif + AS2( movdqa xmm6, xmm2) + AS2( movss xmm6, xmm3) + ASS( pshufd xmm5, xmm6, 0, 3, 2, 1) + AS2( movd xmm6, eax) + AS2( movdqa xmm7, xmm3) + AS2( movss xmm7, xmm6) + ASS( pshufd xmm6, xmm7, 0, 3, 2, 1) +#if CRYPTOPP_SSSE3_ASM_AVAILABLE + ASJ( jmp, 7, f) + ASL(6) + AS2( movdqa xmm5, xmm3) + AS3( palignr xmm5, xmm2, 4) + AS2( movd xmm6, eax) + AS3( palignr xmm6, xmm3, 4) + ASL(7) +#endif + + AS2( movd AS_REG_1d, xmm2) + AS1( not AS_REG_1d) + AS2( movd AS_REG_7d, xmm3) + AS2( or AS_REG_1d, AS_REG_7d) + AS2( xor eax, AS_REG_1d) + +#define SSE2_Index(i) ASM_MOD(((i)*13+16), 17) + +#define pi(i) \ + AS2( movd AS_REG_1d, xmm7)\ + AS2( rol AS_REG_1d, ASM_MOD((ASM_MOD(5*i,17)*(ASM_MOD(5*i,17)+1)/2), 32))\ + AS2( mov [AS_REG_2+SSE2_Index(ASM_MOD(5*(i), 17))*4], AS_REG_1d) + +#define pi4(x, y, z, a, b, c, d) \ + AS2( pcmpeqb xmm7, xmm7)\ + AS2( pxor xmm7, x)\ + AS2( por xmm7, y)\ + AS2( pxor xmm7, z)\ + pi(a)\ + ASS( pshuflw xmm7, xmm7, 1, 0, 3, 2)\ + pi(b)\ + AS2( punpckhqdq xmm7, xmm7)\ + pi(c)\ + ASS( pshuflw xmm7, xmm7, 1, 0, 3, 2)\ + pi(d) + + pi4(xmm1, xmm2, xmm3, 1, 5, 9, 13) + pi4(xmm0, xmm1, xmm2, 2, 6, 10, 14) + pi4(xmm6, xmm0, xmm1, 3, 7, 11, 15) + pi4(xmm5, xmm6, xmm0, 4, 8, 12, 16) + + // output keystream and update buffer here to hide partial memory stalls between pi and theta + AS2( movdqa xmm4, xmm3) + AS2( punpcklqdq xmm3, xmm2) // 1 5 2 6 + AS2( punpckhdq xmm4, xmm2) // 9 10 13 14 + AS2( movdqa xmm2, xmm1) + AS2( punpcklqdq xmm1, xmm0) // 3 7 4 8 + AS2( punpckhdq xmm2, xmm0) // 11 12 15 16 + + // keystream + AS2( test AS_REG_3, AS_REG_3) + ASJ( jz, 0, f) + AS2( movdqa xmm6, xmm4) + AS2( punpcklqdq xmm4, xmm2) + AS2( punpckhqdq xmm6, xmm2) + AS2( test AS_REG_4, 15) + ASJ( jnz, 2, f) + AS2( test AS_REG_4, AS_REG_4) + ASJ( jz, 1, f) + AS2( pxor xmm4, [AS_REG_4]) + AS2( pxor xmm6, [AS_REG_4+16]) + AS2( add AS_REG_4, 32) + ASJ( jmp, 1, f) + ASL(2) + AS2( movdqu xmm0, [AS_REG_4]) + AS2( movdqu xmm2, [AS_REG_4+16]) + AS2( pxor xmm4, xmm0) + AS2( pxor xmm6, xmm2) + AS2( add AS_REG_4, 32) + ASL(1) + AS2( test AS_REG_3, 15) + ASJ( jnz, 3, f) + AS2( movdqa XMMWORD_PTR [AS_REG_3], xmm4) + AS2( movdqa XMMWORD_PTR [AS_REG_3+16], xmm6) + AS2( add AS_REG_3, 32) + ASJ( jmp, 0, f) + ASL(3) + AS2( movdqu XMMWORD_PTR [AS_REG_3], xmm4) + AS2( movdqu XMMWORD_PTR [AS_REG_3+16], xmm6) + AS2( add AS_REG_3, 32) + ASL(0) + + // buffer update + AS2( lea AS_REG_1, [AS_REG_6 + 32]) + AS2( and AS_REG_1, 31*32) + AS2( lea AS_REG_7, [AS_REG_6 + (32-24)*32]) + AS2( and AS_REG_7, 31*32) + + AS2( movdqa xmm0, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+0*8]) + AS2( pxor xmm3, xmm0) + ASS( pshufd xmm0, xmm0, 2, 3, 0, 1) + AS2( movdqa XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+0*8], xmm3) + AS2( pxor xmm0, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+2*8]) + AS2( movdqa XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+2*8], xmm0) + + AS2( movdqa xmm4, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+2*8]) + AS2( pxor xmm1, xmm4) + AS2( movdqa XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+2*8], xmm1) + AS2( pxor xmm4, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+0*8]) + AS2( movdqa XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+0*8], xmm4) + + // theta + AS2( movdqa xmm3, XMMWORD_PTR [AS_REG_2+3*16]) + AS2( movdqa xmm2, XMMWORD_PTR [AS_REG_2+2*16]) + AS2( movdqa xmm1, XMMWORD_PTR [AS_REG_2+1*16]) + AS2( movdqa xmm0, XMMWORD_PTR [AS_REG_2+0*16]) + +#if CRYPTOPP_SSSE3_ASM_AVAILABLE + AS2( test AS_REG_6, 1) + ASJ( jnz, 8, f) +#endif + AS2( movd xmm6, eax) + AS2( movdqa xmm7, xmm3) + AS2( movss xmm7, xmm6) + AS2( movdqa xmm6, xmm2) + AS2( movss xmm6, xmm3) + AS2( movdqa xmm5, xmm1) + AS2( movss xmm5, xmm2) + AS2( movdqa xmm4, xmm0) + AS2( movss xmm4, xmm1) + ASS( pshufd xmm7, xmm7, 0, 3, 2, 1) + ASS( pshufd xmm6, xmm6, 0, 3, 2, 1) + ASS( pshufd xmm5, xmm5, 0, 3, 2, 1) + ASS( pshufd xmm4, xmm4, 0, 3, 2, 1) +#if CRYPTOPP_SSSE3_ASM_AVAILABLE + ASJ( jmp, 9, f) + ASL(8) + AS2( movd xmm7, eax) + AS3( palignr xmm7, xmm3, 4) + AS2( movq xmm6, xmm3) + AS3( palignr xmm6, xmm2, 4) + AS2( movq xmm5, xmm2) + AS3( palignr xmm5, xmm1, 4) + AS2( movq xmm4, xmm1) + AS3( palignr xmm4, xmm0, 4) + ASL(9) +#endif + + AS2( xor eax, 1) + AS2( movd AS_REG_1d, xmm0) + AS2( xor eax, AS_REG_1d) + AS2( movd AS_REG_1d, xmm3) + AS2( xor eax, AS_REG_1d) + + AS2( pxor xmm3, xmm2) + AS2( pxor xmm2, xmm1) + AS2( pxor xmm1, xmm0) + AS2( pxor xmm0, xmm7) + AS2( pxor xmm3, xmm7) + AS2( pxor xmm2, xmm6) + AS2( pxor xmm1, xmm5) + AS2( pxor xmm0, xmm4) + + // sigma + AS2( lea AS_REG_1, [AS_REG_6 + (32-4)*32]) + AS2( and AS_REG_1, 31*32) + AS2( lea AS_REG_7, [AS_REG_6 + 16*32]) + AS2( and AS_REG_7, 31*32) + + AS2( movdqa xmm4, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+0*16]) + AS2( movdqa xmm5, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+0*16]) + AS2( movdqa xmm6, xmm4) + AS2( punpcklqdq xmm4, xmm5) + AS2( punpckhqdq xmm6, xmm5) + AS2( pxor xmm3, xmm4) + AS2( pxor xmm2, xmm6) + + AS2( movdqa xmm4, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+1*16]) + AS2( movdqa xmm5, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+1*16]) + AS2( movdqa xmm6, xmm4) + AS2( punpcklqdq xmm4, xmm5) + AS2( punpckhqdq xmm6, xmm5) + AS2( pxor xmm1, xmm4) + AS2( pxor xmm0, xmm6) + + // loop + AS2( add AS_REG_6, 32) + AS2( cmp AS_REG_6, REG_loopEnd) + ASJ( jne, 4, b) + + // save state + AS2( mov [AS_REG_2+4*16], eax) + AS2( movdqa XMMWORD_PTR [AS_REG_2+3*16], xmm3) + AS2( movdqa XMMWORD_PTR [AS_REG_2+2*16], xmm2) + AS2( movdqa XMMWORD_PTR [AS_REG_2+1*16], xmm1) + AS2( movdqa XMMWORD_PTR [AS_REG_2+0*16], xmm0) + + #if CRYPTOPP_BOOL_X86 + AS2( add esp, 4) + AS_POP_IF86( bp) + #endif + ASL(5) + +#if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + AS_POP_IF86( bx) + ATT_PREFIX + : + #if CRYPTOPP_BOOL_X64 + : "D" (count), "S" (state), "d" (z), "c" (y) + : "%r8", "%r9", "r10", "%eax", "memory", "cc", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" + #else + : "c" (count), "d" (state), "S" (z), "D" (y) + : "%eax", "memory", "cc" + #endif + ); +#endif + +#ifdef CRYPTOPP_GENERATE_X64_MASM + movdqa xmm6, [rsp + 0h] + movdqa xmm7, [rsp + 10h] + add rsp, 2*16 + pop rdi + ret + Panama_SSE2_Pull ENDP +#else +} +#endif +#endif // CRYPTOPP_SSE2_ASM_AVAILABLE + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +template +void Panama::Iterate(size_t count, const word32 *p, byte *output, const byte *input, KeystreamOperation operation) +{ + word32 bstart = m_state[17]; + word32 *const aPtr = m_state; + word32 cPtr[17]; + +#define bPtr ((byte *)(aPtr+20)) + +// reorder the state for SSE2 +// a and c: 4 8 12 16 | 3 7 11 15 | 2 6 10 14 | 1 5 9 13 | 0 | +// xmm0 xmm1 xmm2 xmm3 eax +#define a(i) aPtr[((i)*13+16) % 17] // 13 is inverse of 4 mod 17 +#define c(i) cPtr[((i)*13+16) % 17] +// b: 0 4 | 1 5 | 2 6 | 3 7 +#define b(i, j) b##i[(j)*2%8 + (j)/4] + +// buffer update +#define US(i) {word32 t=b(0,i); b(0,i)=ConditionalByteReverse(B::ToEnum(), p[i])^t; b(25,(i+6)%8)^=t;} +#define UL(i) {word32 t=b(0,i); b(0,i)=a(i+1)^t; b(25,(i+6)%8)^=t;} +// gamma and pi +#define GP(i) c(5*i%17) = rotlFixed(a(i) ^ (a((i+1)%17) | ~a((i+2)%17)), ((5*i%17)*((5*i%17)+1)/2)%32) +// theta and sigma +#define T(i,x) a(i) = c(i) ^ c((i+1)%17) ^ c((i+4)%17) ^ x +#define TS1S(i) T(i+1, ConditionalByteReverse(B::ToEnum(), p[i])) +#define TS1L(i) T(i+1, b(4,i)) +#define TS2(i) T(i+9, b(16,i)) + + while (count--) + { + if (output) + { +#define PANAMA_OUTPUT(x) \ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 0, a(0+9));\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 1, a(1+9));\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 2, a(2+9));\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 3, a(3+9));\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 4, a(4+9));\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 5, a(5+9));\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 6, a(6+9));\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 7, a(7+9)); + + typedef word32 WordType; + CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(PANAMA_OUTPUT, 4*8); + } + + word32 *const b16 = (word32 *)(void *)(bPtr+((bstart+16*32) & 31*32)); + word32 *const b4 = (word32 *)(void *)(bPtr+((bstart+(32-4)*32) & 31*32)); + bstart += 32; + word32 *const b0 = (word32 *)(void *)(bPtr+((bstart) & 31*32)); + word32 *const b25 = (word32 *)(void *)(bPtr+((bstart+(32-25)*32) & 31*32)); + + if (p) + { + US(0); US(1); US(2); US(3); US(4); US(5); US(6); US(7); + } + else + { + UL(0); UL(1); UL(2); UL(3); UL(4); UL(5); UL(6); UL(7); + } + + GP(0); + GP(1); + GP(2); + GP(3); + GP(4); + GP(5); + GP(6); + GP(7); + GP(8); + GP(9); + GP(10); + GP(11); + GP(12); + GP(13); + GP(14); + GP(15); + GP(16); + + T(0,1); + + if (p) + { + TS1S(0); TS1S(1); TS1S(2); TS1S(3); TS1S(4); TS1S(5); TS1S(6); TS1S(7); + p += 8; + } + else + { + TS1L(0); TS1L(1); TS1L(2); TS1L(3); TS1L(4); TS1L(5); TS1L(6); TS1L(7); + } + + TS2(0); TS2(1); TS2(2); TS2(3); TS2(4); TS2(5); TS2(6); TS2(7); + } + m_state[17] = bstart; +} + +NAMESPACE_BEGIN(Weak) +template +size_t PanamaHash::HashMultipleBlocks(const word32 *input, size_t length) +{ + this->Iterate(length / this->BLOCKSIZE, input); + return length % this->BLOCKSIZE; +} + +template +void PanamaHash::TruncatedFinal(byte *hash, size_t size) +{ + this->ThrowIfInvalidTruncatedSize(size); + + this->PadLastBlock(this->BLOCKSIZE, 0x01); + + this->HashEndianCorrectedBlock(this->m_data); + + this->Iterate(32); // pull + + this->Iterate(1, NULLPTR, m_buf.BytePtr(), NULLPTR); + + memcpy(hash, m_buf, size); + + this->Restart(); // reinit for next use +} +NAMESPACE_END + +template +void PanamaCipherPolicy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length==32); + memcpy(m_key, key, 32); +} + +template +void PanamaCipherPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(iv); + CRYPTOPP_UNUSED(length); CRYPTOPP_ASSERT(length==32); + + this->Reset(); + this->Iterate(1, m_key); + if (iv && IsAligned(iv)) + this->Iterate(1, reinterpret_cast(iv)); + else + { + if (iv) + memcpy(m_buf, iv, 32); + else + memset(m_buf, 0, 32); + this->Iterate(1, m_buf); + } + +#if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_PANAMA_ASM) + if (B::ToEnum() == LITTLE_ENDIAN_ORDER && HasSSE2() && !IsP4()) // SSE2 code is slower on P4 Prescott + Panama_SSE2_Pull(32, this->m_state, NULLPTR, NULLPTR); + else +#endif + this->Iterate(32); +} + +template +std::string PanamaCipherPolicy::AlgorithmProvider() const +{ + return Panama::AlgorithmProvider(); +} + +template +unsigned int PanamaCipherPolicy::GetAlignment() const +{ +#if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_PANAMA_ASM) + if (B::ToEnum() == LITTLE_ENDIAN_ORDER && HasSSE2()) + return 16; + else +#endif + return 1; +} + +template +void PanamaCipherPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ +#if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_PANAMA_ASM) + if (B::ToEnum() == LITTLE_ENDIAN_ORDER && HasSSE2()) + Panama_SSE2_Pull(iterationCount, this->m_state, + reinterpret_cast(output), reinterpret_cast(input)); + else +#endif + this->Iterate(iterationCount, NULLPTR, output, input, operation); +} + +template class Panama; +template class Panama; + +template class Weak::PanamaHash; +template class Weak::PanamaHash; + +template class PanamaCipherPolicy; +template class PanamaCipherPolicy; + +NAMESPACE_END + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM diff --git a/external/ours/library/crypto/src/shared/original/panama.h b/external/ours/library/crypto/src/shared/original/panama.h new file mode 100755 index 000000000..b3d50a044 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/pch.cpp b/external/ours/library/crypto/src/shared/original/pch.cpp new file mode 100755 index 000000000..9e6b2e073 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/external/ours/library/crypto/src/shared/original/pch.h b/external/ours/library/crypto/src/shared/original/pch.h new file mode 100755 index 000000000..f158399c5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/pkcspad.cpp b/external/ours/library/crypto/src/shared/original/pkcspad.cpp new file mode 100755 index 000000000..5192c1094 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/pkcspad.cpp @@ -0,0 +1,160 @@ +// pkcspad.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_PKCSPAD_CPP // SunCC workaround: compiler could cause this file to be included twice +#define CRYPTOPP_PKCSPAD_CPP + +#include "pkcspad.h" +#include "emsa2.h" +#include "hashfwd.h" +#include "misc.h" +#include "trap.h" + +NAMESPACE_BEGIN(CryptoPP) + +// Typedef/cast change due to Clang, http://github.com/weidai11/cryptopp/issues/300 +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,0x04,0x10}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x29,0x30,0x0D,0x06,0x09,0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x0C,0x02,0x05,0x00,0x04,0x18}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +// Inclusion based on DLL due to Clang, http://github.com/weidai11/cryptopp/issues/300 +#ifndef CRYPTOPP_IS_DLL +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1c}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x51,0x30,0x0d, 0x06,0x09,0x60,0x86, 0x48,0x01,0x65,0x03, 0x04,0x02,0x03,0x05, 0x00,0x04,0x40}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +// http://github.com/weidai11/cryptopp/issues/517. OIDs and encoded prefixes found at +// http://www.ietf.org/archive/id/draft-jivsov-openpgp-sha3-01.txt +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x31,0x30,0x0d, 0x06,0x09,0x60,0x86, 0x48,0x01,0x65,0x03, 0x04,0x02,0x08,0x05, 0x00,0x04,0x20}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x41,0x30,0x0d, 0x06,0x09,0x60,0x86, 0x48,0x01,0x65,0x03, 0x04,0x02,0x09,0x05, 0x00,0x04,0x30}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x51,0x30,0x0d, 0x06,0x09,0x60,0x86, 0x48,0x01,0x65,0x03, 0x04,0x02,0x0a,0x05, 0x00,0x04,0x40}; +template<> const unsigned int PKCS_DigestDecoration::length = (unsigned int)sizeof(PKCS_DigestDecoration::decoration); +#endif + +size_t PKCS_EncryptionPaddingScheme::MaxUnpaddedLength(size_t paddedLength) const +{ + return SaturatingSubtract(paddedLength/8, 10U); +} + +void PKCS_EncryptionPaddingScheme::Pad(RandomNumberGenerator& rng, const byte *input, size_t inputLen, byte *pkcsBlock, size_t pkcsBlockLen, const NameValuePairs& parameters) const +{ + CRYPTOPP_UNUSED(parameters); + CRYPTOPP_ASSERT (inputLen <= MaxUnpaddedLength(pkcsBlockLen)); // this should be checked by caller + + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + pkcsBlock[0] = 0; + pkcsBlock++; + } + pkcsBlockLen /= 8; + + pkcsBlock[0] = 2; // block type 2 + + // pad with non-zero random bytes + for (unsigned i = 1; i < pkcsBlockLen-inputLen-1; i++) + pkcsBlock[i] = (byte)rng.GenerateWord32(1, 0xff); + + pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator + memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); +} + +DecodingResult PKCS_EncryptionPaddingScheme::Unpad(const byte *pkcsBlock, size_t pkcsBlockLen, byte *output, const NameValuePairs& parameters) const +{ + CRYPTOPP_UNUSED(parameters); + bool invalid = false; + size_t maxOutputLen = MaxUnpaddedLength(pkcsBlockLen); + + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + invalid = (pkcsBlock[0] != 0) || invalid; + pkcsBlock++; + } + pkcsBlockLen /= 8; + + // Require block type 2. + invalid = (pkcsBlock[0] != 2) || invalid; + + // skip past the padding until we find the separator + size_t i=1; + while (i maxOutputLen) || invalid; + + if (invalid) + return DecodingResult(); + + memcpy (output, pkcsBlock+i, outputLen); + return DecodingResult(outputLen); +} + +// ******************************************************** + +#ifndef CRYPTOPP_IMPORTS + +void PKCS1v15_SignatureMessageEncodingMethod::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); + CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); + + size_t pkcsBlockLen = representativeBitLength; + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + representative[0] = 0; + representative++; + } + pkcsBlockLen /= 8; + + representative[0] = 1; // block type 1 + + unsigned int digestSize = hash.DigestSize(); + byte *pPadding = representative + 1; + byte *pDigest = representative + pkcsBlockLen - digestSize; + byte *pHashId = pDigest - hashIdentifier.second; + byte *pSeparator = pHashId - 1; + + // pad with 0xff + memset(pPadding, 0xff, pSeparator-pPadding); + *pSeparator = 0; + memcpy(pHashId, hashIdentifier.first, hashIdentifier.second); + hash.Final(pDigest); +} + +#endif + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/pkcspad.h b/external/ours/library/crypto/src/shared/original/pkcspad.h new file mode 100755 index 000000000..88d9d7358 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/poly1305.cpp b/external/ours/library/crypto/src/shared/original/poly1305.cpp new file mode 100755 index 000000000..354d76c42 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/poly1305.cpp @@ -0,0 +1,403 @@ +// poly1305.cpp - 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/. + +// Copyright (c) 2006-2017, CRYPTOGAMS by +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain copyright notices, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// * Neither the name of the CRYPTOGAMS nor the names of its copyright +// holder and contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. + +#include "pch.h" +#include "cryptlib.h" +#include "poly1305.h" +#include "aes.h" +#include "cpu.h" + +////////////////////////////// Common Poly1305 ////////////////////////////// + +ANONYMOUS_NAMESPACE_BEGIN + +using namespace CryptoPP; + +inline word32 CONSTANT_TIME_CARRY(word32 a, word32 b) +{ + return ((a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1)); +} + +void Poly1305_HashBlocks(word32 h[5], word32 r[4], const byte *input, size_t length, word32 padbit) +{ + word32 r0, r1, r2, r3; + word32 s1, s2, s3; + word32 h0, h1, h2, h3, h4, c; + word64 d0, d1, d2, d3; + + r0 = r[0]; r1 = r[1]; + r2 = r[2]; r3 = r[3]; + + s1 = r1 + (r1 >> 2); + s2 = r2 + (r2 >> 2); + s3 = r3 + (r3 >> 2); + + h0 = h[0]; h1 = h[1]; h2 = h[2]; + h3 = h[3]; h4 = h[4]; + + while (length >= 16) + { + // h += m[i] + h0 = (word32)(d0 = (word64)h0 + GetWord(false, LITTLE_ENDIAN_ORDER, input + 0)); + h1 = (word32)(d1 = (word64)h1 + (d0 >> 32) + GetWord(false, LITTLE_ENDIAN_ORDER, input + 4)); + h2 = (word32)(d2 = (word64)h2 + (d1 >> 32) + GetWord(false, LITTLE_ENDIAN_ORDER, input + 8)); + h3 = (word32)(d3 = (word64)h3 + (d2 >> 32) + GetWord(false, LITTLE_ENDIAN_ORDER, input + 12)); + h4 += (word32)(d3 >> 32) + padbit; + + // h *= r "%" p + d0 = ((word64)h0 * r0) + + ((word64)h1 * s3) + + ((word64)h2 * s2) + + ((word64)h3 * s1); + d1 = ((word64)h0 * r1) + + ((word64)h1 * r0) + + ((word64)h2 * s3) + + ((word64)h3 * s2) + + (h4 * s1); + d2 = ((word64)h0 * r2) + + ((word64)h1 * r1) + + ((word64)h2 * r0) + + ((word64)h3 * s3) + + (h4 * s2); + d3 = ((word64)h0 * r3) + + ((word64)h1 * r2) + + ((word64)h2 * r1) + + ((word64)h3 * r0) + + (h4 * s3); + h4 = (h4 * r0); + + // a) h4:h0 = h4<<128 + d3<<96 + d2<<64 + d1<<32 + d0 + h0 = (word32)d0; + h1 = (word32)(d1 += d0 >> 32); + h2 = (word32)(d2 += d1 >> 32); + h3 = (word32)(d3 += d2 >> 32); + h4 += (word32)(d3 >> 32); + + // b) (h4:h0 += (h4:h0>>130) * 5) %= 2^130 + c = (h4 >> 2) + (h4 & ~3U); + h4 &= 3; + h0 += c; + h1 += (c = CONSTANT_TIME_CARRY(h0,c)); + h2 += (c = CONSTANT_TIME_CARRY(h1,c)); + h3 += (c = CONSTANT_TIME_CARRY(h2,c)); + h4 += CONSTANT_TIME_CARRY(h3,c); + + input += 16; + length -= 16; + } + + h[0] = h0; h[1] = h1; h[2] = h2; + h[3] = h3; h[4] = h4; +} + +void Poly1305_HashFinal(word32 h[5], word32 n[4], byte *mac, size_t size) +{ + word32 h0, h1, h2, h3, h4; + word32 g0, g1, g2, g3, g4; + word32 mask; + word64 t; + + h0 = h[0]; + h1 = h[1]; + h2 = h[2]; + h3 = h[3]; + h4 = h[4]; + + // compare to modulus by computing h + -p + g0 = (word32)(t = (word64)h0 + 5); + g1 = (word32)(t = (word64)h1 + (t >> 32)); + g2 = (word32)(t = (word64)h2 + (t >> 32)); + g3 = (word32)(t = (word64)h3 + (t >> 32)); + g4 = h4 + (word32)(t >> 32); + + // if there was carry into 131st bit, h3:h0 = g3:g0 + mask = 0 - (g4 >> 2); + g0 &= mask; g1 &= mask; + g2 &= mask; g3 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; h1 = (h1 & mask) | g1; + h2 = (h2 & mask) | g2; h3 = (h3 & mask) | g3; + + // mac = (h + nonce) % (2^128) + h0 = (word32)(t = (word64)h0 + n[0]); + h1 = (word32)(t = (word64)h1 + (t >> 32) + n[1]); + h2 = (word32)(t = (word64)h2 + (t >> 32) + n[2]); + h3 = (word32)(t = (word64)h3 + (t >> 32) + n[3]); + + if (size >= 16) + { + PutWord(false, LITTLE_ENDIAN_ORDER, mac + 0, h0); + PutWord(false, LITTLE_ENDIAN_ORDER, mac + 4, h1); + PutWord(false, LITTLE_ENDIAN_ORDER, mac + 8, h2); + PutWord(false, LITTLE_ENDIAN_ORDER, mac + 12, h3); + } + else + { + FixedSizeAlignedSecBlock m; + PutWord(false, LITTLE_ENDIAN_ORDER, m + 0, h0); + PutWord(false, LITTLE_ENDIAN_ORDER, m + 4, h1); + PutWord(false, LITTLE_ENDIAN_ORDER, m + 8, h2); + PutWord(false, LITTLE_ENDIAN_ORDER, m + 12, h3); + std::memcpy(mac, m, size); + } +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +////////////////////////////// Bernstein Poly1305 ////////////////////////////// + +// TODO: No longer needed. Remove at next major version bump +template +void Poly1305_Base::HashBlocks(const byte *input, size_t length, word32 padbit) { + CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length); CRYPTOPP_UNUSED(padbit); + CRYPTOPP_ASSERT(0); +} + +// TODO: No longer needed. Remove at next major version bump +template +void Poly1305_Base::HashFinal(byte *mac, size_t length) { + CRYPTOPP_UNUSED(mac); CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(0); +} + +template +std::string Poly1305_Base::AlgorithmProvider() const +{ + return m_cipher.AlgorithmProvider(); +} + +template +void Poly1305_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + CRYPTOPP_ASSERT(key && length >= 32); + + // key is {k,r} pair. k is AES key, r is the additional key that gets clamped + length = SaturatingSubtract(length, (unsigned)BLOCKSIZE); + m_cipher.SetKey(key, length); + key += length; + + // Rbar is clamped and little endian + m_r[0] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 0) & 0x0fffffff; + m_r[1] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 4) & 0x0ffffffc; + m_r[2] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 8) & 0x0ffffffc; + m_r[3] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 12) & 0x0ffffffc; + + // Mark the nonce as dirty, meaning we need a new one + m_used = true; + + ConstByteArrayParameter t; + if (params.GetValue(Name::IV(), t) && t.begin() && t.size()) + { + CRYPTOPP_ASSERT(t.size() == m_nk.size()); + Resynchronize(t.begin(), (int)t.size()); + } + + Restart(); +} + +template +void Poly1305_Base::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT((input && length) || !length); + if (!length) return; + + size_t rem, num = m_idx; + if (num) + { + rem = BLOCKSIZE - num; + if (length >= rem) + { + // Process + memcpy_s(m_acc + num, BLOCKSIZE - num, input, rem); + Poly1305_HashBlocks(m_h, m_r, m_acc, BLOCKSIZE, 1); + input += rem; length -= rem; + } + else + { + // Accumulate + memcpy_s(m_acc + num, BLOCKSIZE - num, input, length); + m_idx = num + length; + return; + } + } + + rem = length % BLOCKSIZE; + length -= rem; + + if (length >= BLOCKSIZE) { + Poly1305_HashBlocks(m_h, m_r, input, length, 1); + input += length; + } + + if (rem) + memcpy(m_acc, input, rem); + + m_idx = rem; +} + +template +void Poly1305_Base::TruncatedFinal(byte *mac, size_t size) +{ + CRYPTOPP_ASSERT(mac); // Pointer is valid + CRYPTOPP_ASSERT(!m_used); // Nonce is fresh + + ThrowIfInvalidTruncatedSize(size); + + size_t num = m_idx; + if (num) + { + m_acc[num++] = 1; /* pad bit */ + while (num < BLOCKSIZE) + m_acc[num++] = 0; + Poly1305_HashBlocks(m_h, m_r, m_acc, BLOCKSIZE, 0); + } + + Poly1305_HashFinal(m_h, m_n, mac, size); + + // Restart + m_used = true; + Restart(); +} + +template +void Poly1305_Base::Resynchronize(const byte *nonce, int nonceLength) +{ + CRYPTOPP_ASSERT(nonceLength == -1 || nonceLength == (int)BLOCKSIZE); + if (nonceLength == -1) { nonceLength = BLOCKSIZE; } + + // Encrypt the nonce, stash in m_nk + m_cipher.ProcessBlock(nonce, m_nk.begin()); + + m_n[0] = GetWord(false, LITTLE_ENDIAN_ORDER, m_nk + 0); + m_n[1] = GetWord(false, LITTLE_ENDIAN_ORDER, m_nk + 4); + m_n[2] = GetWord(false, LITTLE_ENDIAN_ORDER, m_nk + 8); + m_n[3] = GetWord(false, LITTLE_ENDIAN_ORDER, m_nk + 12); + + // Mark nonce as unused, meaning it is fresh + m_used = false; +} + +template +void Poly1305_Base::GetNextIV(RandomNumberGenerator &rng, byte *iv) +{ + rng.GenerateBlock(iv, BLOCKSIZE); +} + +template +void Poly1305_Base::Restart() +{ + m_h[0] = m_h[1] = m_h[2] = m_h[3] = m_h[4] = 0; + m_idx = 0; +} + +////////////////////////////// IETF Poly1305 ////////////////////////////// + +void Poly1305TLS_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(key && length >= 32); + + // key is {r,s} pair. r is the additional key that gets clamped, s is the nonce. + m_r[0] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 0) & 0x0fffffff; + m_r[1] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 4) & 0x0ffffffc; + m_r[2] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 8) & 0x0ffffffc; + m_r[3] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 12) & 0x0ffffffc; + + key += 16; + m_n[0] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 0); + m_n[1] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 4); + m_n[2] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 8); + m_n[3] = GetWord(false, LITTLE_ENDIAN_ORDER, key + 12); + + Restart(); +} + +void Poly1305TLS_Base::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT((input && length) || !length); + if (!length) return; + + size_t rem, num = m_idx; + if (num) + { + rem = BLOCKSIZE - num; + if (length >= rem) + { + // Process + memcpy_s(m_acc + num, BLOCKSIZE - num, input, rem); + Poly1305_HashBlocks(m_h, m_r, m_acc, BLOCKSIZE, 1); + input += rem; length -= rem; + } + else + { + // Accumulate + memcpy_s(m_acc + num, BLOCKSIZE - num, input, length); + m_idx = num + length; + return; + } + } + + rem = length % BLOCKSIZE; + length -= rem; + + if (length >= BLOCKSIZE) { + Poly1305_HashBlocks(m_h, m_r, input, length, 1); + input += length; + } + + if (rem) + memcpy(m_acc, input, rem); + + m_idx = rem; +} + +void Poly1305TLS_Base::TruncatedFinal(byte *mac, size_t size) +{ + CRYPTOPP_ASSERT(mac); // Pointer is valid + + ThrowIfInvalidTruncatedSize(size); + + size_t num = m_idx; + if (num) + { + m_acc[num++] = 1; /* pad bit */ + while (num < BLOCKSIZE) + m_acc[num++] = 0; + Poly1305_HashBlocks(m_h, m_r, m_acc, BLOCKSIZE, 0); + } + + Poly1305_HashFinal(m_h, m_n, mac, size); + + Restart(); +} + +void Poly1305TLS_Base::Restart() +{ + m_h[0] = m_h[1] = m_h[2] = m_h[3] = m_h[4] = 0; + m_idx = 0; +} + +template class Poly1305_Base; +template class Poly1305; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/poly1305.h b/external/ours/library/crypto/src/shared/original/poly1305.h new file mode 100755 index 000000000..0745d9352 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 classses 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/external/ours/library/crypto/src/shared/original/polynomi.cpp b/external/ours/library/crypto/src/shared/original/polynomi.cpp new file mode 100755 index 000000000..2305f80ae --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/polynomi.cpp @@ -0,0 +1,577 @@ +// polynomi.cpp - originally written and placed in the public domain by Wei Dai + +// Part of the code for polynomial evaluation and interpolation +// originally came from Hal Finney's public domain secsplit.c. + +#include "pch.h" +#include "polynomi.h" +#include "secblock.h" + +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +template +void PolynomialOver::Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, const Ring &ring) +{ + m_coefficients.resize(parameter.m_coefficientCount); + for (unsigned int i=0; i +void PolynomialOver::FromStr(const char *str, const Ring &ring) +{ + std::istringstream in((char *)str); + bool positive = true; + CoefficientType coef; + unsigned int power; + + while (in) + { + std::ws(in); + if (in.peek() == 'x') + coef = ring.MultiplicativeIdentity(); + else + in >> coef; + + std::ws(in); + if (in.peek() == 'x') + { + in.get(); + std::ws(in); + if (in.peek() == '^') + { + in.get(); + in >> power; + } + else + power = 1; + } + else + power = 0; + + if (!positive) + coef = ring.Inverse(coef); + + SetCoefficient(power, coef, ring); + + std::ws(in); + switch (in.get()) + { + case '+': + positive = true; + break; + case '-': + positive = false; + break; + default: + return; // something's wrong with the input string + } + } +} + +template +unsigned int PolynomialOver::CoefficientCount(const Ring &ring) const +{ + unsigned count = m_coefficients.size(); + while (count && ring.Equal(m_coefficients[count-1], ring.Identity())) + count--; + const_cast &>(m_coefficients).resize(count); + return count; +} + +template +typename PolynomialOver::CoefficientType PolynomialOver::GetCoefficient(unsigned int i, const Ring &ring) const +{ + return (i < m_coefficients.size()) ? m_coefficients[i] : ring.Identity(); +} + +template +PolynomialOver& PolynomialOver::operator=(const PolynomialOver& t) +{ + if (this != &t) + { + m_coefficients.resize(t.m_coefficients.size()); + for (unsigned int i=0; i +PolynomialOver& PolynomialOver::Accumulate(const PolynomialOver& t, const Ring &ring) +{ + unsigned int count = t.CoefficientCount(ring); + + if (count > CoefficientCount(ring)) + m_coefficients.resize(count, ring.Identity()); + + for (unsigned int i=0; i +PolynomialOver& PolynomialOver::Reduce(const PolynomialOver& t, const Ring &ring) +{ + unsigned int count = t.CoefficientCount(ring); + + if (count > CoefficientCount(ring)) + m_coefficients.resize(count, ring.Identity()); + + for (unsigned int i=0; i +typename PolynomialOver::CoefficientType PolynomialOver::EvaluateAt(const CoefficientType &x, const Ring &ring) const +{ + int degree = Degree(ring); + + if (degree < 0) + return ring.Identity(); + + CoefficientType result = m_coefficients[degree]; + for (int j=degree-1; j>=0; j--) + { + result = ring.Multiply(result, x); + ring.Accumulate(result, m_coefficients[j]); + } + return result; +} + +template +PolynomialOver& PolynomialOver::ShiftLeft(unsigned int n, const Ring &ring) +{ + unsigned int i = CoefficientCount(ring) + n; + m_coefficients.resize(i, ring.Identity()); + while (i > n) + { + i--; + m_coefficients[i] = m_coefficients[i-n]; + } + while (i) + { + i--; + m_coefficients[i] = ring.Identity(); + } + return *this; +} + +template +PolynomialOver& PolynomialOver::ShiftRight(unsigned int n, const Ring &ring) +{ + unsigned int count = CoefficientCount(ring); + if (count > n) + { + for (unsigned int i=0; i +void PolynomialOver::SetCoefficient(unsigned int i, const CoefficientType &value, const Ring &ring) +{ + if (i >= m_coefficients.size()) + m_coefficients.resize(i+1, ring.Identity()); + m_coefficients[i] = value; +} + +template +void PolynomialOver::Negate(const Ring &ring) +{ + unsigned int count = CoefficientCount(ring); + for (unsigned int i=0; i +void PolynomialOver::swap(PolynomialOver &t) +{ + m_coefficients.swap(t.m_coefficients); +} + +template +bool PolynomialOver::Equals(const PolynomialOver& t, const Ring &ring) const +{ + unsigned int count = CoefficientCount(ring); + + if (count != t.CoefficientCount(ring)) + return false; + + for (unsigned int i=0; i +PolynomialOver PolynomialOver::Plus(const PolynomialOver& t, const Ring &ring) const +{ + unsigned int i; + unsigned int count = CoefficientCount(ring); + unsigned int tCount = t.CoefficientCount(ring); + + if (count > tCount) + { + PolynomialOver result(ring, count); + + for (i=0; i result(ring, tCount); + + for (i=0; i +PolynomialOver PolynomialOver::Minus(const PolynomialOver& t, const Ring &ring) const +{ + unsigned int i; + unsigned int count = CoefficientCount(ring); + unsigned int tCount = t.CoefficientCount(ring); + + if (count > tCount) + { + PolynomialOver result(ring, count); + + for (i=0; i result(ring, tCount); + + for (i=0; i +PolynomialOver PolynomialOver::Inverse(const Ring &ring) const +{ + unsigned int count = CoefficientCount(ring); + PolynomialOver result(ring, count); + + for (unsigned int i=0; i +PolynomialOver PolynomialOver::Times(const PolynomialOver& t, const Ring &ring) const +{ + if (IsZero(ring) || t.IsZero(ring)) + return PolynomialOver(); + + unsigned int count1 = CoefficientCount(ring), count2 = t.CoefficientCount(ring); + PolynomialOver result(ring, count1 + count2 - 1); + + for (unsigned int i=0; i +PolynomialOver PolynomialOver::DividedBy(const PolynomialOver& t, const Ring &ring) const +{ + PolynomialOver remainder, quotient; + Divide(remainder, quotient, *this, t, ring); + return quotient; +} + +template +PolynomialOver PolynomialOver::Modulo(const PolynomialOver& t, const Ring &ring) const +{ + PolynomialOver remainder, quotient; + Divide(remainder, quotient, *this, t, ring); + return remainder; +} + +template +PolynomialOver PolynomialOver::MultiplicativeInverse(const Ring &ring) const +{ + return Degree(ring)==0 ? ring.MultiplicativeInverse(m_coefficients[0]) : ring.Identity(); +} + +template +bool PolynomialOver::IsUnit(const Ring &ring) const +{ + return Degree(ring)==0 && ring.IsUnit(m_coefficients[0]); +} + +template +std::istream& PolynomialOver::Input(std::istream &in, const Ring &ring) +{ + char c; + unsigned int length = 0; + SecBlock str(length + 16); + bool paren = false; + + std::ws(in); + + if (in.peek() == '(') + { + paren = true; + in.get(); + } + + do + { + in.read(&c, 1); + str[length++] = c; + if (length >= str.size()) + str.Grow(length + 16); + } + // if we started with a left paren, then read until we find a right paren, + // otherwise read until the end of the line + while (in && ((paren && c != ')') || (!paren && c != '\n'))); + + str[length-1] = '\0'; + *this = PolynomialOver(str, ring); + + return in; +} + +template +std::ostream& PolynomialOver::Output(std::ostream &out, const Ring &ring) const +{ + unsigned int i = CoefficientCount(ring); + if (i) + { + bool firstTerm = true; + + while (i--) + { + if (m_coefficients[i] != ring.Identity()) + { + if (firstTerm) + { + firstTerm = false; + if (!i || !ring.Equal(m_coefficients[i], ring.MultiplicativeIdentity())) + out << m_coefficients[i]; + } + else + { + CoefficientType inverse = ring.Inverse(m_coefficients[i]); + std::ostringstream pstr, nstr; + + pstr << m_coefficients[i]; + nstr << inverse; + + if (pstr.str().size() <= nstr.str().size()) + { + out << " + "; + if (!i || !ring.Equal(m_coefficients[i], ring.MultiplicativeIdentity())) + out << m_coefficients[i]; + } + else + { + out << " - "; + if (!i || !ring.Equal(inverse, ring.MultiplicativeIdentity())) + out << inverse; + } + } + + switch (i) + { + case 0: + break; + case 1: + out << "x"; + break; + default: + out << "x^" << i; + } + } + } + } + else + { + out << ring.Identity(); + } + return out; +} + +template +void PolynomialOver::Divide(PolynomialOver &r, PolynomialOver &q, const PolynomialOver &a, const PolynomialOver &d, const Ring &ring) +{ + unsigned int i = a.CoefficientCount(ring); + const int dDegree = d.Degree(ring); + + if (dDegree < 0) + throw DivideByZero(); + + r = a; + q.m_coefficients.resize(STDMAX(0, int(i - dDegree))); + + while (i > (unsigned int)dDegree) + { + --i; + q.m_coefficients[i-dDegree] = ring.Divide(r.m_coefficients[i], d.m_coefficients[dDegree]); + for (int j=0; j<=dDegree; j++) + ring.Reduce(r.m_coefficients[i-dDegree+j], ring.Multiply(q.m_coefficients[i-dDegree], d.m_coefficients[j])); + } + + r.CoefficientCount(ring); // resize r.m_coefficients +} + +// ******************************************************** + +// helper function for Interpolate() and InterpolateAt() +template +void RingOfPolynomialsOver::CalculateAlpha(std::vector &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const +{ + for (unsigned int j=0; j=k; --j) + { + m_ring.Reduce(alpha[j], alpha[j-1]); + + CoefficientType d = m_ring.Subtract(x[j], x[j-k]); + if (!m_ring.IsUnit(d)) + throw InterpolationFailed(); + alpha[j] = m_ring.Divide(alpha[j], d); + } + } +} + +template +typename RingOfPolynomialsOver::Element RingOfPolynomialsOver::Interpolate(const CoefficientType x[], const CoefficientType y[], unsigned int n) const +{ + CRYPTOPP_ASSERT(n > 0); + + std::vector alpha(n); + CalculateAlpha(alpha, x, y, n); + + std::vector coefficients((size_t)n, m_ring.Identity()); + coefficients[0] = alpha[n-1]; + + for (int j=n-2; j>=0; --j) + { + for (unsigned int i=n-j-1; i>0; i--) + coefficients[i] = m_ring.Subtract(coefficients[i-1], m_ring.Multiply(coefficients[i], x[j])); + + coefficients[0] = m_ring.Subtract(alpha[j], m_ring.Multiply(coefficients[0], x[j])); + } + + return PolynomialOver(coefficients.begin(), coefficients.end()); +} + +template +typename RingOfPolynomialsOver::CoefficientType RingOfPolynomialsOver::InterpolateAt(const CoefficientType &position, const CoefficientType x[], const CoefficientType y[], unsigned int n) const +{ + CRYPTOPP_ASSERT(n > 0); + + std::vector alpha(n); + CalculateAlpha(alpha, x, y, n); + + CoefficientType result = alpha[n-1]; + for (int j=n-2; j>=0; --j) + { + result = m_ring.Multiply(result, m_ring.Subtract(position, x[j])); + m_ring.Accumulate(result, alpha[j]); + } + return result; +} + +template +void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n) +{ + for (unsigned int i=0; i +void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n) +{ + CRYPTOPP_ASSERT(n > 0); + + std::vector a(2*n-1); + unsigned int i; + + for (i=0; i1; i--) + a[i-1] = ring.Multiply(a[2*i], a[2*i-1]); + + a[0] = ring.MultiplicativeIdentity(); + + for (i=0; i +Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n) +{ + Element result = ring.Identity(); + for (unsigned int i=0; i +const PolynomialOverFixedRing &PolynomialOverFixedRing::Zero() +{ + return Singleton().Ref(); +} + +template +const PolynomialOverFixedRing &PolynomialOverFixedRing::One() +{ + return Singleton().Ref(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/polynomi.h b/external/ours/library/crypto/src/shared/original/polynomi.h new file mode 100755 index 000000000..025ee67bc --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/ppc_power7.cpp b/external/ours/library/crypto/src/shared/original/ppc_power7.cpp new file mode 100755 index 000000000..84a7275a5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ppc_power7.cpp @@ -0,0 +1,93 @@ +// ppc_power7.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// +// This source file uses intrinsics and built-ins to gain access to +// Power7 instructions. A separate source file is needed because +// additional CXXFLAGS are required to enable the appropriate +// instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#if defined(__ALTIVEC__) || defined(_ARCH_PWR7) +# include "ppc_simd.h" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char PPC_POWER7_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +// ************************* Feature Probes ************************* // + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); + + static jmp_buf s_jmpSIGILL; + static void SigIllHandler(int) + { + longjmp(s_jmpSIGILL, 1); + } +} +#endif // CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY + +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) +bool CPU_ProbePower7() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif defined(CRYPTOPP_POWER7_AVAILABLE) +# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile int result = false; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + // POWER7 added unaligned loads and store operations + byte b1[19] = {255, 255, 255, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, b2[17]; + + // See comments in ppc_simd.h for some of these defines. + #if defined(_AIX) && defined(_ARCH_PWR7) && ((__xlC__ & 0xff00) == 0x0c00) + vec_xstw4(vec_xlw4(0, (unsigned int*)(b1+3)), 0, (unsigned int*)(b2+1)); + result = (0 == std::memcmp(b1+3, b2+1, 16)); + #elif defined(_ARCH_PWR7) && defined(__VSX__) + vec_xst(vec_xl(0, (unsigned int*)(b1+3)), 0, (unsigned int*)(b2+1)); + result = (0 == std::memcmp(b1+3, b2+1, 16)); + #else + result = false; + #endif + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // _ARCH_PWR7 +} + +#endif // PPC32 or PPC64 + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/ppc_power8.cpp b/external/ours/library/crypto/src/shared/original/ppc_power8.cpp new file mode 100755 index 000000000..7e287ee58 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ppc_power8.cpp @@ -0,0 +1,246 @@ +// ppc_power8.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// +// This source file uses intrinsics and built-ins to gain access to +// Power8 instructions. A separate source file is needed because +// additional CXXFLAGS are required to enable the appropriate +// instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#if defined(_ARCH_PWR8) || defined(__CRYPTO__) +# include "ppc_simd.h" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char PPC_POWER8_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +// ************************* Feature Probes ************************* // + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); + + static jmp_buf s_jmpSIGILL; + static void SigIllHandler(int) + { + longjmp(s_jmpSIGILL, 1); + } +} +#endif // CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY + +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) + +bool CPU_ProbePower8() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (_ARCH_PWR8) && defined(CRYPTOPP_POWER8_AVAILABLE) +# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile int result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + // POWER8 added 64-bit SIMD operations + const word64 x = W64LIT(0xffffffffffffffff); + word64 w1[2] = {x, x}, w2[2] = {4, 6}, w3[2]; + + // Specifically call the VSX loads and stores with 64-bit types + #if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__)) || defined(__clang__) + const uint64x2_p v1 = vec_xl(0, (unsigned long long*)w1); + const uint64x2_p v2 = vec_xl(0, (unsigned long long*)w2); + const uint64x2_p v3 = vec_add(v1, v2); // 64-bit add + vec_xst(v3, 0, (unsigned long long*)w3); + #else + const uint64x2_p v1 = (uint64x2_p)vec_vsx_ld(0, (const byte*)w1); + const uint64x2_p v2 = (uint64x2_p)vec_vsx_ld(0, (const byte*)w2); + const uint64x2_p v3 = vec_add(v1, v2); // 64-bit add + vec_vsx_st((uint8x16_p)v3, 0, (byte*)w3); + #endif + + // Relies on integer wrap + result = (w3[0] == 3 && w3[1] == 5); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // _ARCH_PWR8 +} + +bool CPU_ProbeAES() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (__CRYPTO__) && defined(CRYPTOPP_POWER8_AES_AVAILABLE) +# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile int result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + byte key[16] = {0xA0, 0xFA, 0xFE, 0x17, 0x88, 0x54, 0x2c, 0xb1, + 0x23, 0xa3, 0x39, 0x39, 0x2a, 0x6c, 0x76, 0x05}; + byte state[16] = {0x19, 0x3d, 0xe3, 0xb3, 0xa0, 0xf4, 0xe2, 0x2b, + 0x9a, 0xc6, 0x8d, 0x2a, 0xe9, 0xf8, 0x48, 0x08}; + byte r[16] = {255}, z[16] = {}; + + uint8x16_p k = (uint8x16_p)VecLoad(0, key); + uint8x16_p s = (uint8x16_p)VecLoad(0, state); + s = VecEncrypt(s, k); + s = VecEncryptLast(s, k); + s = VecDecrypt(s, k); + s = VecDecryptLast(s, k); + VecStore(s, r); + + result = (0 != std::memcmp(r, z, 16)); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // __CRYPTO__ +} + +bool CPU_ProbeSHA256() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (__CRYPTO__) && defined(CRYPTOPP_POWER8_SHA_AVAILABLE) +# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile int result = false; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + byte r[16], z[16] = {0}; + uint8x16_p x = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + x = VecSHA256<0,0>(x); + x = VecSHA256<0,0xf>(x); + x = VecSHA256<1,0>(x); + x = VecSHA256<1,0xf>(x); + VecStore(x, r); + + result = (0 == std::memcmp(r, z, 16)); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_ALTIVEC_AVAILABLE +} + +bool CPU_ProbeSHA512() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (__CRYPTO__) && defined(CRYPTOPP_POWER8_SHA_AVAILABLE) +# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile int result = false; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + byte r[16], z[16] = {0}; + uint8x16_p x = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + x = VecSHA512<0,0>(x); + x = VecSHA512<0,0xf>(x); + x = VecSHA512<1,0>(x); + x = VecSHA512<1,0xf>(x); + VecStore(x, r); + + result = (0 == std::memcmp(r, z, 16)); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_POWER8_AVAILABLE +} + +#endif // PPC32 or PPC64 + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/ppc_power9.cpp b/external/ours/library/crypto/src/shared/original/ppc_power9.cpp new file mode 100755 index 000000000..b7288f7c4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ppc_power9.cpp @@ -0,0 +1,136 @@ +// ppc_power9.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// +// This source file uses intrinsics and built-ins to gain access to +// Power9 instructions. A separate source file is needed because +// additional CXXFLAGS are required to enable the appropriate +// instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#if defined(_ARCH_PWR9) +# include "ppc_simd.h" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char PPC_POWER9_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +// ************************* Feature Probes ************************* // + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); + + static jmp_buf s_jmpSIGILL; + static void SigIllHandler(int) + { + longjmp(s_jmpSIGILL, 1); + } +} +#endif // CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY + +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) + +bool CPU_ProbePower9() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif defined(CRYPTOPP_POWER9_AVAILABLE) +# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721954 + volatile int result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + // This is "darn r3, 0" from POWER9. We cannot use __builtin_darn + // and friends because Clang and IBM XL C/C++ does not offer them. +#if CRYPTOPP_BIG_ENDIAN + __asm__ __volatile__ (".byte 0x7c, 0x60, 0x05, 0xe6 \n" : : : "r3"); +#else + __asm__ __volatile__ (".byte 0xe6, 0x05, 0x60, 0x7c \n" : : : "r3"); +#endif + result = true; + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // _ARCH_PWR9 +} + +// The DARN probe is not guarded with a preprocessor macro at the moment. We +// don't use CRYPTOPP_POWER9_AVAILABLE because old compilers, like GCC 4.8 on +// CentOS 7, will report NO even though we can produce the random numbers. +// Other Power9 implementations which use builtins will use the preprocessor +// macro guard. This strategy also gets into a situation where Power9 is not +// available but DARN is. +bool CPU_ProbeDARN() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#else +# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721954 + volatile int result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + // This is "darn r3, 0" from POWER9. We cannot use __builtin_darn + // and friends because Clang and IBM XL C/C++ does not offer them. +#if CRYPTOPP_BIG_ENDIAN + __asm__ __volatile__ (".byte 0x7c, 0x60, 0x05, 0xe6 \n" : : : "r3"); +#else + __asm__ __volatile__ (".byte 0xe6, 0x05, 0x60, 0x7c \n" : : : "r3"); +#endif + result = true; + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#endif // DARN +} + +#endif // PPC32 or PPC64 + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/ppc_simd.cpp b/external/ours/library/crypto/src/shared/original/ppc_simd.cpp new file mode 100755 index 000000000..081d05150 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ppc_simd.cpp @@ -0,0 +1,96 @@ +// ppc_simd.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// +// This source file uses intrinsics to gain access to AltiVec, +// Power8 and in-core crypto instructions. A separate source file +// is needed because additional CXXFLAGS are required to enable the +// appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" +#include "stdcpp.h" + +#if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +# include "ppc_simd.h" +#endif + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#ifndef EXCEPTION_EXECUTE_HANDLER +# define EXCEPTION_EXECUTE_HANDLER 1 +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char PPC_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); + + static jmp_buf s_jmpSIGILL; + static void SigIllHandler(int) + { + longjmp(s_jmpSIGILL, 1); + } +} +#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY + +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) +bool CPU_ProbeAltivec() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (_ARCH_PWR3) && (CRYPTOPP_ALTIVEC_AVAILABLE) +# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile int result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + CRYPTOPP_ALIGN_DATA(16) + const byte b1[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + CRYPTOPP_ALIGN_DATA(16) + const byte b2[16] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; + CRYPTOPP_ALIGN_DATA(16) byte b3[16]; + + // Specifically call the Altivec loads and stores + const uint8x16_p v1 = (uint8x16_p)vec_ld(0, (byte*)b1); + const uint8x16_p v2 = (uint8x16_p)vec_ld(0, (byte*)b2); + const uint8x16_p v3 = (uint8x16_p)VecXor(v1, v2); + vec_st(v3, 0, b3); + + result = (0 == std::memcmp(b2, b3, 16)); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_ALTIVEC_AVAILABLE +} + +# endif // CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64 + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/ppc_simd.h b/external/ours/library/crypto/src/shared/original/ppc_simd.h new file mode 100755 index 000000000..1ed0b5601 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 intructions. +/// \details The abstractions are necesssary 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 adresses. +/// \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 adresses. +/// \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 adresses. +/// \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 adresses. +/// \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/external/ours/library/crypto/src/shared/original/pssr.cpp b/external/ours/library/crypto/src/shared/original/pssr.cpp new file mode 100755 index 000000000..753797ba4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/pssr.cpp @@ -0,0 +1,163 @@ +// pssr.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "pssr.h" +#include "emsa2.h" +#include "ripemd.h" +#include "whrlpool.h" +#include "misc.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +template<> const byte EMSA2HashId::id = 0x31; +template<> const byte EMSA2HashId::id = 0x32; +template<> const byte EMSA2HashId::id = 0x37; + +#ifndef CRYPTOPP_IMPORTS + +size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const +{ + size_t saltLen = SaltLen(digestLength); + size_t minPadLen = MinPadLen(digestLength); + return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength); +} + +size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const +{ + if (AllowRecovery()) + return SaturatingSubtract(representativeBitLength, MinRepresentativeBitLength(hashIdentifierLength, digestLength)) / 8; + return 0; +} + +bool PSSR_MEM_Base::IsProbabilistic() const +{ + return SaltLen(1) > 0; +} + +bool PSSR_MEM_Base::AllowNonrecoverablePart() const +{ + return true; +} + +bool PSSR_MEM_Base::RecoverablePartFirst() const +{ + return false; +} + +void PSSR_MEM_Base::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); + CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); + + const size_t u = hashIdentifier.second + 1; + const size_t representativeByteLength = BitsToBytes(representativeBitLength); + const size_t digestSize = hash.DigestSize(); + const size_t saltSize = SaltLen(digestSize); + byte *const h = representative + representativeByteLength - u - digestSize; + + SecByteBlock digest(digestSize), salt(saltSize); + hash.Final(digest); + rng.GenerateBlock(salt, saltSize); + + // compute H = hash of M' + byte c[8]; + PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); + PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); + hash.Update(c, 8); + hash.Update(recoverableMessage, recoverableMessageLength); + hash.Update(digest, digestSize); + hash.Update(salt, saltSize); + hash.Final(h); + + // compute representative + GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false); + byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1; + xorStart[0] ^= 1; + if (recoverableMessage && recoverableMessageLength) + xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength); + xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size()); + if (hashIdentifier.first && hashIdentifier.second) + { + memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second); + representative[representativeByteLength - 1] = 0xcc; + } + else + { + representative[representativeByteLength - 1] = 0xbc; + } + if (representativeBitLength % 8 != 0) + representative[0] = (byte)Crop(representative[0], representativeBitLength % 8); +} + +DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength, + byte *recoverableMessage) const +{ + CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(messageEmpty), CRYPTOPP_UNUSED(hashIdentifier); + CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); + + const size_t u = hashIdentifier.second + 1; + const size_t representativeByteLength = BitsToBytes(representativeBitLength); + const size_t digestSize = hash.DigestSize(); + const size_t saltSize = SaltLen(digestSize); + const byte *const h = representative + representativeByteLength - u - digestSize; + + SecByteBlock digest(digestSize); + hash.Final(digest); + + DecodingResult result(0); + bool &valid = result.isValidCoding; + size_t &recoverableMessageLength = result.messageLength; + + valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid; + + if (hashIdentifier.first && hashIdentifier.second) + valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid; + + GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize); + if (representativeBitLength % 8 != 0) + representative[0] = (byte)Crop(representative[0], representativeBitLength % 8); + + // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt + byte *salt = representative + representativeByteLength - u - digestSize - saltSize; + byte *M = FindIfNot(representative, salt-1, byte(0)); + recoverableMessageLength = salt-M-1; + if (*M == 0x01 && + (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize) && + recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize)) + { + if (recoverableMessage) + memcpy(recoverableMessage, M+1, recoverableMessageLength); + } + else + { + recoverableMessageLength = 0; + valid = false; + } + + // verify H = hash of M' + byte c[8]; + PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); + PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); + hash.Update(c, 8); + hash.Update(recoverableMessage, recoverableMessageLength); + hash.Update(digest, digestSize); + hash.Update(salt, saltSize); + valid = hash.Verify(h) && valid; + + if (!AllowRecovery() && valid && recoverableMessageLength != 0) + {throw NotImplemented("PSSR_MEM: message recovery disabled");} + + return result; +} + +#endif + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/pssr.h b/external/ours/library/crypto/src/shared/original/pssr.h new file mode 100755 index 000000000..e192aaf3a --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/pubkey.cpp b/external/ours/library/crypto/src/shared/original/pubkey.cpp new file mode 100755 index 000000000..3a6009063 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/pubkey.cpp @@ -0,0 +1,170 @@ +// pubkey.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "pubkey.h" +#include "integer.h" +#include "filters.h" + +NAMESPACE_BEGIN(CryptoPP) + +void 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) +{ + ArraySink *sink; + HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength)); + word32 counter = counterStart; + while (sink->AvailableSize() > 0) + { + filter.Put(input, inputLength); + filter.PutWord32(counter++); + filter.Put(derivationParams, derivationParamsLength); + filter.MessageEnd(); + } +} + +bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const +{ + SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength)); + ComputeMessageRepresentative(NullRNG(), NULLPTR, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength); + return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size()); +} + +bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const +{ + SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize())); + DecodingResult result = RecoverMessageFromRepresentative( + hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage); + return result.isValidCoding && result.messageLength == 0; +} + +void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const +{ + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize()); + + if (maxRecoverableLength == 0) + {throw NotImplemented("TF_SignerBase: this algorithm does not support message recovery or the key is too short");} + if (recoverableMessageLength > maxRecoverableLength) + throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm"); + + ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength); + encoding.ProcessRecoverableMessage( + ma.AccessHash(), + recoverableMessage, recoverableMessageLength, + NULLPTR, 0, ma.m_semisignature); +} + +size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const +{ + CRYPTOPP_UNUSED(restart); + + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + SecByteBlock representative(MessageRepresentativeLength()); + encoding.ComputeMessageRepresentative(rng, + ma.m_recoverableMessage, ma.m_recoverableMessage.size(), + ma.AccessHash(), id, ma.m_empty, + representative, MessageRepresentativeBitLength()); + ma.m_empty = true; + + Integer r(representative, representative.size()); + size_t signatureLength = SignatureLength(); + GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength); + return signatureLength; +} + +void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const +{ + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + ma.m_representative.New(MessageRepresentativeLength()); + Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength)); + if (x.BitCount() > MessageRepresentativeBitLength()) + x = Integer::Zero(); // don't return false here to prevent timing attack + x.Encode(ma.m_representative, ma.m_representative.size()); +} + +bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const +{ + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + bool result = encoding.VerifyMessageRepresentative( + ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength()); + ma.m_empty = true; + return result; +} + +DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const +{ + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + DecodingResult result = encoding.RecoverMessageFromRepresentative( + ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage); + ma.m_empty = true; + return result; +} + +DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const +{ + if (ciphertextLength != FixedCiphertextLength()) + throw InvalidArgument(AlgorithmName() + ": ciphertext length of " + IntToString(ciphertextLength) + " doesn't match the required length of " + IntToString(FixedCiphertextLength()) + " for this key"); + + SecByteBlock paddedBlock(PaddedBlockByteLength()); + Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, ciphertextLength)); + if (x.ByteCount() > paddedBlock.size()) + x = Integer::Zero(); // don't return false here to prevent timing attack + x.Encode(paddedBlock, paddedBlock.size()); + return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters); +} + +void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const +{ + if (plaintextLength > FixedMaxPlaintextLength()) + { + if (FixedMaxPlaintextLength() < 1) + throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages"); + else + throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key"); + } + + SecByteBlock paddedBlock(PaddedBlockByteLength()); + GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters); + GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength()); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/pubkey.h b/external/ours/library/crypto/src/shared/original/pubkey.h new file mode 100755 index 000000000..efa607b68 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 hierachies 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 message after the trapdoor function is applied + /// \return the maximum size of a message 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 message after the trapdoor function is applied bound to a public key + /// \return the maximum size of a message 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() \a + /// 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() \a + /// 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 elemenet + /// \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/external/ours/library/crypto/src/shared/original/pwdbased.h b/external/ours/library/crypto/src/shared/original/pwdbased.h new file mode 100755 index 000000000..f1e2c79f9 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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; inext; current; current = current->next) - { - m_tail->next = new ByteQueueNode(*current); - m_tail = m_tail->next; - } - - m_tail->next = nullptr; - - Put(copy.m_lazyString, copy.m_lazyLength); -} - -ByteQueue::~ByteQueue() -{ - Destroy(); -} - -void ByteQueue::Destroy() -{ - ByteQueueNode *next; - - for (ByteQueueNode *current = m_head; current; current = next) - { - next = current->next; - delete current; - } -} - -unsigned long ByteQueue::CurrentSize() const -{ - unsigned long size = 0; - - for (ByteQueueNode *current = m_head; current; current = current->next) - size += current->CurrentSize(); - - return size + m_lazyLength; -} - -bool ByteQueue::IsEmpty() const -{ - return m_head == m_tail && m_head->CurrentSize() == 0 && m_lazyLength == 0; -} - -void ByteQueue::Clear() -{ - Destroy(); - m_head = m_tail = new ByteQueueNode(m_nodeSize); - m_lazyLength = 0; -} - -void ByteQueue::Put(byte inByte) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - - if (!m_tail->Put(inByte)) - { - m_tail->next = new ByteQueueNode(m_nodeSize); - m_tail = m_tail->next; - m_tail->Put(inByte); - } -} - -void ByteQueue::Put(const byte *inString, unsigned int length) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - - unsigned int len; - while ((len = m_tail->Put(inString, length)) < length) - { - m_tail->next = new ByteQueueNode(m_nodeSize); - m_tail = m_tail->next; - inString += len; - length -= len; - } -} - -void ByteQueue::CleanupUsedNodes() -{ - while (m_head != m_tail && m_head->UsedUp()) - { - ByteQueueNode *temp = m_head; - m_head = m_head->next; - delete temp; - } - - if (m_head->CurrentSize() == 0) - m_head->Clear(); -} - -void ByteQueue::LazyPut(const byte *inString, unsigned int size) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - m_lazyString = inString; - m_lazyLength = size; -} - -void ByteQueue::FinalizeLazyPut() -{ - unsigned int len = m_lazyLength; - m_lazyLength = 0; - Put(m_lazyString, len); -} - -unsigned int ByteQueue::Get(byte &outByte) -{ - if (m_head->Get(outByte)) - { - if (m_head->UsedUp()) - CleanupUsedNodes(); - return 1; - } - else if (m_lazyLength > 0) - { - outByte = *m_lazyString++; - m_lazyLength--; - return 1; - } - else - return 0; -} - -unsigned int ByteQueue::Get(byte *outString, unsigned int getMax) -{ - ArraySink sink(outString, getMax); - return TransferTo(sink, getMax); -} - -unsigned int ByteQueue::Peek(byte &outByte) const -{ - if (m_head->Peek(outByte)) - return 1; - else if (m_lazyLength > 0) - { - outByte = *m_lazyString; - return 1; - } - else - return 0; -} - -unsigned int ByteQueue::Peek(byte *outString, unsigned int peekMax) const -{ - ArraySink sink(outString, peekMax); - return CopyTo(sink, peekMax); -} - -unsigned long ByteQueue::Skip(unsigned long skipMax) -{ - return TransferTo(g_bitBucket, skipMax); -} - -unsigned long ByteQueue::TransferTo(BufferedTransformation &target, unsigned long transferMax) -{ - unsigned long bytesLeft = transferMax; - for (ByteQueueNode *current = m_head; bytesLeft && current; current = current->next) - bytesLeft -= current->TransferTo(target, bytesLeft); - CleanupUsedNodes(); - - unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength); - if (len) - { - target.Put(m_lazyString, len); - m_lazyString += len; - m_lazyLength -= len; - bytesLeft -= len; - } - return transferMax - bytesLeft; -} - -unsigned long ByteQueue::CopyTo(BufferedTransformation &target, unsigned long copyMax) const -{ - unsigned long bytesLeft = copyMax; - for (ByteQueueNode *current = m_head; bytesLeft && current; current = current->next) - bytesLeft -= current->CopyTo(target, bytesLeft); - if (bytesLeft && m_lazyLength) - { - unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength); - target.Put(m_lazyString, len); - bytesLeft -= len; - } - return copyMax - bytesLeft; -} - -void ByteQueue::Unget(byte inByte) -{ - Unget(&inByte, 1); -} - -void ByteQueue::Unget(const byte *inString, unsigned int length) -{ - ByteQueueNode *newHead = new ByteQueueNode(length); - newHead->next = m_head; - m_head = newHead; - m_head->Put(inString, length); -} -/* -byte * ByteQueue::Spy(unsigned int &contiguousSize) -{ - contiguousSize = m_head->m_tail - m_head->m_head; - return m_head->buf + m_head->m_head; -} -*/ -const byte * ByteQueue::Spy(unsigned int &contiguousSize) const -{ - contiguousSize = m_head->m_tail - m_head->m_head; - if (contiguousSize == 0 && m_lazyLength > 0) - { - contiguousSize = m_lazyLength; - return m_lazyString; - } - else - return m_head->buf + m_head->m_head; -} - -byte * ByteQueue::MakeNewSpace(unsigned int &contiguousSize) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - - if (m_tail->m_tail == m_tail->MaxSize()) - { - m_tail->next = new ByteQueueNode(m_nodeSize); - m_tail = m_tail->next; - } - - contiguousSize = m_tail->MaxSize() - m_tail->m_tail; - return m_tail->buf + m_tail->m_tail; -} - -void ByteQueue::OccupyNewSpace(unsigned int size) -{ - m_tail->m_tail += size; - assert(m_tail->m_tail <= m_tail->MaxSize()); -} - -ByteQueue & ByteQueue::operator=(const ByteQueue &rhs) -{ - Destroy(); - CopyFrom(rhs); - return *this; -} - -bool ByteQueue::operator==(const ByteQueue &rhs) const -{ - const unsigned long currentSize = CurrentSize(); - - if (currentSize != rhs.CurrentSize()) - return false; - - Walker walker1(*this), walker2(rhs); - byte b1, b2; - - while (walker1.Get(b1) && walker2.Get(b2)) - if (b1 != b2) - return false; - - return true; -} - -byte ByteQueue::operator[](unsigned long i) const -{ - for (ByteQueueNode *current = m_head; current; current = current->next) - { - if (i < current->CurrentSize()) - return (*current)[i]; - - i -= current->CurrentSize(); - } - - assert(i < m_lazyLength); - return m_lazyString[i]; -} - -void ByteQueue::swap(ByteQueue &rhs) -{ - std::swap(m_nodeSize, rhs.m_nodeSize); - std::swap(m_head, rhs.m_head); - std::swap(m_tail, rhs.m_tail); - std::swap(m_lazyString, rhs.m_lazyString); - std::swap(m_lazyLength, rhs.m_lazyLength); -} - -// ******************************************************** - -unsigned int ByteQueue::Walker::Get(byte &outByte) -{ - ArraySink sink(&outByte, 1); - return TransferTo(sink, 1); -} - -unsigned int ByteQueue::Walker::Get(byte *outString, unsigned int getMax) -{ - ArraySink sink(outString, getMax); - return TransferTo(sink, getMax); -} - -unsigned int ByteQueue::Walker::Peek(byte &outByte) const -{ - ArraySink sink(&outByte, 1); - return CopyTo(sink, 1); -} - -unsigned int ByteQueue::Walker::Peek(byte *outString, unsigned int peekMax) const -{ - ArraySink sink(outString, peekMax); - return CopyTo(sink, peekMax); -} - -unsigned long ByteQueue::Walker::TransferTo(BufferedTransformation &target, unsigned long transferMax) -{ - unsigned long bytesLeft = transferMax; - while (m_node) - { - unsigned int len = STDMIN(bytesLeft, (unsigned long)m_node->CurrentSize() - m_offset); - target.Put(m_node->buf + m_node->m_head + m_offset, len); - m_position += len; - bytesLeft -= len; - - if (!bytesLeft) - { - m_offset += len; - break; - } - - m_node = m_node->next; - m_offset = 0; - } - - unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength); - if (len) - { - target.Put(m_lazyString, len); - m_lazyString += len; - m_lazyLength -= len; - bytesLeft -= len; - } - return transferMax - bytesLeft; -} - -unsigned long ByteQueue::Walker::Skip(unsigned long skipMax) -{ - return TransferTo(g_bitBucket, skipMax); -} - -unsigned long ByteQueue::Walker::CopyTo(BufferedTransformation &target, unsigned long copyMax) const -{ - return Walker(*this).TransferTo(target, copyMax); -} - -NAMESPACE_END \ No newline at end of file +// queue.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "queue.h" +#include "filters.h" +#include "misc.h" +#include "trap.h" + +NAMESPACE_BEGIN(CryptoPP) + +static const unsigned int s_maxAutoNodeSize = 16*1024u; + +// this class for use by ByteQueue only +class ByteQueueNode +{ +public: + ByteQueueNode(size_t maxSize) + : m_buf(maxSize) + { + // See GH #962 for the reason for this assert. + CRYPTOPP_ASSERT(maxSize != SIZE_MAX); + + m_head = m_tail = 0; + m_next = NULLPTR; + } + + inline size_t MaxSize() const {return m_buf.size();} + + inline size_t CurrentSize() const + { + return m_tail-m_head; + } + + inline bool UsedUp() const + { + return (m_head==MaxSize()); + } + + inline void Clear() + { + m_head = m_tail = 0; + } + + inline size_t Put(const byte *begin, size_t length) + { + // Avoid passing NULL to memcpy + if (!begin || !length) return length; + size_t l = STDMIN(length, MaxSize()-m_tail); + if (m_buf+m_tail != begin) + memcpy(m_buf+m_tail, begin, l); + m_tail += l; + return l; + } + + inline size_t Peek(byte &outByte) const + { + if (m_tail==m_head) + return 0; + + outByte=m_buf[m_head]; + return 1; + } + + inline size_t Peek(byte *target, size_t copyMax) const + { + size_t len = STDMIN(copyMax, m_tail-m_head); + memcpy(target, m_buf+m_head, len); + return len; + } + + inline size_t CopyTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const + { + size_t len = m_tail-m_head; + target.ChannelPut(channel, m_buf+m_head, len); + return len; + } + + inline size_t CopyTo(BufferedTransformation &target, size_t copyMax, const std::string &channel=DEFAULT_CHANNEL) const + { + size_t len = STDMIN(copyMax, m_tail-m_head); + target.ChannelPut(channel, m_buf+m_head, len); + return len; + } + + inline size_t Get(byte &outByte) + { + size_t len = Peek(outByte); + m_head += len; + return len; + } + + inline size_t Get(byte *outString, size_t getMax) + { + size_t len = Peek(outString, getMax); + m_head += len; + return len; + } + + inline size_t TransferTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) + { + size_t len = m_tail-m_head; + target.ChannelPutModifiable(channel, m_buf+m_head, len); + m_head = m_tail; + return len; + } + + inline size_t TransferTo(BufferedTransformation &target, lword transferMax, const std::string &channel=DEFAULT_CHANNEL) + { + size_t len = UnsignedMin(m_tail-m_head, transferMax); + target.ChannelPutModifiable(channel, m_buf+m_head, len); + m_head += len; + return len; + } + + inline size_t Skip(size_t skipMax) + { + size_t len = STDMIN(skipMax, m_tail-m_head); + m_head += len; + return len; + } + + inline byte operator[](size_t i) const + { + return m_buf[m_head+i]; + } + + ByteQueueNode* m_next; + + SecByteBlock m_buf; + size_t m_head, m_tail; +}; + +// ******************************************************** + +ByteQueue::ByteQueue(size_t nodeSize) + : Bufferless() + , m_head(NULLPTR), m_tail(NULLPTR), m_lazyString(NULLPTR), m_lazyLength(0) + , m_nodeSize(nodeSize), m_lazyStringModifiable(false), m_autoNodeSize(!nodeSize) +{ + // See GH #962 for the reason for this assert. + CRYPTOPP_ASSERT(nodeSize != SIZE_MAX); + + SetNodeSize(nodeSize); + m_head = m_tail = new ByteQueueNode(m_nodeSize); +} + +void ByteQueue::SetNodeSize(size_t nodeSize) +{ + m_autoNodeSize = !nodeSize; + m_nodeSize = m_autoNodeSize ? 256 : nodeSize; +} + +ByteQueue::ByteQueue(const ByteQueue ©) + : Bufferless(copy), m_lazyString(NULLPTR), m_lazyLength(0) +{ + CopyFrom(copy); +} + +void ByteQueue::CopyFrom(const ByteQueue ©) +{ + m_lazyLength = 0; + m_autoNodeSize = copy.m_autoNodeSize; + m_nodeSize = copy.m_nodeSize; + m_head = m_tail = new ByteQueueNode(*copy.m_head); + + for (ByteQueueNode *current=copy.m_head->m_next; current; current=current->m_next) + { + m_tail->m_next = new ByteQueueNode(*current); + m_tail = m_tail->m_next; + } + + m_tail->m_next = NULLPTR; + + Put(copy.m_lazyString, copy.m_lazyLength); +} + +ByteQueue::~ByteQueue() +{ + Destroy(); +} + +void ByteQueue::Destroy() +{ + for (ByteQueueNode *next, *current=m_head; current; current=next) + { + next=current->m_next; + delete current; + } +} + +void ByteQueue::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256); + Clear(); +} + +lword ByteQueue::CurrentSize() const +{ + lword size=0; + + for (ByteQueueNode *current=m_head; current; current=current->m_next) + size += current->CurrentSize(); + + return size + m_lazyLength; +} + +bool ByteQueue::IsEmpty() const +{ + return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0; +} + +void ByteQueue::Clear() +{ + for (ByteQueueNode *next, *current=m_head->m_next; current; current=next) + { + next=current->m_next; + delete current; + } + + m_tail = m_head; + m_head->Clear(); + m_head->m_next = NULLPTR; + m_lazyLength = 0; +} + +size_t ByteQueue::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) +{ + CRYPTOPP_UNUSED(messageEnd), CRYPTOPP_UNUSED(blocking); + + if (m_lazyLength > 0) + FinalizeLazyPut(); + + size_t len; + while ((len=m_tail->Put(inString, length)) < length) + { + inString = PtrAdd(inString, len); + length -= len; + if (m_autoNodeSize && m_nodeSize < s_maxAutoNodeSize) + { + do + { + m_nodeSize *= 2; + } + while (m_nodeSize < length && m_nodeSize < s_maxAutoNodeSize); + } + m_tail->m_next = new ByteQueueNode(STDMAX(m_nodeSize, length)); + m_tail = m_tail->m_next; + } + + return 0; +} + +void ByteQueue::CleanupUsedNodes() +{ + // Test for m_head due to Enterprise Anlysis finding + while (m_head && m_head != m_tail && m_head->UsedUp()) + { + ByteQueueNode *temp=m_head; + m_head=m_head->m_next; + delete temp; + } + + // Test for m_head due to Enterprise Anlysis finding + if (m_head && m_head->CurrentSize() == 0) + m_head->Clear(); +} + +void ByteQueue::LazyPut(const byte *inString, size_t size) +{ + if (m_lazyLength > 0) + FinalizeLazyPut(); + + if (inString == m_tail->m_buf+m_tail->m_tail) + Put(inString, size); + else + { + m_lazyString = const_cast(inString); + m_lazyLength = size; + m_lazyStringModifiable = false; + } +} + +void ByteQueue::LazyPutModifiable(byte *inString, size_t size) +{ + if (m_lazyLength > 0) + FinalizeLazyPut(); + m_lazyString = inString; + m_lazyLength = size; + m_lazyStringModifiable = true; +} + +void ByteQueue::UndoLazyPut(size_t size) +{ + if (m_lazyLength < size) + throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large"); + + m_lazyLength -= size; +} + +void ByteQueue::FinalizeLazyPut() +{ + size_t len = m_lazyLength; + m_lazyLength = 0; + if (len) + Put(m_lazyString, len); +} + +size_t ByteQueue::Get(byte &outByte) +{ + if (m_head->Get(outByte)) + { + if (m_head->UsedUp()) + CleanupUsedNodes(); + return 1; + } + else if (m_lazyLength > 0) + { + outByte = *m_lazyString++; + m_lazyLength--; + return 1; + } + else + return 0; +} + +size_t ByteQueue::Get(byte *outString, size_t getMax) +{ + ArraySink sink(outString, getMax); + return (size_t)TransferTo(sink, getMax); +} + +size_t ByteQueue::Peek(byte &outByte) const +{ + if (m_head->Peek(outByte)) + return 1; + else if (m_lazyLength > 0) + { + outByte = *m_lazyString; + return 1; + } + else + return 0; +} + +size_t ByteQueue::Peek(byte *outString, size_t peekMax) const +{ + ArraySink sink(outString, peekMax); + return (size_t)CopyTo(sink, peekMax); +} + +size_t ByteQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + // No need for CRYPTOPP_ASSERT on transferBytes here. + // TransferTo2 handles LWORD_MAX as expected. + + if (blocking) + { + lword bytesLeft = transferBytes; + for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->m_next) + bytesLeft -= current->TransferTo(target, bytesLeft, channel); + CleanupUsedNodes(); + + size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength); + if (len) + { + if (m_lazyStringModifiable) + target.ChannelPutModifiable(channel, m_lazyString, len); + else + target.ChannelPut(channel, m_lazyString, len); + m_lazyString = PtrAdd(m_lazyString, len); + m_lazyLength -= len; + bytesLeft -= len; + } + transferBytes -= bytesLeft; + return 0; + } + else + { + Walker walker(*this); + size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); + Skip(transferBytes); + return blockedBytes; + } +} + +size_t ByteQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + Walker walker(*this); + walker.Skip(begin); + lword transferBytes = end-begin; + + size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); + begin += transferBytes; + return blockedBytes; +} + +void ByteQueue::Unget(byte inByte) +{ + Unget(&inByte, 1); +} + +void ByteQueue::Unget(const byte *inString, size_t length) +{ + // See GH #962 for the reason for this assert. + CRYPTOPP_ASSERT(length != SIZE_MAX); + + size_t len = STDMIN(length, m_head->m_head); + length -= len; + m_head->m_head = m_head->m_head - len; + memcpy(m_head->m_buf + m_head->m_head, inString + length, len); + + if (length > 0) + { + ByteQueueNode *newHead = new ByteQueueNode(length); + newHead->m_next = m_head; + m_head = newHead; + m_head->Put(inString, length); + } +} + +const byte * ByteQueue::Spy(size_t &contiguousSize) const +{ + contiguousSize = m_head->m_tail - m_head->m_head; + if (contiguousSize == 0 && m_lazyLength > 0) + { + contiguousSize = m_lazyLength; + return m_lazyString; + } + else + return m_head->m_buf + m_head->m_head; +} + +byte * ByteQueue::CreatePutSpace(size_t &size) +{ + // See GH #962 for the reason for this assert. + CRYPTOPP_ASSERT(size != SIZE_MAX); + // Sanity check for a reasonable size + CRYPTOPP_ASSERT(size <= 16U*1024*1024); + + if (m_lazyLength > 0) + FinalizeLazyPut(); + + if (m_tail->m_tail == m_tail->MaxSize()) + { + m_tail->m_next = new ByteQueueNode(STDMAX(m_nodeSize, size)); + m_tail = m_tail->m_next; + } + + size = m_tail->MaxSize() - m_tail->m_tail; + return PtrAdd(m_tail->m_buf.begin(), m_tail->m_tail); +} + +ByteQueue & ByteQueue::operator=(const ByteQueue &rhs) +{ + Destroy(); + CopyFrom(rhs); + return *this; +} + +bool ByteQueue::operator==(const ByteQueue &rhs) const +{ + const lword currentSize = CurrentSize(); + + if (currentSize != rhs.CurrentSize()) + return false; + + Walker walker1(*this), walker2(rhs); + byte b1, b2; + + while (walker1.Get(b1) && walker2.Get(b2)) + if (b1 != b2) + return false; + + return true; +} + +byte ByteQueue::operator[](lword index) const +{ + for (ByteQueueNode *current=m_head; current; current=current->m_next) + { + if (index < current->CurrentSize()) + return (*current)[(size_t)index]; + + index -= current->CurrentSize(); + } + + CRYPTOPP_ASSERT(index < m_lazyLength); + return m_lazyString[index]; +} + +void ByteQueue::swap(ByteQueue &rhs) +{ + std::swap(m_autoNodeSize, rhs.m_autoNodeSize); + std::swap(m_nodeSize, rhs.m_nodeSize); + std::swap(m_head, rhs.m_head); + std::swap(m_tail, rhs.m_tail); + std::swap(m_lazyString, rhs.m_lazyString); + std::swap(m_lazyLength, rhs.m_lazyLength); + std::swap(m_lazyStringModifiable, rhs.m_lazyStringModifiable); +} + +// ******************************************************** + +void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs ¶meters) +{ + CRYPTOPP_UNUSED(parameters); + + m_node = m_queue.m_head; + m_position = 0; + m_offset = 0; + m_lazyString = m_queue.m_lazyString; + m_lazyLength = m_queue.m_lazyLength; +} + +size_t ByteQueue::Walker::Get(byte &outByte) +{ + ArraySink sink(&outByte, 1); + return (size_t)TransferTo(sink, 1); +} + +size_t ByteQueue::Walker::Get(byte *outString, size_t getMax) +{ + ArraySink sink(outString, getMax); + return (size_t)TransferTo(sink, getMax); +} + +size_t ByteQueue::Walker::Peek(byte &outByte) const +{ + ArraySink sink(&outByte, 1); + return (size_t)CopyTo(sink, 1); +} + +size_t ByteQueue::Walker::Peek(byte *outString, size_t peekMax) const +{ + ArraySink sink(outString, peekMax); + return (size_t)CopyTo(sink, peekMax); +} + +size_t ByteQueue::Walker::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + // No need for CRYPTOPP_ASSERT on transferBytes here. + // TransferTo2 handles LWORD_MAX as expected. + + lword bytesLeft = transferBytes; + size_t blockedBytes = 0; + + while (m_node) + { + size_t len = (size_t)STDMIN(bytesLeft, (lword)m_node->CurrentSize()-m_offset); + blockedBytes = target.ChannelPut2(channel, m_node->m_buf+m_node->m_head+m_offset, len, 0, blocking); + + if (blockedBytes) + goto done; + + m_position += len; + bytesLeft -= len; + + if (!bytesLeft) + { + m_offset += len; + goto done; + } + + m_node = m_node->m_next; + m_offset = 0; + } + + if (bytesLeft && m_lazyLength) + { + size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength); + blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking); + if (blockedBytes) + goto done; + + m_lazyString = PtrAdd(m_lazyString, len); + m_lazyLength -= len; + bytesLeft -= len; + } + +done: + transferBytes -= bytesLeft; + return blockedBytes; +} + +size_t ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + Walker walker(*this); + walker.Skip(begin); + lword transferBytes = end-begin; + + size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); + begin += transferBytes; + return blockedBytes; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/queue.h b/external/ours/library/crypto/src/shared/original/queue.h index 76cf58d7f..f2d0dc53f 100755 --- a/external/ours/library/crypto/src/shared/original/queue.h +++ b/external/ours/library/crypto/src/shared/original/queue.h @@ -1,128 +1,272 @@ -// specification file for an unlimited queue for storing bytes - -#ifndef CRYPTOPP_QUEUE_H -#define CRYPTOPP_QUEUE_H - -#include "cryptlib.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -/** The queue is implemented as a linked list of arrays, but you don't need to - know about that. So just ignore this next line. :) */ -class ByteQueueNode; - -//! Byte Queue -class ByteQueue : public BufferedTransformation -{ -public: - ByteQueue(unsigned int m_nodeSize=256); - ByteQueue(const ByteQueue ©); - ~ByteQueue(); - - unsigned long MaxRetrievable() const - {return CurrentSize();} - bool AnyRetrievable() const - {return !IsEmpty();} - - void Put(byte inByte); - void Put(const byte *inString, unsigned int length); - - unsigned int Get(byte &outByte); - unsigned int Get(byte *outString, unsigned int getMax); - - unsigned int Peek(byte &outByte) const; - unsigned int Peek(byte *outString, unsigned int peekMax) const; - - unsigned long Skip(unsigned long skipMax=ULONG_MAX); - unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX); - unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const; - - // these member functions are not inherited - unsigned long CurrentSize() const; - bool IsEmpty() const; - - void Clear(); - - void Unget(byte inByte); - void Unget(const byte *inString, unsigned int length); - - const byte * Spy(unsigned int &contiguousSize) const; - - byte * MakeNewSpace(unsigned int &contiguousSize); - void OccupyNewSpace(unsigned int size); - - void LazyPut(const byte *inString, unsigned int size); - void FinalizeLazyPut(); - - ByteQueue & operator=(const ByteQueue &rhs); - bool operator==(const ByteQueue &rhs) const; - byte operator[](unsigned long i) const; - void swap(ByteQueue &rhs); - - class Walker : public BufferedTransformation - { - public: - Walker(const ByteQueue &queue) - : m_queue(queue), m_node(queue.m_head), m_position(0), m_offset(0) - , m_lazyString(queue.m_lazyString), m_lazyLength(queue.m_lazyLength) {} - - unsigned long MaxRetrievable() const - {return m_queue.CurrentSize() - m_position;} - - void Put(byte inByte) {} - void Put(const byte *inString, unsigned int length) {} - - unsigned int Get(byte &outByte); - unsigned int Get(byte *outString, unsigned int getMax); - - unsigned int Peek(byte &outByte) const; - unsigned int Peek(byte *outString, unsigned int peekMax) const; - - unsigned long Skip(unsigned long skipMax=ULONG_MAX); - unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX); - unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const; - - private: - const ByteQueue &m_queue; - const ByteQueueNode *m_node; - unsigned int m_position, m_offset; - const byte *m_lazyString; - unsigned int m_lazyLength; - }; - - friend class Walker; - -private: - void CleanupUsedNodes(); - void CopyFrom(const ByteQueue ©); - void Destroy(); - - unsigned int m_nodeSize; - ByteQueueNode *m_head, *m_tail; - const byte *m_lazyString; - unsigned int m_lazyLength; -}; - -//! use this to make sure LazyPut is finalized in event of exception -class LazyPutter -{ -public: - LazyPutter(ByteQueue &bq, const byte *inString, unsigned int size) - : m_bq(bq) {bq.LazyPut(inString, size);} - ~LazyPutter() - {try {m_bq.FinalizeLazyPut();} catch(...) {}} -private: - ByteQueue &m_bq; -}; - -NAMESPACE_END - -NAMESPACE_BEGIN(std) -template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b) -{ - a.swap(b); -} -NAMESPACE_END - -#endif +// queue.h - originally written and placed in the public domain by Wei Dai + +/// \file +/// \brief Classes for an unlimited queue to store bytes + +#ifndef CRYPTOPP_QUEUE_H +#define CRYPTOPP_QUEUE_H + +#include "cryptlib.h" +#include "simple.h" + +NAMESPACE_BEGIN(CryptoPP) + +class ByteQueueNode; + +/// \brief Data structure used to store byte strings +/// \details The queue is implemented as a linked list of byte arrays. +/// Each byte array is stored in a ByteQueueNode. +/// \sa ByteQueue +/// 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/external/ours/library/crypto/src/shared/original/rabbit.cpp b/external/ours/library/crypto/src/shared/original/rabbit.cpp new file mode 100755 index 000000000..4f6551117 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rabbit.cpp @@ -0,0 +1,259 @@ +// rabbit.cpp - 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. + +#include "pch.h" +#include "config.h" + +#include "rabbit.h" +#include "secblock.h" +#include "misc.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::rotlConstant; + +word32 G_func(word32 x) +{ +#if 0 + /* Temporary variables */ + word32 a, b, h, l; + + /* Construct high and low argument for squaring */ + a = x & 0xFFFF; + b = x >> 16; + + /* Calculate high and low result of squaring */ + h = (((static_cast(a*a) >> 17U) + static_cast(a*b)) >> 15U) + b*b; + l = x*x; + + /* Return high XOR low */ + return static_cast(h^l); +#endif + + // Thanks to Jack Lloyd for suggesting the 64-bit multiply. + word64 z = x; + z *= x; + return static_cast((z >> 32) ^ z); +} + +word32 NextState(word32 c[8], word32 x[8], word32 carry) +{ + /* Temporary variables */ + word32 g[8], c_old[8], i; + + /* Save old counter values */ + for (i = 0; i<8; i++) + c_old[i] = c[i]; + + /* Calculate new counter values */ + c[0] = static_cast(c[0] + 0x4D34D34D + carry); + c[1] = static_cast(c[1] + 0xD34D34D3 + (c[0] < c_old[0])); + c[2] = static_cast(c[2] + 0x34D34D34 + (c[1] < c_old[1])); + c[3] = static_cast(c[3] + 0x4D34D34D + (c[2] < c_old[2])); + c[4] = static_cast(c[4] + 0xD34D34D3 + (c[3] < c_old[3])); + c[5] = static_cast(c[5] + 0x34D34D34 + (c[4] < c_old[4])); + c[6] = static_cast(c[6] + 0x4D34D34D + (c[5] < c_old[5])); + c[7] = static_cast(c[7] + 0xD34D34D3 + (c[6] < c_old[6])); + carry = (c[7] < c_old[7]); + + /* Calculate the g-values */ + for (i = 0; i<8; i++) + g[i] = G_func(static_cast(x[i] + c[i])); + + /* Calculate new state values */ + x[0] = static_cast(g[0] + rotlConstant<16>(g[7]) + rotlConstant<16>(g[6])); + x[1] = static_cast(g[1] + rotlConstant<8>(g[0]) + g[7]); + x[2] = static_cast(g[2] + rotlConstant<16>(g[1]) + rotlConstant<16>(g[0])); + x[3] = static_cast(g[3] + rotlConstant<8>(g[2]) + g[1]); + x[4] = static_cast(g[4] + rotlConstant<16>(g[3]) + rotlConstant<16>(g[2])); + x[5] = static_cast(g[5] + rotlConstant<8>(g[4]) + g[3]); + x[6] = static_cast(g[6] + rotlConstant<16>(g[5]) + rotlConstant<16>(g[4])); + x[7] = static_cast(g[7] + rotlConstant<8>(g[6]) + g[5]); + + return carry; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void RabbitPolicy::CipherSetKey(const NameValuePairs ¶ms, const byte *userKey, size_t keylen) +{ + /* Generate four subkeys */ + CRYPTOPP_UNUSED(params); + GetUserKey(LITTLE_ENDIAN_ORDER, m_t.begin(), 4, userKey, keylen); + + /* Generate initial state variables */ + m_mx[0] = m_t[0]; + m_mx[2] = m_t[1]; + m_mx[4] = m_t[2]; + m_mx[6] = m_t[3]; + m_mx[1] = static_cast(m_t[3] << 16) | (m_t[2] >> 16); + m_mx[3] = static_cast(m_t[0] << 16) | (m_t[3] >> 16); + m_mx[5] = static_cast(m_t[1] << 16) | (m_t[0] >> 16); + m_mx[7] = static_cast(m_t[2] << 16) | (m_t[1] >> 16); + + /* Generate initial counter values */ + m_mc[0] = rotlConstant<16>(m_t[2]); + m_mc[2] = rotlConstant<16>(m_t[3]); + m_mc[4] = rotlConstant<16>(m_t[0]); + m_mc[6] = rotlConstant<16>(m_t[1]); + m_mc[1] = (m_t[0] & 0xFFFF0000) | (m_t[1] & 0xFFFF); + m_mc[3] = (m_t[1] & 0xFFFF0000) | (m_t[2] & 0xFFFF); + m_mc[5] = (m_t[2] & 0xFFFF0000) | (m_t[3] & 0xFFFF); + m_mc[7] = (m_t[3] & 0xFFFF0000) | (m_t[0] & 0xFFFF); + + /* Clear carry bit */ + m_mcy = 0; + + /* Iterate the system four times */ + for (unsigned int i = 0; i<4; i++) + m_mcy = NextState(m_mc, m_mx, m_mcy); + + /* Modify the counters */ + for (unsigned int i = 0; i<8; i++) + m_mc[i] ^= m_mx[(i + 4) & 0x7]; + + /* Copy master instance to work instance */ + for (unsigned int i = 0; i<8; i++) + { + m_wx[i] = m_mx[i]; + m_wc[i] = m_mc[i]; + } + m_wcy = m_mcy; +} + +void RabbitPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ + byte* out = output; + for (size_t i = 0; i> 16) ^ (m_wx[3] << 16)); + PutWord(false, LITTLE_ENDIAN_ORDER, out + 4, m_wx[2] ^ (m_wx[7] >> 16) ^ (m_wx[5] << 16)); + PutWord(false, LITTLE_ENDIAN_ORDER, out + 8, m_wx[4] ^ (m_wx[1] >> 16) ^ (m_wx[7] << 16)); + PutWord(false, LITTLE_ENDIAN_ORDER, out + 12, m_wx[6] ^ (m_wx[3] >> 16) ^ (m_wx[1] << 16)); + } + + // If AdditiveCipherTemplate does not have an accumulated keystream + // then it will ask OperateKeystream to generate one. Optionally it + // will ask for an XOR of the input with the keystream while + // writing the result to the output buffer. In all cases the + // keystream is written to the output buffer. The optional part is + // adding the input buffer and keystream. + if ((operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL)) + xorbuf(output, input, GetBytesPerIteration() * iterationCount); +} + +void RabbitWithIVPolicy::CipherSetKey(const NameValuePairs ¶ms, const byte *userKey, size_t keylen) +{ + /* Generate four subkeys */ + CRYPTOPP_UNUSED(params); + GetUserKey(LITTLE_ENDIAN_ORDER, m_t.begin(), 4, userKey, keylen); + + /* Generate initial state variables */ + m_mx[0] = m_t[0]; + m_mx[2] = m_t[1]; + m_mx[4] = m_t[2]; + m_mx[6] = m_t[3]; + m_mx[1] = static_cast(m_t[3] << 16) | (m_t[2] >> 16); + m_mx[3] = static_cast(m_t[0] << 16) | (m_t[3] >> 16); + m_mx[5] = static_cast(m_t[1] << 16) | (m_t[0] >> 16); + m_mx[7] = static_cast(m_t[2] << 16) | (m_t[1] >> 16); + + /* Generate initial counter values */ + m_mc[0] = rotlConstant<16>(m_t[2]); + m_mc[2] = rotlConstant<16>(m_t[3]); + m_mc[4] = rotlConstant<16>(m_t[0]); + m_mc[6] = rotlConstant<16>(m_t[1]); + m_mc[1] = (m_t[0] & 0xFFFF0000) | (m_t[1] & 0xFFFF); + m_mc[3] = (m_t[1] & 0xFFFF0000) | (m_t[2] & 0xFFFF); + m_mc[5] = (m_t[2] & 0xFFFF0000) | (m_t[3] & 0xFFFF); + m_mc[7] = (m_t[3] & 0xFFFF0000) | (m_t[0] & 0xFFFF); + + /* Clear carry bit */ + m_mcy = 0; + + /* Iterate the system four times */ + for (unsigned int i = 0; i<4; i++) + m_mcy = NextState(m_mc, m_mx, m_mcy); + + /* Modify the counters */ + for (unsigned int i = 0; i<8; i++) + m_mc[i] ^= m_mx[(i + 4) & 0x7]; + + /* Copy master instance to work instance */ + for (unsigned int i = 0; i<8; i++) + { + m_wx[i] = m_mx[i]; + m_wc[i] = m_mc[i]; + } + m_wcy = m_mcy; +} + +void RabbitWithIVPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer); + CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length == 8); + + /* Generate four subvectors */ + GetBlock v(iv); v(m_t[0])(m_t[2]); + m_t[1] = (m_t[0] >> 16) | (m_t[2] & 0xFFFF0000); + m_t[3] = (m_t[2] << 16) | (m_t[0] & 0x0000FFFF); + + /* Modify counter values */ + m_wc[0] = m_mc[0] ^ m_t[0]; + m_wc[1] = m_mc[1] ^ m_t[1]; + m_wc[2] = m_mc[2] ^ m_t[2]; + m_wc[3] = m_mc[3] ^ m_t[3]; + m_wc[4] = m_mc[4] ^ m_t[0]; + m_wc[5] = m_mc[5] ^ m_t[1]; + m_wc[6] = m_mc[6] ^ m_t[2]; + m_wc[7] = m_mc[7] ^ m_t[3]; + + /* Copy state variables */ + for (unsigned int i = 0; i<8; i++) + m_wx[i] = m_mx[i]; + m_wcy = m_mcy; + + /* Iterate the system four times */ + for (unsigned int i = 0; i<4; i++) + m_wcy = NextState(m_wc, m_wx, m_wcy); +} + +void RabbitWithIVPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ + byte* out = output; + for (unsigned int i = 0; i> 16) ^ (m_wx[3] << 16)); + PutWord(false, LITTLE_ENDIAN_ORDER, out + 4, m_wx[2] ^ (m_wx[7] >> 16) ^ (m_wx[5] << 16)); + PutWord(false, LITTLE_ENDIAN_ORDER, out + 8, m_wx[4] ^ (m_wx[1] >> 16) ^ (m_wx[7] << 16)); + PutWord(false, LITTLE_ENDIAN_ORDER, out + 12, m_wx[6] ^ (m_wx[3] >> 16) ^ (m_wx[1] << 16)); + } + + // If AdditiveCipherTemplate does not have an accumulated keystream + // then it will ask OperateKeystream to generate one. Optionally it + // will ask for an XOR of the input with the keystream while + // writing the result to the output buffer. In all cases the + // keystream is written to the output buffer. The optional part is + // adding the input buffer and keystream. + if ((operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL)) + xorbuf(output, input, GetBytesPerIteration() * iterationCount); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/rabbit.h b/external/ours/library/crypto/src/shared/original/rabbit.h new file mode 100755 index 000000000..6601dcd19 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/rabin.cpp b/external/ours/library/crypto/src/shared/original/rabin.cpp new file mode 100755 index 000000000..e112d9b86 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rabin.cpp @@ -0,0 +1,241 @@ +// rabin.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "rabin.h" +#include "integer.h" +#include "nbtheory.h" +#include "modarith.h" +#include "asn.h" +#include "sha.h" + +NAMESPACE_BEGIN(CryptoPP) + +void RabinFunction::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + m_n.BERDecode(seq); + m_r.BERDecode(seq); + m_s.BERDecode(seq); + seq.MessageEnd(); +} + +void RabinFunction::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + m_n.DEREncode(seq); + m_r.DEREncode(seq); + m_s.DEREncode(seq); + seq.MessageEnd(); +} + +Integer RabinFunction::ApplyFunction(const Integer &in) const +{ + DoQuickSanityCheck(); + + Integer out = in.Squared()%m_n; + if (in.IsOdd()) + out = out*m_r%m_n; + if (Jacobi(in, m_n)==-1) + out = out*m_s%m_n; + return out; +} + +bool RabinFunction::Validate(RandomNumberGenerator& /*rng*/, unsigned int level) const +{ + bool pass = true; + pass = pass && m_n > Integer::One() && m_n%4 == 1; + CRYPTOPP_ASSERT(pass); + pass = pass && m_r > Integer::One() && m_r < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_s > Integer::One() && m_s < m_n; + CRYPTOPP_ASSERT(pass); + if (level >= 1) + { + pass = pass && Jacobi(m_r, m_n) == -1 && Jacobi(m_s, m_n) == -1; + CRYPTOPP_ASSERT(pass); + } + return pass; +} + +bool RabinFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_GET_FUNCTION_ENTRY(QuadraticResidueModPrime1) + CRYPTOPP_GET_FUNCTION_ENTRY(QuadraticResidueModPrime2) + ; +} + +void RabinFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_SET_FUNCTION_ENTRY(QuadraticResidueModPrime1) + CRYPTOPP_SET_FUNCTION_ENTRY(QuadraticResidueModPrime2) + ; +} + +// ***************************************************************************** +// private key operations: + +// generate a random private key +void InvertibleRabinFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + int modulusSize = 2048; + alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize); + + if (modulusSize < 16) + throw InvalidArgument("InvertibleRabinFunction: specified modulus size is too small"); + + // VC70 workaround: putting these after primeParam causes overlapped stack allocation + bool rFound=false, sFound=false; + Integer t=2; + + AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize) + ("EquivalentTo", 3)("Mod", 4); + m_p.GenerateRandom(rng, primeParam); + m_q.GenerateRandom(rng, primeParam); + + while (!(rFound && sFound)) + { + int jp = Jacobi(t, m_p); + int jq = Jacobi(t, m_q); + + if (!rFound && jp==1 && jq==-1) + { + m_r = t; + rFound = true; + } + + if (!sFound && jp==-1 && jq==1) + { + m_s = t; + sFound = true; + } + + ++t; + } + + m_n = m_p * m_q; + m_u = m_q.InverseMod(m_p); +} + +void InvertibleRabinFunction::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + m_n.BERDecode(seq); + m_r.BERDecode(seq); + m_s.BERDecode(seq); + m_p.BERDecode(seq); + m_q.BERDecode(seq); + m_u.BERDecode(seq); + seq.MessageEnd(); +} + +void InvertibleRabinFunction::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + m_n.DEREncode(seq); + m_r.DEREncode(seq); + m_s.DEREncode(seq); + m_p.DEREncode(seq); + m_q.DEREncode(seq); + m_u.DEREncode(seq); + seq.MessageEnd(); +} + +Integer InvertibleRabinFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &in) const +{ + DoQuickSanityCheck(); + + ModularArithmetic modn(m_n); + Integer r(rng, Integer::One(), m_n - Integer::One()); + r = modn.Square(r); + Integer r2 = modn.Square(r); + Integer c = modn.Multiply(in, r2); // blind + + Integer cp=c%m_p, cq=c%m_q; + + int jp = Jacobi(cp, m_p); + int jq = Jacobi(cq, m_q); + + if (jq==-1) + { + cp = cp*EuclideanMultiplicativeInverse(m_r, m_p)%m_p; + cq = cq*EuclideanMultiplicativeInverse(m_r, m_q)%m_q; + } + + if (jp==-1) + { + cp = cp*EuclideanMultiplicativeInverse(m_s, m_p)%m_p; + cq = cq*EuclideanMultiplicativeInverse(m_s, m_q)%m_q; + } + + cp = ModularSquareRoot(cp, m_p); + cq = ModularSquareRoot(cq, m_q); + + if (jp==-1) + cp = m_p-cp; + + Integer out = CRT(cq, m_q, cp, m_p, m_u); + + out = modn.Divide(out, r); // unblind + + if ((jq==-1 && out.IsEven()) || (jq==1 && out.IsOdd())) + out = m_n-out; + + return out; +} + +bool InvertibleRabinFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = RabinFunction::Validate(rng, level); + CRYPTOPP_ASSERT(pass); + pass = pass && m_p > Integer::One() && m_p%4 == 3 && m_p < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_q > Integer::One() && m_q%4 == 3 && m_q < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_u.IsPositive() && m_u < m_p; + CRYPTOPP_ASSERT(pass); + if (level >= 1) + { + pass = pass && m_p * m_q == m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_u * m_q % m_p == 1; + CRYPTOPP_ASSERT(pass); + pass = pass && Jacobi(m_r, m_p) == 1; + CRYPTOPP_ASSERT(pass); + pass = pass && Jacobi(m_r, m_q) == -1; + CRYPTOPP_ASSERT(pass); + pass = pass && Jacobi(m_s, m_p) == -1; + CRYPTOPP_ASSERT(pass); + pass = pass && Jacobi(m_s, m_q) == 1; + CRYPTOPP_ASSERT(pass); + } + if (level >= 2) + { + pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2); + CRYPTOPP_ASSERT(pass); + } + return pass; +} + +bool InvertibleRabinFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_GET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; +} + +void InvertibleRabinFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/rabin.h b/external/ours/library/crypto/src/shared/original/rabin.h new file mode 100755 index 000000000..1cea7d454 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/randpool.cpp b/external/ours/library/crypto/src/shared/original/randpool.cpp new file mode 100755 index 000000000..8e686f07c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/randpool.cpp @@ -0,0 +1,174 @@ +// randpool.cpp - originally written and placed in the public domain by Wei Dai +// RandomPool used to follow the design of randpool in PGP 2.6.x, +// but as of version 5.5 it has been redesigned to reduce the risk +// of reusing random numbers after state rollback (which may occur +// when running in a virtual machine like VMware). + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "randpool.h" +#include "aes.h" +#include "sha.h" +#include "hrtimer.h" +#include "trap.h" + +// OldRandomPool +#include "mdc.h" +#include "modes.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +RandomPool::RandomPool() + : m_pCipher(new AES::Encryption), m_keySet(false) +{ + std::memset(m_key, 0, m_key.SizeInBytes()); + std::memset(m_seed, 0, m_seed.SizeInBytes()); +} + +void RandomPool::IncorporateEntropy(const byte *input, size_t length) +{ + SHA256 hash; + hash.Update(m_key, 32); + hash.Update(input, length); + hash.Final(m_key); + m_keySet = false; +} + +void RandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size) +{ + if (size > 0) + { + if (!m_keySet) + m_pCipher->SetKey(m_key, 32); + + CRYPTOPP_COMPILE_ASSERT(sizeof(TimerWord) <= 16); + CRYPTOPP_COMPILE_ASSERT(sizeof(time_t) <= 8); + + Timer timer; + TimerWord tw = timer.GetCurrentTimerValue(); + + *(TimerWord *)(void*)m_seed.data() += tw; + time_t t = time(NULLPTR); + + // UBsan finding: signed integer overflow: 1876017710 + 1446085457 cannot be represented in type 'long int' + // *(time_t *)(m_seed.data()+8) += t; + word64 tt1 = 0, tt2 = (word64)t; + std::memcpy(&tt1, m_seed.data()+8, 8); + std::memcpy(m_seed.data()+8, &(tt2 += tt1), 8); + + // Wipe the intermediates + *((volatile TimerWord*)&tw) = 0; + *((volatile word64*)&tt1) = 0; + *((volatile word64*)&tt2) = 0; + + do + { + m_pCipher->ProcessBlock(m_seed); + size_t len = UnsignedMin(16, size); + target.ChannelPut(channel, m_seed, len); + size -= len; + } while (size > 0); + } +} + +// OldRandomPool is provided for backwards compatibility for a migration path +typedef MDC OldRandomPoolCipher; + +OldRandomPool::OldRandomPool(unsigned int poolSize) + : pool(poolSize), key(OldRandomPoolCipher::DEFAULT_KEYLENGTH), addPos(0), getPos(poolSize) +{ + CRYPTOPP_ASSERT(poolSize > key.size()); + std::memset(pool, 0, poolSize); + std::memset(key, 0, key.size()); +} + +void OldRandomPool::IncorporateEntropy(const byte *input, size_t length) +{ + size_t t; + while (length > (t = pool.size() - addPos)) + { + xorbuf(pool+addPos, input, t); + input += t; + length -= t; + Stir(); + } + + if (length) + { + xorbuf(pool+addPos, input, length); + addPos += length; + getPos = pool.size(); // Force stir on get + } +} + +// GenerateWord32 is overriden and provides Crypto++ 5.4 behavior. +// Taken from RandomNumberGenerator::GenerateWord32 in cryptlib.cpp. +word32 OldRandomPool::GenerateWord32 (word32 min, word32 max) +{ + const word32 range = max-min; + const unsigned int maxBytes = BytePrecision(range); + const unsigned int maxBits = BitPrecision(range); + + word32 value; + + do + { + value = 0; + for (unsigned int i=0; i range); + + return value+min; +} + +void OldRandomPool::Stir() +{ + CFB_Mode::Encryption cipher; + + for (int i=0; i<2; i++) + { + cipher.SetKeyWithIV(key, key.size(), pool.end()-cipher.IVSize()); + cipher.ProcessString(pool, pool.size()); + std::memcpy(key, pool, key.size()); + } + + addPos = 0; + getPos = key.size(); +} + +void OldRandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size) +{ + while (size > 0) + { + if (getPos == pool.size()) + Stir(); + size_t t = UnsignedMin(pool.size() - getPos, size); + target.ChannelPut(channel, pool+getPos, t); + size -= t; + getPos += t; + } +} + +byte OldRandomPool::GenerateByte() +{ + if (getPos == pool.size()) + Stir(); + + return pool[getPos++]; +} + +void OldRandomPool::GenerateBlock(byte *outString, size_t size) +{ + ArraySink sink(outString, size); + GenerateIntoBufferedTransformation(sink, DEFAULT_CHANNEL, size); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/randpool.h b/external/ours/library/crypto/src/shared/original/randpool.h new file mode 100755 index 000000000..e640b943f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 overriden 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/external/ours/library/crypto/src/shared/original/rc2.cpp b/external/ours/library/crypto/src/shared/original/rc2.cpp new file mode 100755 index 000000000..1469cc59e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rc2.cpp @@ -0,0 +1,118 @@ +// rc2.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "rc2.h" +#include "misc.h" +#include "argnames.h" + +NAMESPACE_BEGIN(CryptoPP) + +void RC2::Base::UncheckedSetKey(const byte *key, unsigned int keyLen, const NameValuePairs ¶ms) +{ + AssertValidKeyLength(keyLen); + + int effectiveLen = params.GetIntValueWithDefault(Name::EffectiveKeyLength(), DEFAULT_EFFECTIVE_KEYLENGTH); + if (effectiveLen > MAX_EFFECTIVE_KEYLENGTH) + throw InvalidArgument("RC2: effective key length parameter exceeds maximum"); + + static const unsigned char PITABLE[256] = { + 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, + 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, + 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, + 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, + 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, + 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, + 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, + 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, + 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, + 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, + 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, + 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, + 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, + 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, + 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, + 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173}; + + SecByteBlock L(128); + memcpy(L, key, keyLen); + + int i; + for (i=keyLen; i<128; i++) + L[i] = PITABLE[(L[i-1] + L[i-keyLen]) & 255]; + + unsigned int T8 = (effectiveLen+7) / 8; + byte TM = byte((int)255 >> ((8-(effectiveLen%8))%8)); + L[128-T8] = PITABLE[L[128-T8] & TM]; + + for (i=127-T8; i>=0; i--) + L[i] = PITABLE[L[i+1] ^ L[i+T8]]; + + for (i=0; i<64; i++) + K[i] = L[2*i] + (L[2*i+1] << 8); +} + +typedef BlockGetAndPut Block; + +void RC2::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word16 R0, R1, R2, R3; + Block::Get(inBlock)(R0)(R1)(R2)(R3); + + for (int i = 0; i < 16; i++) + { + R0 += (R1 & ~R3) + (R2 & R3) + K[4*i+0]; + R0 = rotlConstant<1>(R0); + + R1 += (R2 & ~R0) + (R3 & R0) + K[4*i+1]; + R1 = rotlConstant<2>(R1); + + R2 += (R3 & ~R1) + (R0 & R1) + K[4*i+2]; + R2 = rotlConstant<3>(R2); + + R3 += (R0 & ~R2) + (R1 & R2) + K[4*i+3]; + R3 = rotlConstant<5>(R3); + + if (i == 4 || i == 10) + { + R0 = word16(R0 + K[R3 & 63]); + R1 = word16(R1 + K[R0 & 63]); + R2 = word16(R2 + K[R1 & 63]); + R3 = word16(R3 + K[R2 & 63]); + } + } + + Block::Put(xorBlock, outBlock)(R0)(R1)(R2)(R3); +} + +void RC2::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word16 R0, R1, R2, R3; + Block::Get(inBlock)(R0)(R1)(R2)(R3); + + for (int i = 15; i >= 0; i--) + { + if (i == 4 || i == 10) + { + R3 = word16(R3 - K[R2 & 63]); + R2 = word16(R2 - K[R1 & 63]); + R1 = word16(R1 - K[R0 & 63]); + R0 = word16(R0 - K[R3 & 63]); + } + + R3 = rotrConstant<5>(R3); + R3 = word16(R3 - ((R0 & ~R2) + (R1 & R2) + K[4*i+3])); + + R2 = rotrConstant<3>(R2); + R2 = word16(R2 - ((R3 & ~R1) + (R0 & R1) + K[4*i+2])); + + R1 = rotrConstant<2>(R1); + R1 = word16(R1 - ((R2 & ~R0) + (R3 & R0) + K[4*i+1])); + + R0 = rotrConstant<1>(R0); + R0 = word16(R0 - ((R1 & ~R3) + (R2 & R3) + K[4*i+0])); + } + + Block::Put(xorBlock, outBlock)(R0)(R1)(R2)(R3); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/rc2.h b/external/ours/library/crypto/src/shared/original/rc2.h new file mode 100755 index 000000000..50a39ae8c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/rc5.cpp b/external/ours/library/crypto/src/shared/original/rc5.cpp new file mode 100755 index 000000000..262c9aec2 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rc5.cpp @@ -0,0 +1,80 @@ +// rc5.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "rc5.h" +#include "misc.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +void RC5::Base::UncheckedSetKey(const byte *k, unsigned int keylen, const NameValuePairs ¶ms) +{ + AssertValidKeyLength(keylen); + + r = GetRoundsAndThrowIfInvalid(params, this); + sTable.New(2*(r+1)); + + static const RC5_WORD MAGIC_P = 0xb7e15163L; // magic constant P for wordsize + static const RC5_WORD MAGIC_Q = 0x9e3779b9L; // magic constant Q for wordsize + static const int U=sizeof(RC5_WORD); + + const unsigned int c = STDMAX((keylen+U-1)/U, 1U); // RC6 paper says c=1 if keylen==0 + SecBlock l(c); + + GetUserKey(LITTLE_ENDIAN_ORDER, l.begin(), c, k, keylen); + + sTable[0] = MAGIC_P; + for (unsigned j=1; j((sTable[h % sTable.size()] + a + b)); + b = l[h % c] = rotlMod((l[h % c] + a + b), (a+b)); + } +} + +typedef BlockGetAndPut Block; + +void RC5::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + const RC5_WORD *sptr = sTable; + RC5_WORD a, b; + + Block::Get(inBlock)(a)(b); + a += sptr[0]; + b += sptr[1]; + sptr += 2; + + for(unsigned i=0; i, 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/external/ours/library/crypto/src/shared/original/rc6.cpp b/external/ours/library/crypto/src/shared/original/rc6.cpp new file mode 100755 index 000000000..a03c51081 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rc6.cpp @@ -0,0 +1,96 @@ +// rc6.cpp - written and placed in the public domain by Sean Woods +// based on Wei Dai's RC5 code. + +#include "pch.h" +#include "rc6.h" +#include "misc.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +void RC6::Base::UncheckedSetKey(const byte *k, unsigned int keylen, const NameValuePairs ¶ms) +{ + AssertValidKeyLength(keylen); + + r = GetRoundsAndThrowIfInvalid(params, this); + sTable.New(2*(r+2)); + + static const RC6_WORD MAGIC_P = 0xb7e15163L; // magic constant P for wordsize + static const RC6_WORD MAGIC_Q = 0x9e3779b9L; // magic constant Q for wordsize + static const int U=sizeof(RC6_WORD); + + const unsigned int c = STDMAX((keylen+U-1)/U, 1U); // RC6 paper says c=1 if keylen==0 + SecBlock l(c); + + GetUserKey(LITTLE_ENDIAN_ORDER, l.begin(), c, k, keylen); + + sTable[0] = MAGIC_P; + for (unsigned j=1; j((sTable[h % sTable.size()] + a + b)); + b = l[h % c] = rotlMod((l[h % c] + a + b), (a+b)); + } +} + +typedef BlockGetAndPut Block; + +void RC6::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + const RC6_WORD *sptr = sTable; + RC6_WORD a, b, c, d, t, u; + + Block::Get(inBlock)(a)(b)(c)(d); + b += sptr[0]; + d += sptr[1]; + sptr += 2; + + for(unsigned i=0; i(b*(2*b+1)); + u = rotlConstant<5>(d*(2*d+1)); + a = rotlMod(a^t,u) + sptr[0]; + c = rotlMod(c^u,t) + sptr[1]; + t = a; a = b; b = c; c = d; d = t; + sptr += 2; + } + + a += sptr[0]; + c += sptr[1]; + + Block::Put(xorBlock, outBlock)(a)(b)(c)(d); +} + +void RC6::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + const RC6_WORD *sptr = sTable.end(); + RC6_WORD a, b, c, d, t, u; + + Block::Get(inBlock)(a)(b)(c)(d); + + sptr -= 2; + c -= sptr[1]; + a -= sptr[0]; + + for (unsigned i=0; i < r; i++) + { + sptr -= 2; + t = a; a = d; d = c; c = b; b = t; + u = rotlConstant<5>(d*(2 * d + 1)); + t = rotlConstant<5>(b*(2 * b + 1)); + c = rotrMod(c-sptr[1], t) ^ u; + a = rotrMod(a-sptr[0], u) ^ t; + } + + d -= sTable[1]; + b -= sTable[0]; + + Block::Put(xorBlock, outBlock)(a)(b)(c)(d); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/rc6.h b/external/ours/library/crypto/src/shared/original/rc6.h new file mode 100755 index 000000000..1a41ab2c4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/rdrand.cpp b/external/ours/library/crypto/src/shared/original/rdrand.cpp new file mode 100755 index 000000000..f8ebe82bb --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rdrand.cpp @@ -0,0 +1,327 @@ +// rdrand.cpp - written and placed in public domain by Jeffrey Walton and Uri Blumenthal. + +#include "pch.h" +#include "config.h" +#include "cryptlib.h" +#include "secblock.h" +#include "rdrand.h" +#include "cpu.h" + +// This file (and friends) 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 throws "NotImplemented". Users of the +// classes should call HasRDRAND() or HasRDSEED() to determine if a +// generator is available at runtime. +// The original classes accepted a retry count. Retries were superflous 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. +// Intel recommends using a retry count in case RDRAND or RDSEED circuit +// is bad. This implemenation does not follow the advice and requires +// good silicon. If the circuit or processor is bad then the user has +// bigger problems than generating random numbers. + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4702) +#endif + +#if defined(CRYPTOPP_RDRAND_AVAILABLE) +# if defined(CRYPTOPP_MSC_VERSION) +# define MASM_RDRAND_ASM_AVAILABLE 1 +# endif +# if (__SUNPRO_CC >= 0x5100) || (CRYPTOPP_APPLE_CLANG_VERSION >= 30000) || \ + (CRYPTOPP_LLVM_CLANG_VERSION >= 20800) || (CRYPTOPP_GCC_VERSION >= 30200) +# define GCC_RDRAND_ASM_AVAILABLE 1 +# endif +#endif // CRYPTOPP_RDRAND_AVAILABLE + +#if defined(CRYPTOPP_RDSEED_AVAILABLE) +# if defined(CRYPTOPP_MSC_VERSION) +# define MASM_RDSEED_ASM_AVAILABLE 1 +# endif +# if (__SUNPRO_CC >= 0x5100) || (CRYPTOPP_APPLE_CLANG_VERSION >= 30000) || \ + (CRYPTOPP_LLVM_CLANG_VERSION >= 20800) || (CRYPTOPP_GCC_VERSION >= 30200) +# define GCC_RDSEED_ASM_AVAILABLE 1 +# endif +#endif // CRYPTOPP_RDSEED_AVAILABLE + +typedef unsigned char byte; + +#if MASM_RDRAND_ASM_AVAILABLE +extern "C" void CRYPTOPP_FASTCALL MASM_RDRAND_GenerateBlock(byte*, size_t); +#endif + +#if MASM_RDSEED_ASM_AVAILABLE +extern "C" void CRYPTOPP_FASTCALL MASM_RDSEED_GenerateBlock(byte*, size_t); +#endif + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_RDRAND_AVAILABLE) + +// Fills 4 bytes +inline void RDRAND32(void* output) +{ + CRYPTOPP_UNUSED(output); // MSC warning +# if defined(GCC_RDRAND_ASM_AVAILABLE) + __asm__ __volatile__ + ( + "1:\n" + ".byte 0x0f, 0xc7, 0xf0;\n" + "jnc 1b;\n" + : "=a" (*reinterpret_cast(output)) + : : "cc" + ); +# endif +} + +# if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32) +// Fills 8 bytes +inline void RDRAND64(void* output) +{ + CRYPTOPP_UNUSED(output); // MSC warning +# if defined(GCC_RDRAND_ASM_AVAILABLE) + __asm__ __volatile__ + ( + "1:\n" + ".byte 0x48, 0x0f, 0xc7, 0xf0;\n" + "jnc 1b;\n" + : "=a" (*reinterpret_cast(output)) + : : "cc" + ); +# endif +} +# endif // RDRAND64 + +RDRAND::RDRAND() +{ + if (!HasRDRAND()) + throw RDRAND_Err("HasRDRAND"); +} + +void RDRAND::GenerateBlock(byte *output, size_t size) +{ + CRYPTOPP_ASSERT((output && size) || !(output || size)); + if (size == 0) return; + +# if defined(MASM_RDRAND_ASM_AVAILABLE) + + MASM_RDRAND_GenerateBlock(output, size); + +# elif defined(GCC_RDRAND_ASM_AVAILABLE) + +# if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32) + size_t i = 0; + for (i = 0; i < size/8; i++) + RDRAND64(output+i*8); + + output += i*8; + size -= i*8; + + if (size) + { + word64 val; + RDRAND64(&val); + std::memcpy(output, &val, size); + } +# else + size_t i = 0; + for (i = 0; i < size/4; i++) + RDRAND32(output+i*4); + + output += i*4; + size -= i*4; + + if (size) + { + word32 val; + RDRAND32(&val); + std::memcpy(output, &val, size); + } +# endif +# else + // No suitable compiler found + CRYPTOPP_UNUSED(output); + throw NotImplemented("RDRAND: failed to find a suitable implementation"); +# endif +} + +void RDRAND::DiscardBytes(size_t n) +{ + // RoundUpToMultipleOf is used because a full word is read, and its cheaper + // to discard full words. There's no sense in dealing with tail bytes. + FixedSizeSecBlock discard; + n = RoundUpToMultipleOf(n, sizeof(word64)); + + size_t count = STDMIN(n, discard.SizeInBytes()); + while (count) + { + GenerateBlock(discard.BytePtr(), count); + n -= count; + count = STDMIN(n, discard.SizeInBytes()); + } +} + +#endif // CRYPTOPP_RDRAND_AVAILABLE + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// + +#if defined(CRYPTOPP_RDSEED_AVAILABLE) + +// Fills 4 bytes +inline void RDSEED32(void* output) +{ + CRYPTOPP_UNUSED(output); // MSC warning +# if defined(GCC_RDSEED_ASM_AVAILABLE) + __asm__ __volatile__ + ( + "1:\n" + ".byte 0x0f, 0xc7, 0xf8;\n" + "jnc 1b;\n" + : "=a" (*reinterpret_cast(output)) + : : "cc" + ); +# endif +} + +# if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32) +// Fills 8 bytes +inline void RDSEED64(void* output) +{ + CRYPTOPP_UNUSED(output); // MSC warning +# if defined(GCC_RDSEED_ASM_AVAILABLE) + __asm__ __volatile__ + ( + "1:\n" + ".byte 0x48, 0x0f, 0xc7, 0xf8;\n" + "jnc 1b;\n" + : "=a" (*reinterpret_cast(output)) + : : "cc" + ); +# endif +} +# endif // RDSEED64 + +RDSEED::RDSEED() +{ + if (!HasRDSEED()) + throw RDSEED_Err("HasRDSEED"); +} + +void RDSEED::GenerateBlock(byte *output, size_t size) +{ + CRYPTOPP_ASSERT((output && size) || !(output || size)); + if (size == 0) return; + +# if defined(MASM_RDSEED_ASM_AVAILABLE) + + MASM_RDSEED_GenerateBlock(output, size); + +# elif defined(GCC_RDSEED_ASM_AVAILABLE) +# if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32) + size_t i = 0; + for (i = 0; i < size/8; i++) + RDSEED64(output+i*8); + + output += i*8; + size -= i*8; + + if (size) + { + word64 val; + RDSEED64(&val); + std::memcpy(output, &val, size); + } +# else + size_t i = 0; + for (i = 0; i < size/4; i++) + RDSEED32(output+i*4); + + output += i*4; + size -= i*4; + + if (size) + { + word32 val; + RDSEED32(&val); + std::memcpy(output, &val, size); + } +# endif +# else + // No suitable compiler found + CRYPTOPP_UNUSED(output); + throw NotImplemented("RDSEED: failed to find a suitable implementation"); +# endif // RDSEED64 +} + +void RDSEED::DiscardBytes(size_t n) +{ + // RoundUpToMultipleOf is used because a full word is read, and its cheaper + // to discard full words. There's no sense in dealing with tail bytes. + FixedSizeSecBlock discard; + n = RoundUpToMultipleOf(n, sizeof(word64)); + + size_t count = STDMIN(n, discard.SizeInBytes()); + while (count) + { + GenerateBlock(discard.BytePtr(), count); + n -= count; + count = STDMIN(n, discard.SizeInBytes()); + } +} + +#endif // CRYPTOPP_RDSEED_AVAILABLE + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// + +#if !defined(CRYPTOPP_RDRAND_AVAILABLE) + +RDRAND::RDRAND() +{ + throw RDRAND_Err("HasRDRAND"); +} + +void RDRAND::GenerateBlock(byte *output, size_t size) +{ + // Constructor will throw, should not get here + CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(size); +} + +void RDRAND::DiscardBytes(size_t n) +{ + // Constructor will throw, should not get here + CRYPTOPP_UNUSED(n); +} + +#endif // CRYPTOPP_RDRAND_AVAILABLE + +#if !defined(CRYPTOPP_RDSEED_AVAILABLE) + +RDSEED::RDSEED() +{ + throw RDSEED_Err("HasRDSEED"); +} + +void RDSEED::GenerateBlock(byte *output, size_t size) +{ + // Constructor will throw, should not get here + CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(size); +} + +void RDSEED::DiscardBytes(size_t n) +{ + // Constructor will throw, should not get here + CRYPTOPP_UNUSED(n); +} + +#endif // CRYPTOPP_RDSEED_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/rdrand.h b/external/ours/library/crypto/src/shared/original/rdrand.h new file mode 100755 index 000000000..11d29ca99 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 superflous 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 generaton 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/external/ours/library/crypto/src/shared/original/rdtables.cpp b/external/ours/library/crypto/src/shared/original/rdtables.cpp new file mode 100755 index 000000000..8ceb800f1 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rdtables.cpp @@ -0,0 +1,166 @@ +// Rijndael tables + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "rijndael.h" + +NAMESPACE_BEGIN(CryptoPP) + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +*/ + +const byte Rijndael::Base::Se[256] = { + 0x63, 0x7c, 0x77, 0x7b, + 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, + 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, + 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, + 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, + 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, + 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, + 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, + 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, + 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, + 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, + 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, + 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, + 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, + 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, + 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, + 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, + 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, + 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, + 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, + 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, + 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16, +}; + +const byte Rijndael::Base::Sd[256] = { + 0x52, 0x09, 0x6a, 0xd5, + 0x30, 0x36, 0xa5, 0x38, + 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, + 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, + 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, + 0xee, 0x4c, 0x95, 0x0b, + 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, + 0x28, 0xd9, 0x24, 0xb2, + 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, + 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, + 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, + 0x5e, 0x15, 0x46, 0x57, + 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, + 0x8c, 0xbc, 0xd3, 0x0a, + 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, + 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, + 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, + 0x97, 0xf2, 0xcf, 0xce, + 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, + 0xe7, 0xad, 0x35, 0x85, + 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, + 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, + 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, + 0x9a, 0xdb, 0xc0, 0xfe, + 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, + 0x88, 0x07, 0xc7, 0x31, + 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, + 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, + 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, + 0xc8, 0xeb, 0xbb, 0x3c, + 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, + 0xba, 0x77, 0xd6, 0x26, + 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d, +}; + +/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +const word32 Rijndael::Base::rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000 +}; + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/regtest1.cpp b/external/ours/library/crypto/src/shared/original/regtest1.cpp new file mode 100755 index 000000000..4e71b68c9 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/regtest1.cpp @@ -0,0 +1,160 @@ +// regtest1.cpp - originally written and placed in the public domain by Wei Dai +// regtest.cpp split into 3 files due to OOM kills by JW +// in April 2017. A second split occurred in July 2018. + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "factory.h" +#include "bench.h" +#include "cpu.h" + +#include "crc.h" +#include "adler32.h" +#include "md2.h" +#include "md5.h" +#include "keccak.h" +#include "sha3.h" +#include "shake.h" +#include "blake2.h" +#include "sha.h" +#include "sha3.h" +#include "sm3.h" +#include "hkdf.h" +#include "tiger.h" +#include "ripemd.h" +#include "panama.h" +#include "whrlpool.h" +#include "lsh.h" + +#include "osrng.h" +#include "drbg.h" +#include "darn.h" +#include "mersenne.h" +#include "rdrand.h" +#include "padlkrng.h" + +#include "modes.h" +#include "aes.h" + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +USING_NAMESPACE(CryptoPP) + +// Unkeyed ciphers +void RegisterFactories1(); +// MAC ciphers +void RegisterFactories2(); +// Stream ciphers +void RegisterFactories3(); +// Block ciphers +void RegisterFactories4(); +// Public key ciphers +void RegisterFactories5(); + +void RegisterFactories(Test::TestClass suites) +{ + static bool s_registered = false; + if (s_registered) + return; + + if ((suites & Test::Unkeyed) == Test::Unkeyed) + RegisterFactories1(); + + if ((suites & Test::SharedKeyMAC) == Test::SharedKeyMAC) + RegisterFactories2(); + + if ((suites & Test::SharedKeyStream) == Test::SharedKeyStream) + RegisterFactories3(); + + if ((suites & Test::SharedKeyBlock) == Test::SharedKeyBlock) + RegisterFactories4(); + + if ((suites & Test::PublicKey) == Test::PublicKey) + RegisterFactories5(); + + s_registered = true; +} + +// Unkeyed ciphers +void RegisterFactories1() +{ + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + +#ifdef BLOCKING_RNG_AVAILABLE + RegisterDefaultFactoryFor(); +#endif +#ifdef NONBLOCKING_RNG_AVAILABLE + RegisterDefaultFactoryFor(); +#endif +#ifdef OS_RNG_AVAILABLE + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor >(); +#endif + RegisterDefaultFactoryFor(); +#if (CRYPTOPP_BOOL_X86) + if (HasPadlockRNG()) + RegisterDefaultFactoryFor(); +#endif +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + if (HasRDRAND()) + RegisterDefaultFactoryFor(); + if (HasRDSEED()) + RegisterDefaultFactoryFor(); +#endif +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) + if (HasDARN()) + RegisterDefaultFactoryFor(); +#endif + RegisterDefaultFactoryFor::Encryption >("AES/OFB RNG"); + RegisterDefaultFactoryFor >("Hash_DRBG(SHA1)"); + RegisterDefaultFactoryFor >("Hash_DRBG(SHA256)"); + RegisterDefaultFactoryFor >("HMAC_DRBG(SHA1)"); + RegisterDefaultFactoryFor >("HMAC_DRBG(SHA256)"); + + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); +} diff --git a/external/ours/library/crypto/src/shared/original/regtest2.cpp b/external/ours/library/crypto/src/shared/original/regtest2.cpp new file mode 100755 index 000000000..e379432dc --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/regtest2.cpp @@ -0,0 +1,105 @@ +// regtest2.cpp - originally written and placed in the public domain by Wei Dai +// regtest.cpp split into 3 files due to OOM kills by JW +// in April 2017. A second split occurred in July 2018. + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "factory.h" +#include "bench.h" +#include "cpu.h" + +// For MAC's +#include "hmac.h" +#include "cmac.h" +#include "dmac.h" +#include "vmac.h" +#include "ttmac.h" + +// Ciphers +#include "md5.h" +#include "keccak.h" +#include "sha.h" +#include "sha3.h" +#include "blake2.h" +#include "ripemd.h" +#include "chacha.h" +#include "poly1305.h" +#include "siphash.h" +#include "panama.h" + +// Stream ciphers +#include "arc4.h" +#include "seal.h" +#include "wake.h" +#include "chacha.h" +#include "salsa.h" +#include "rabbit.h" +#include "hc128.h" +#include "hc256.h" +#include "panama.h" +#include "sosemanuk.h" + +// Block for CMAC +#include "aes.h" +#include "des.h" + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +USING_NAMESPACE(CryptoPP) + +// MAC ciphers +void RegisterFactories2() +{ + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor >(); + RegisterDefaultFactoryFor >(); +} + +// Stream ciphers +void RegisterFactories3() +{ + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); +} diff --git a/external/ours/library/crypto/src/shared/original/regtest3.cpp b/external/ours/library/crypto/src/shared/original/regtest3.cpp new file mode 100755 index 000000000..0d2f6fdca --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/regtest3.cpp @@ -0,0 +1,156 @@ +// regtest3.cpp - originally written and placed in the public domain by Wei Dai +// regtest.cpp split into 3 files due to OOM kills by JW +// in April 2017. A second split occurred in July 2018. + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "factory.h" +#include "bench.h" +#include "cpu.h" + +#include "modes.h" +#include "aria.h" +#include "seed.h" +#include "hight.h" +#include "camellia.h" +#include "shacal2.h" +#include "tea.h" +#include "aes.h" +#include "tiger.h" +#include "ccm.h" +#include "gcm.h" +#include "eax.h" +#include "xts.h" +#include "twofish.h" +#include "serpent.h" +#include "cast.h" +#include "rc6.h" +#include "mars.h" +#include "kalyna.h" +#include "threefish.h" +#include "cham.h" +#include "lea.h" +#include "simeck.h" +#include "simon.h" +#include "speck.h" +#include "sm4.h" +#include "des.h" +#include "idea.h" +#include "rc5.h" +#include "skipjack.h" +#include "blowfish.h" +#include "chachapoly.h" + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +USING_NAMESPACE(CryptoPP) + +// Shared key ciphers +void RegisterFactories4() +{ + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + + RegisterAuthenticatedSymmetricCipherDefaultFactories >(); + RegisterAuthenticatedSymmetricCipherDefaultFactories >(); + RegisterAuthenticatedSymmetricCipherDefaultFactories >(); + RegisterAuthenticatedSymmetricCipherDefaultFactories(); + RegisterAuthenticatedSymmetricCipherDefaultFactories(); + + RegisterSymmetricCipherDefaultFactories >(); // For test vectors + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + RegisterSymmetricCipherDefaultFactories >(); + + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks +} diff --git a/external/ours/library/crypto/src/shared/original/regtest4.cpp b/external/ours/library/crypto/src/shared/original/regtest4.cpp new file mode 100755 index 000000000..f45320839 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/regtest4.cpp @@ -0,0 +1,58 @@ +// regtest4.cpp - originally written and placed in the public domain by Wei Dai +// regtest.cpp split into 3 files due to OOM kills by JW +// in April 2017. A second split occurred in July 2018. + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "factory.h" +#include "bench.h" +#include "cpu.h" + +#include "dh.h" +#include "nr.h" +#include "rw.h" +#include "rsa.h" +#include "dsa.h" +#include "pssr.h" +#include "esign.h" + +// Hashes +#include "md2.h" +#include "md5.h" +#include "sha.h" + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +USING_NAMESPACE(CryptoPP) + +void RegisterFactories5() +{ + RegisterDefaultFactoryFor(); + RegisterAsymmetricCipherDefaultFactories > >("RSA/OAEP-MGF1(SHA-1)"); + RegisterAsymmetricCipherDefaultFactories >("DLIES(NoCofactorMultiplication, KDF2(SHA-1), XOR, HMAC(SHA-1), DHAES)"); + RegisterSignatureSchemeDefaultFactories(); + RegisterSignatureSchemeDefaultFactories >(); + RegisterSignatureSchemeDefaultFactories >(); + RegisterSignatureSchemeDefaultFactories >(); + RegisterSignatureSchemeDefaultFactories >(); + RegisterSignatureSchemeDefaultFactories >(); + RegisterSignatureSchemeDefaultFactories >(); + RegisterSignatureSchemeDefaultFactories >(); + RegisterSignatureSchemeDefaultFactories >(); + RegisterSignatureSchemeDefaultFactories >(); + RegisterSignatureSchemeDefaultFactories >("NR(1363)/EMSA1(SHA-1)"); + RegisterSignatureSchemeDefaultFactories >("DSA-1363/EMSA1(SHA-1)"); + RegisterSignatureSchemeDefaultFactories >("RSA/PKCS1-1.5(MD2)"); + RegisterSignatureSchemeDefaultFactories >("RSA/PKCS1-1.5(SHA-1)"); + RegisterSignatureSchemeDefaultFactories >("ESIGN/EMSA5-MGF1(SHA-1)"); + RegisterSignatureSchemeDefaultFactories >("RW/EMSA2(SHA-1)"); + RegisterSignatureSchemeDefaultFactories >("RSA/PSS-MGF1(SHA-1)"); +} diff --git a/external/ours/library/crypto/src/shared/original/resource.h b/external/ours/library/crypto/src/shared/original/resource.h new file mode 100755 index 000000000..80f1df1a3 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/rijndael.cpp b/external/ours/library/crypto/src/shared/original/rijndael.cpp new file mode 100755 index 000000000..65f6d9e0a --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rijndael.cpp @@ -0,0 +1,1334 @@ +// rijndael.cpp - modified by Chris Morgan +// and Wei Dai from Paulo Baretto's Rijndael implementation +// The original code and all modifications are in the public domain. + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM rijndael.cpp" to generate MASM code + +/* +July 2018: Added support for ARMv7 AES instructions via Cryptogams ASM. + See the head notes in aes_armv4.S for copyright and license. +*/ + +/* +September 2017: Added support for Power8 AES instructions via compiler intrinsics. +*/ + +/* +July 2017: Added support for ARMv8 AES instructions via compiler intrinsics. +*/ + +/* +July 2010: Added support for AES-NI instructions via compiler intrinsics. +*/ + +/* +Feb 2009: The x86/x64 assembly code was rewritten in by Wei Dai to do counter mode +caching, which was invented by Hongjun Wu and popularized by Daniel J. Bernstein +and Peter Schwabe in their paper "New AES software speed records". The round +function was also modified to include a trick similar to one in Brian Gladman's +x86 assembly code, doing an 8-bit register move to minimize the number of +register spills. Also switched to compressed tables and copying round keys to +the stack. + +The C++ implementation uses compressed tables if +CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS is defined. +It is defined on x86 platforms by default but no others. +*/ + +/* +July 2006: Defense against timing attacks was added in by Wei Dai. + +The code now uses smaller tables in the first and last rounds, +and preloads them into L1 cache before usage (by loading at least +one element in each cache line). + +We try to delay subsequent accesses to each table (used in the first +and last rounds) until all of the table has been preloaded. Hopefully +the compiler isn't smart enough to optimize that code away. + +After preloading the table, we also try not to access any memory location +other than the table and the stack, in order to prevent table entries from +being unloaded from L1 cache, until that round is finished. +(Some popular CPUs have 2-way associative caches.) +*/ + +// This is the original introductory comment: + +/** + * version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * author Vincent Rijmen + * author Antoon Bosselaers + * author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_IMPORTS +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#include "rijndael.h" +#include "misc.h" +#include "cpu.h" + +// VS2017 and global optimization bug. TODO, figure out when +// we can re-enable full optimizations for VS2017. Also see +// https://github.com/weidai11/cryptopp/issues/649 +#if (_MSC_VER >= 1910) +# ifndef CRYPTOPP_DEBUG +# pragma optimize("", off) +# pragma optimize("ts", on) +# endif +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// Hack for http://github.com/weidai11/cryptopp/issues/42 and http://github.com/weidai11/cryptopp/issues/132 +#if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) +# define CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS 1 +#endif + +// Clang intrinsic casts +#define M128I_CAST(x) ((__m128i *)(void *)(x)) +#define CONST_M128I_CAST(x) ((const __m128i *)(const void *)(x)) + +#if defined(CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS) +# if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_RIJNDAEL_ASM) +namespace rdtable {CRYPTOPP_ALIGN_DATA(16) word64 Te[256+2];} +using namespace rdtable; +# else +static word64 Te[256]; +# endif +static word64 Td[256]; +#else // Not CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS +# if defined(CRYPTOPP_X64_MASM_AVAILABLE) +// Unused; avoids linker error on Microsoft X64 non-AESNI platforms +namespace rdtable {CRYPTOPP_ALIGN_DATA(16) word64 Te[256+2];} +# endif +CRYPTOPP_ALIGN_DATA(16) static word32 Te[256*4]; +CRYPTOPP_ALIGN_DATA(16) static word32 Td[256*4]; +#endif // CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS + +static volatile bool s_TeFilled = false, s_TdFilled = false; + +ANONYMOUS_NAMESPACE_BEGIN + +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 + +// Determine whether the range between begin and end overlaps +// with the same 4k block offsets as the Te table. Logically, +// the code is trying to create the condition: +// +// Two sepearate memory pages: +// +// +-----+ +-----+ +// |XXXXX| |YYYYY| +// |XXXXX| |YYYYY| +// | | | | +// | | | | +// +-----+ +-----+ +// Te Table Locals +// +// Have a logical cache view of (X and Y may be inverted): +// +// +-----+ +// |XXXXX| +// |XXXXX| +// |YYYYY| +// |YYYYY| +// +-----+ +// +static inline bool AliasedWithTable(const byte *begin, const byte *end) +{ + ptrdiff_t s0 = uintptr_t(begin)%4096, s1 = uintptr_t(end)%4096; + ptrdiff_t t0 = uintptr_t(Te)%4096, t1 = (uintptr_t(Te)+sizeof(Te))%4096; + if (t1 > t0) + return (s0 >= t0 && s0 < t1) || (s1 > t0 && s1 <= t1); + else + return (s0 < t1 || s1 <= t1) || (s0 >= t0 || s1 > t0); +} + +struct Locals +{ + word32 subkeys[4*12], workspace[8]; + const byte *inBlocks, *inXorBlocks, *outXorBlocks; + byte *outBlocks; + size_t inIncrement, inXorIncrement, outXorIncrement, outIncrement; + size_t regSpill, lengthAndCounterFlag, keysBegin; +}; + +const size_t s_aliasPageSize = 4096; +const size_t s_aliasBlockSize = 256; +const size_t s_sizeToAllocate = s_aliasPageSize + s_aliasBlockSize + sizeof(Locals); + +#endif // CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 + +ANONYMOUS_NAMESPACE_END + +// ************************* Portable Code ************************************ + +#define QUARTER_ROUND(L, T, t, a, b, c, d) \ + a ^= L(T, 3, byte(t)); t >>= 8;\ + b ^= L(T, 2, byte(t)); t >>= 8;\ + c ^= L(T, 1, byte(t)); t >>= 8;\ + d ^= L(T, 0, t); + +#define QUARTER_ROUND_LE(t, a, b, c, d) \ + tempBlock[a] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\ + tempBlock[b] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\ + tempBlock[c] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\ + tempBlock[d] = ((byte *)(Te+t))[1]; + +#if defined(CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS) + #define QUARTER_ROUND_LD(t, a, b, c, d) \ + tempBlock[a] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\ + tempBlock[b] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\ + tempBlock[c] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\ + tempBlock[d] = ((byte *)(Td+t))[GetNativeByteOrder()*7]; +#else + #define QUARTER_ROUND_LD(t, a, b, c, d) \ + tempBlock[a] = Sd[byte(t)]; t >>= 8;\ + tempBlock[b] = Sd[byte(t)]; t >>= 8;\ + tempBlock[c] = Sd[byte(t)]; t >>= 8;\ + tempBlock[d] = Sd[t]; +#endif + +#define QUARTER_ROUND_E(t, a, b, c, d) QUARTER_ROUND(TL_M, Te, t, a, b, c, d) +#define QUARTER_ROUND_D(t, a, b, c, d) QUARTER_ROUND(TL_M, Td, t, a, b, c, d) + +#if (CRYPTOPP_LITTLE_ENDIAN) + #define QUARTER_ROUND_FE(t, a, b, c, d) QUARTER_ROUND(TL_F, Te, t, d, c, b, a) + #define QUARTER_ROUND_FD(t, a, b, c, d) QUARTER_ROUND(TL_F, Td, t, d, c, b, a) + #if defined(CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS) + #define TL_F(T, i, x) (*(word32 *)(void *)((byte *)T + x*8 + (6-i)%4+1)) + #define TL_M(T, i, x) (*(word32 *)(void *)((byte *)T + x*8 + (i+3)%4+1)) + #else + #define TL_F(T, i, x) rotrFixed(T[x], (3-i)*8) + #define TL_M(T, i, x) T[i*256 + x] + #endif +#else + #define QUARTER_ROUND_FE(t, a, b, c, d) QUARTER_ROUND(TL_F, Te, t, a, b, c, d) + #define QUARTER_ROUND_FD(t, a, b, c, d) QUARTER_ROUND(TL_F, Td, t, a, b, c, d) + #if defined(CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS) + #define TL_F(T, i, x) (*(word32 *)(void *)((byte *)T + x*8 + (4-i)%4)) + #define TL_M TL_F + #else + #define TL_F(T, i, x) rotrFixed(T[x], i*8) + #define TL_M(T, i, x) T[i*256 + x] + #endif +#endif + + +#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b)) +#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b)) +#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b)) + +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +unsigned int Rijndael::Base::OptimalDataAlignment() const +{ +#if (CRYPTOPP_AESNI_AVAILABLE) + if (HasAESNI()) + return 16; // load __m128i +#endif +#if (CRYPTOPP_ARM_AES_AVAILABLE) + if (HasAES()) + return 4; // load uint32x4_t +#endif +#if (CRYPTOGAMS_ARM_AES) + // Must use 1 here for Cryptogams AES. Also see + // https://github.com/weidai11/cryptopp/issues/683 + if (HasARMv7()) + return 1; +#endif +#if (CRYPTOPP_POWER8_AES_AVAILABLE) + if (HasAES()) + return 16; // load uint32x4_p +#endif + return BlockTransformation::OptimalDataAlignment(); +} + +void Rijndael::Base::FillEncTable() +{ + for (int i=0; i<256; i++) + { + byte x = Se[i]; +#if defined(CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS) + word32 y = word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24; + Te[i] = word64(y | f3(x))<<32 | y; +#else + word32 y = f3(x) | word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24; + for (int j=0; j<4; j++) + { + Te[i+j*256] = y; + y = rotrConstant<8>(y); + } +#endif + } +#if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_RIJNDAEL_ASM) + Te[256] = Te[257] = 0; +#endif + s_TeFilled = true; +} + +void Rijndael::Base::FillDecTable() +{ + for (int i=0; i<256; i++) + { + byte x = Sd[i]; +#if defined(CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS) + word32 y = word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24; + Td[i] = word64(y | fb(x))<<32 | y | x; +#else + word32 y = fb(x) | word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24; + for (int j=0; j<4; j++) + { + Td[i+j*256] = y; + y = rotrConstant<8>(y); + } +#endif + } + s_TdFilled = true; +} + +#if (CRYPTOPP_AESNI_AVAILABLE) +extern void Rijndael_UncheckedSetKey_SSE4_AESNI(const byte *userKey, size_t keyLen, word32* rk); +extern void Rijndael_UncheckedSetKeyRev_AESNI(word32 *key, unsigned int rounds); + +extern size_t Rijndael_Enc_AdvancedProcessBlocks_AESNI(const word32 *subkeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +extern size_t Rijndael_Dec_AdvancedProcessBlocks_AESNI(const word32 *subkeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +#if (CRYPTOPP_ARM_AES_AVAILABLE) +extern size_t Rijndael_Enc_AdvancedProcessBlocks_ARMV8(const word32 *subkeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +extern size_t Rijndael_Dec_AdvancedProcessBlocks_ARMV8(const word32 *subkeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +#if (CRYPTOGAMS_ARM_AES) +extern "C" int cryptogams_AES_set_encrypt_key(const unsigned char *userKey, const int bitLen, word32 *rkey); +extern "C" int cryptogams_AES_set_decrypt_key(const unsigned char *userKey, const int bitLen, word32 *rkey); +extern "C" void cryptogams_AES_encrypt_block(const unsigned char *in, unsigned char *out, const word32 *rkey); +extern "C" void cryptogams_AES_decrypt_block(const unsigned char *in, unsigned char *out, const word32 *rkey); +#endif + +#if (CRYPTOPP_POWER8_AES_AVAILABLE) +extern void Rijndael_UncheckedSetKey_POWER8(const byte* userKey, size_t keyLen, + word32* rk, const byte* Se); + +extern size_t Rijndael_Enc_AdvancedProcessBlocks128_6x1_ALTIVEC(const word32 *subkeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +extern size_t Rijndael_Dec_AdvancedProcessBlocks128_6x1_ALTIVEC(const word32 *subkeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +#if (CRYPTOGAMS_ARM_AES) +int CRYPTOGAMS_set_encrypt_key(const byte *userKey, const int bitLen, word32 *rkey) +{ + return cryptogams_AES_set_encrypt_key(userKey, bitLen, rkey); +} +int CRYPTOGAMS_set_decrypt_key(const byte *userKey, const int bitLen, word32 *rkey) +{ + return cryptogams_AES_set_decrypt_key(userKey, bitLen, rkey); +} +void CRYPTOGAMS_encrypt(const byte *inBlock, const byte *xorBlock, byte *outBlock, const word32 *rkey) +{ + cryptogams_AES_encrypt_block(inBlock, outBlock, rkey); + if (xorBlock) + xorbuf (outBlock, xorBlock, 16); +} +void CRYPTOGAMS_decrypt(const byte *inBlock, const byte *xorBlock, byte *outBlock, const word32 *rkey) +{ + cryptogams_AES_decrypt_block(inBlock, outBlock, rkey); + if (xorBlock) + xorbuf (outBlock, xorBlock, 16); +} +#endif + +std::string Rijndael::Base::AlgorithmProvider() const +{ +#if (CRYPTOPP_AESNI_AVAILABLE) + if (HasAESNI()) + return "AESNI"; +#endif +#if CRYPTOPP_SSE2_ASM_AVAILABLE && !defined(CRYPTOPP_DISABLE_RIJNDAEL_ASM) + if (HasSSE2()) + return "SSE2"; +#endif +#if (CRYPTOPP_ARM_AES_AVAILABLE) + if (HasAES()) + return "ARMv8"; +#endif +#if (CRYPTOGAMS_ARM_AES) + if (HasARMv7()) + return "ARMv7"; +#endif +#if (CRYPTOPP_POWER8_AES_AVAILABLE) + if (HasAES()) + return "Power8"; +#endif + return "C++"; +} + +void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLen, const NameValuePairs &) +{ + AssertValidKeyLength(keyLen); + +#if (CRYPTOGAMS_ARM_AES) + if (HasARMv7()) + { + m_rounds = keyLen/4 + 6; + m_key.New(4*(14+1)+4); + + if (IsForwardTransformation()) + CRYPTOGAMS_set_encrypt_key(userKey, keyLen*8, m_key.begin()); + else + CRYPTOGAMS_set_decrypt_key(userKey, keyLen*8, m_key.begin()); + return; + } +#endif + +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 + m_aliasBlock.New(s_sizeToAllocate); + // The alias block is only used on IA-32 when unaligned data access is in effect. + // Setting the low water mark to 0 avoids zeroization when m_aliasBlock is unused. + m_aliasBlock.SetMark(0); +#endif + + m_rounds = keyLen/4 + 6; + m_key.New(4*(m_rounds+1)); + word32 *rk = m_key; + +#if (CRYPTOPP_AESNI_AVAILABLE && CRYPTOPP_SSE41_AVAILABLE && (!defined(_MSC_VER) || _MSC_VER >= 1600 || CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32)) + // MSVC 2008 SP1 generates bad code for _mm_extract_epi32() when compiling for X64 + if (HasAESNI() && HasSSE41()) + { + // TODO: Add non-SSE4.1 variant for low-end Atoms. The low-end + // Atoms have SSE2-SSSE3 and AES-NI, but not SSE4.1 or SSE4.2. + Rijndael_UncheckedSetKey_SSE4_AESNI(userKey, keyLen, rk); + if (!IsForwardTransformation()) + Rijndael_UncheckedSetKeyRev_AESNI(m_key, m_rounds); + + return; + } +#endif + +#if CRYPTOPP_POWER8_AES_AVAILABLE + if (HasAES()) + { + // We still need rcon and Se to fallback to C/C++ for AES-192 and AES-256. + // The IBM docs on AES sucks. Intel's docs on AESNI puts IBM to shame. + Rijndael_UncheckedSetKey_POWER8(userKey, keyLen, rk, Se); + return; + } +#endif + + GetUserKey(BIG_ENDIAN_ORDER, rk, keyLen/4, userKey, keyLen); + const word32 *rc = rcon; + word32 temp; + + while (true) + { + temp = rk[keyLen/4-1]; + word32 x = (word32(Se[GETBYTE(temp, 2)]) << 24) ^ (word32(Se[GETBYTE(temp, 1)]) << 16) ^ + (word32(Se[GETBYTE(temp, 0)]) << 8) ^ Se[GETBYTE(temp, 3)]; + rk[keyLen/4] = rk[0] ^ x ^ *(rc++); + rk[keyLen/4+1] = rk[1] ^ rk[keyLen/4]; + rk[keyLen/4+2] = rk[2] ^ rk[keyLen/4+1]; + rk[keyLen/4+3] = rk[3] ^ rk[keyLen/4+2]; + + if (rk + keyLen/4 + 4 == m_key.end()) + break; + + if (keyLen == 24) + { + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + } + else if (keyLen == 32) + { + temp = rk[11]; + rk[12] = rk[ 4] ^ (word32(Se[GETBYTE(temp, 3)]) << 24) ^ (word32(Se[GETBYTE(temp, 2)]) << 16) ^ (word32(Se[GETBYTE(temp, 1)]) << 8) ^ Se[GETBYTE(temp, 0)]; + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + } + rk += keyLen/4; + } + + rk = m_key; + + if (IsForwardTransformation()) + { + if (!s_TeFilled) + FillEncTable(); + + ConditionalByteReverse(BIG_ENDIAN_ORDER, rk, rk, 16); + ConditionalByteReverse(BIG_ENDIAN_ORDER, rk + m_rounds*4, rk + m_rounds*4, 16); + } + else + { + if (!s_TdFilled) + FillDecTable(); + + #define InverseMixColumn(x) \ + TL_M(Td, 0, Se[GETBYTE(x, 3)]) ^ TL_M(Td, 1, Se[GETBYTE(x, 2)]) ^ \ + TL_M(Td, 2, Se[GETBYTE(x, 1)]) ^ TL_M(Td, 3, Se[GETBYTE(x, 0)]) + + unsigned int i, j; + for (i = 4, j = 4*m_rounds-4; i < j; i += 4, j -= 4) + { + temp = InverseMixColumn(rk[i ]); rk[i ] = InverseMixColumn(rk[j ]); rk[j ] = temp; + temp = InverseMixColumn(rk[i + 1]); rk[i + 1] = InverseMixColumn(rk[j + 1]); rk[j + 1] = temp; + temp = InverseMixColumn(rk[i + 2]); rk[i + 2] = InverseMixColumn(rk[j + 2]); rk[j + 2] = temp; + temp = InverseMixColumn(rk[i + 3]); rk[i + 3] = InverseMixColumn(rk[j + 3]); rk[j + 3] = temp; + } + + rk[i+0] = InverseMixColumn(rk[i+0]); + rk[i+1] = InverseMixColumn(rk[i+1]); + rk[i+2] = InverseMixColumn(rk[i+2]); + rk[i+3] = InverseMixColumn(rk[i+3]); + + temp = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[0]); rk[0] = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[4*m_rounds+0]); rk[4*m_rounds+0] = temp; + temp = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[1]); rk[1] = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[4*m_rounds+1]); rk[4*m_rounds+1] = temp; + temp = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[2]); rk[2] = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[4*m_rounds+2]); rk[4*m_rounds+2] = temp; + temp = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[3]); rk[3] = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[4*m_rounds+3]); rk[4*m_rounds+3] = temp; + } + +#if CRYPTOPP_AESNI_AVAILABLE + if (HasAESNI()) + ConditionalByteReverse(BIG_ENDIAN_ORDER, rk+4, rk+4, (m_rounds-1)*16); +#endif +#if CRYPTOPP_ARM_AES_AVAILABLE + if (HasAES()) + ConditionalByteReverse(BIG_ENDIAN_ORDER, rk+4, rk+4, (m_rounds-1)*16); +#endif +} + +void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) || CRYPTOPP_AESNI_AVAILABLE +# if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_RIJNDAEL_ASM) + if (HasSSE2()) +# else + if (HasAESNI()) +# endif + { + (void)Rijndael::Enc::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0); + return; + } +#endif + +#if (CRYPTOPP_ARM_AES_AVAILABLE) + if (HasAES()) + { + (void)Rijndael::Enc::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0); + return; + } +#endif + +#if (CRYPTOGAMS_ARM_AES) + if (HasARMv7()) + { + CRYPTOGAMS_encrypt(inBlock, xorBlock, outBlock, m_key.begin()); + return; + } +#endif + +#if (CRYPTOPP_POWER8_AES_AVAILABLE) + if (HasAES()) + { + (void)Rijndael::Enc::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0); + return; + } +#endif + + typedef BlockGetAndPut Block; + + word32 s0, s1, s2, s3, t0, t1, t2, t3; + Block::Get(inBlock)(s0)(s1)(s2)(s3); + + const word32 *rk = m_key; + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + t0 = rk[4]; + t1 = rk[5]; + t2 = rk[6]; + t3 = rk[7]; + rk += 8; + + // timing attack countermeasure. see comments at top for more details. + // also see http://github.com/weidai11/cryptopp/issues/146 + const int cacheLineSize = GetCacheLineSize(); + unsigned int i; + volatile word32 _u = 0; + word32 u = _u; +#if defined(CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS) + for (i=0; i<2048; i+=cacheLineSize) +#else + for (i=0; i<1024; i+=cacheLineSize) +#endif + u &= *(const word32 *)(const void *)(((const byte *)Te)+i); + u &= Te[255]; + s0 |= u; s1 |= u; s2 |= u; s3 |= u; + + QUARTER_ROUND_FE(s3, t0, t1, t2, t3) + QUARTER_ROUND_FE(s2, t3, t0, t1, t2) + QUARTER_ROUND_FE(s1, t2, t3, t0, t1) + QUARTER_ROUND_FE(s0, t1, t2, t3, t0) + + // Nr - 2 full rounds: + unsigned int r = m_rounds/2 - 1; + do + { + s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3]; + + QUARTER_ROUND_E(t3, s0, s1, s2, s3) + QUARTER_ROUND_E(t2, s3, s0, s1, s2) + QUARTER_ROUND_E(t1, s2, s3, s0, s1) + QUARTER_ROUND_E(t0, s1, s2, s3, s0) + + t0 = rk[4]; t1 = rk[5]; t2 = rk[6]; t3 = rk[7]; + + QUARTER_ROUND_E(s3, t0, t1, t2, t3) + QUARTER_ROUND_E(s2, t3, t0, t1, t2) + QUARTER_ROUND_E(s1, t2, t3, t0, t1) + QUARTER_ROUND_E(s0, t1, t2, t3, t0) + + rk += 8; + } while (--r); + + word32 tbw[4]; + byte *const tempBlock = (byte *)tbw; + + QUARTER_ROUND_LE(t2, 15, 2, 5, 8) + QUARTER_ROUND_LE(t1, 11, 14, 1, 4) + QUARTER_ROUND_LE(t0, 7, 10, 13, 0) + QUARTER_ROUND_LE(t3, 3, 6, 9, 12) + + Block::Put(xorBlock, outBlock)(tbw[0]^rk[0])(tbw[1]^rk[1])(tbw[2]^rk[2])(tbw[3]^rk[3]); +} + +void Rijndael::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ +#if CRYPTOPP_AESNI_AVAILABLE + if (HasAESNI()) + { + (void)Rijndael::Dec::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0); + return; + } +#endif + +#if (CRYPTOPP_ARM_AES_AVAILABLE) + if (HasAES()) + { + (void)Rijndael::Dec::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0); + return; + } +#endif + +#if (CRYPTOGAMS_ARM_AES) + if (HasARMv7()) + { + CRYPTOGAMS_decrypt(inBlock, xorBlock, outBlock, m_key.begin()); + return; + } +#endif + +#if (CRYPTOPP_POWER8_AES_AVAILABLE) + if (HasAES()) + { + (void)Rijndael::Dec::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0); + return; + } +#endif + + typedef BlockGetAndPut Block; + + word32 s0, s1, s2, s3, t0, t1, t2, t3; + Block::Get(inBlock)(s0)(s1)(s2)(s3); + + const word32 *rk = m_key; + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + t0 = rk[4]; + t1 = rk[5]; + t2 = rk[6]; + t3 = rk[7]; + rk += 8; + + // timing attack countermeasure. see comments at top for more details. + // also see http://github.com/weidai11/cryptopp/issues/146 + const int cacheLineSize = GetCacheLineSize(); + unsigned int i; + volatile word32 _u = 0; + word32 u = _u; +#if defined(CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS) + for (i=0; i<2048; i+=cacheLineSize) +#else + for (i=0; i<1024; i+=cacheLineSize) +#endif + u &= *(const word32 *)(const void *)(((const byte *)Td)+i); + u &= Td[255]; + s0 |= u; s1 |= u; s2 |= u; s3 |= u; + + QUARTER_ROUND_FD(s3, t2, t1, t0, t3) + QUARTER_ROUND_FD(s2, t1, t0, t3, t2) + QUARTER_ROUND_FD(s1, t0, t3, t2, t1) + QUARTER_ROUND_FD(s0, t3, t2, t1, t0) + + // Nr - 2 full rounds: + unsigned int r = m_rounds/2 - 1; + do + { + s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3]; + + QUARTER_ROUND_D(t3, s2, s1, s0, s3) + QUARTER_ROUND_D(t2, s1, s0, s3, s2) + QUARTER_ROUND_D(t1, s0, s3, s2, s1) + QUARTER_ROUND_D(t0, s3, s2, s1, s0) + + t0 = rk[4]; t1 = rk[5]; t2 = rk[6]; t3 = rk[7]; + + QUARTER_ROUND_D(s3, t2, t1, t0, t3) + QUARTER_ROUND_D(s2, t1, t0, t3, t2) + QUARTER_ROUND_D(s1, t0, t3, t2, t1) + QUARTER_ROUND_D(s0, t3, t2, t1, t0) + + rk += 8; + } while (--r); + +#if !(defined(CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS)) + // timing attack countermeasure. see comments at top for more details + // If CRYPTOPP_ALLOW_RIJNDAEL_UNALIGNED_DATA_ACCESS is defined, + // QUARTER_ROUND_LD will use Td, which is already preloaded. + u = _u; + for (i=0; i<256; i+=cacheLineSize) + u &= *(const word32 *)(const void *)(Sd+i); + u &= *(const word32 *)(const void *)(Sd+252); + t0 |= u; t1 |= u; t2 |= u; t3 |= u; +#endif + + word32 tbw[4]; + byte *const tempBlock = (byte *)tbw; + + QUARTER_ROUND_LD(t2, 7, 2, 13, 8) + QUARTER_ROUND_LD(t1, 3, 14, 9, 4) + QUARTER_ROUND_LD(t0, 15, 10, 5, 0) + QUARTER_ROUND_LD(t3, 11, 6, 1, 12) + + Block::Put(xorBlock, outBlock)(tbw[0]^rk[0])(tbw[1]^rk[1])(tbw[2]^rk[2])(tbw[3]^rk[3]); +} + +// ************************* Assembly Code ************************************ + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code +#endif + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM + +#if CRYPTOPP_SSE2_ASM_AVAILABLE && !defined(CRYPTOPP_DISABLE_RIJNDAEL_ASM) + +CRYPTOPP_NAKED void CRYPTOPP_FASTCALL Rijndael_Enc_AdvancedProcessBlocks_SSE2(void *locals, const word32 *k) +{ + CRYPTOPP_UNUSED(locals); CRYPTOPP_UNUSED(k); + +#if CRYPTOPP_BOOL_X86 + +#define L_REG esp +#define L_INDEX(i) (L_REG+768+i) +#define L_INXORBLOCKS L_INBLOCKS+4 +#define L_OUTXORBLOCKS L_INBLOCKS+8 +#define L_OUTBLOCKS L_INBLOCKS+12 +#define L_INCREMENTS L_INDEX(16*15) +#define L_SP L_INDEX(16*16) +#define L_LENGTH L_INDEX(16*16+4) +#define L_KEYS_BEGIN L_INDEX(16*16+8) + +#define MOVD movd +#define MM(i) mm##i + +#define MXOR(a,b,c) \ + AS2( movzx esi, b)\ + AS2( movd mm7, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + AS2( pxor MM(a), mm7)\ + +#define MMOV(a,b,c) \ + AS2( movzx esi, b)\ + AS2( movd MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#else + +#define L_REG r8 +#define L_INDEX(i) (L_REG+i) +#define L_INXORBLOCKS L_INBLOCKS+8 +#define L_OUTXORBLOCKS L_INBLOCKS+16 +#define L_OUTBLOCKS L_INBLOCKS+24 +#define L_INCREMENTS L_INDEX(16*16) +#define L_LENGTH L_INDEX(16*18+8) +#define L_KEYS_BEGIN L_INDEX(16*19) + +#define MOVD mov +#define MM_0 r9d +#define MM_1 r12d +#ifdef __GNUC__ +#define MM_2 r11d +#else +#define MM_2 r10d +#endif +#define MM(i) MM_##i + +#define MXOR(a,b,c) \ + AS2( movzx esi, b)\ + AS2( xor MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#define MMOV(a,b,c) \ + AS2( movzx esi, b)\ + AS2( mov MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#endif + +#define L_SUBKEYS L_INDEX(0) +#define L_SAVED_X L_SUBKEYS +#define L_KEY12 L_INDEX(16*12) +#define L_LASTROUND L_INDEX(16*13) +#define L_INBLOCKS L_INDEX(16*14) +#define MAP0TO4(i) (ASM_MOD(i+3,4)+1) + +#define XOR(a,b,c) \ + AS2( movzx esi, b)\ + AS2( xor a, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#define MOV(a,b,c) \ + AS2( movzx esi, b)\ + AS2( mov a, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#ifdef CRYPTOPP_GENERATE_X64_MASM + ALIGN 8 + Rijndael_Enc_AdvancedProcessBlocks PROC FRAME + rex_push_reg rsi + push_reg rdi + push_reg rbx + push_reg r12 + .endprolog + mov L_REG, rcx + mov AS_REG_7, ?Te@rdtable@CryptoPP@@3PA_KA + mov edi, DWORD PTR [?g_cacheLineSize@CryptoPP@@3IA] +#elif defined(__GNUC__) + __asm__ __volatile__ + ( + INTEL_NOPREFIX + #if CRYPTOPP_BOOL_X64 + AS2( mov L_REG, rcx) + #endif + AS_PUSH_IF86(bx) + AS_PUSH_IF86(bp) + AS2( mov AS_REG_7, WORD_REG(si)) +#else + AS_PUSH_IF86(si) + AS_PUSH_IF86(di) + AS_PUSH_IF86(bx) + AS_PUSH_IF86(bp) + AS2( lea AS_REG_7, [Te]) + AS2( mov edi, [g_cacheLineSize]) +#endif + +#if CRYPTOPP_BOOL_X86 + AS2( mov [ecx+16*12+16*4], esp) // save esp to L_SP + AS2( lea esp, [ecx-768]) +#endif + + // copy subkeys to stack + AS2( mov WORD_REG(si), [L_KEYS_BEGIN]) + AS2( mov WORD_REG(ax), 16) + AS2( and WORD_REG(ax), WORD_REG(si)) + AS2( movdqa xmm3, XMMWORD_PTR [WORD_REG(dx)+16+WORD_REG(ax)]) // subkey 1 (non-counter) or 2 (counter) + AS2( movdqa [L_KEY12], xmm3) + AS2( lea WORD_REG(ax), [WORD_REG(dx)+WORD_REG(ax)+2*16]) + AS2( sub WORD_REG(ax), WORD_REG(si)) + ASL(0) + AS2( movdqa xmm0, [WORD_REG(ax)+WORD_REG(si)]) + AS2( movdqa XMMWORD_PTR [L_SUBKEYS+WORD_REG(si)], xmm0) + AS2( add WORD_REG(si), 16) + AS2( cmp WORD_REG(si), 16*12) + ATT_NOPREFIX + ASJ( jl, 0, b) + INTEL_NOPREFIX + + // read subkeys 0, 1 and last + AS2( movdqa xmm4, [WORD_REG(ax)+WORD_REG(si)]) // last subkey + AS2( movdqa xmm1, [WORD_REG(dx)]) // subkey 0 + AS2( MOVD MM(1), [WORD_REG(dx)+4*4]) // 0,1,2,3 + AS2( mov ebx, [WORD_REG(dx)+5*4]) // 4,5,6,7 + AS2( mov ecx, [WORD_REG(dx)+6*4]) // 8,9,10,11 + AS2( mov edx, [WORD_REG(dx)+7*4]) // 12,13,14,15 + + // load table into cache + AS2( xor WORD_REG(ax), WORD_REG(ax)) + ASL(9) + AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) + AS2( add WORD_REG(ax), WORD_REG(di)) + AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) + AS2( add WORD_REG(ax), WORD_REG(di)) + AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) + AS2( add WORD_REG(ax), WORD_REG(di)) + AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) + AS2( add WORD_REG(ax), WORD_REG(di)) + AS2( cmp WORD_REG(ax), 2048) + ATT_NOPREFIX + ASJ( jl, 9, b) + INTEL_NOPREFIX + AS1( lfence) + + AS2( test DWORD PTR [L_LENGTH], 1) + ATT_NOPREFIX + ASJ( jz, 8, f) + INTEL_NOPREFIX + + // counter mode one-time setup + AS2( mov WORD_REG(si), [L_INBLOCKS]) + AS2( movdqu xmm2, [WORD_REG(si)]) // counter + AS2( pxor xmm2, xmm1) + AS2( psrldq xmm1, 14) + AS2( movd eax, xmm1) + AS2( mov al, BYTE PTR [WORD_REG(si)+15]) + AS2( MOVD MM(2), eax) +#if CRYPTOPP_BOOL_X86 + AS2( mov eax, 1) + AS2( movd mm3, eax) +#endif + + // partial first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: mm1, ebx, ecx, edx + AS2( movd eax, xmm2) + AS2( psrldq xmm2, 4) + AS2( movd edi, xmm2) + AS2( psrldq xmm2, 4) + MXOR( 1, al, 0) // 0 + XOR( edx, ah, 1) // 1 + AS2( shr eax, 16) + XOR( ecx, al, 2) // 2 + XOR( ebx, ah, 3) // 3 + AS2( mov eax, edi) + AS2( movd edi, xmm2) + AS2( psrldq xmm2, 4) + XOR( ebx, al, 0) // 4 + MXOR( 1, ah, 1) // 5 + AS2( shr eax, 16) + XOR( edx, al, 2) // 6 + XOR( ecx, ah, 3) // 7 + AS2( mov eax, edi) + AS2( movd edi, xmm2) + XOR( ecx, al, 0) // 8 + XOR( ebx, ah, 1) // 9 + AS2( shr eax, 16) + MXOR( 1, al, 2) // 10 + XOR( edx, ah, 3) // 11 + AS2( mov eax, edi) + XOR( edx, al, 0) // 12 + XOR( ecx, ah, 1) // 13 + AS2( shr eax, 16) + XOR( ebx, al, 2) // 14 + AS2( psrldq xmm2, 3) + + // partial second round, in: ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15), out: eax, ebx, edi, mm0 + AS2( mov eax, [L_KEY12+0*4]) + AS2( mov edi, [L_KEY12+2*4]) + AS2( MOVD MM(0), [L_KEY12+3*4]) + MXOR( 0, cl, 3) /* 11 */ + XOR( edi, bl, 3) /* 7 */ + MXOR( 0, bh, 2) /* 6 */ + AS2( shr ebx, 16) /* 4,5 */ + XOR( eax, bl, 1) /* 5 */ + MOV( ebx, bh, 0) /* 4 */ + AS2( xor ebx, [L_KEY12+1*4]) + XOR( eax, ch, 2) /* 10 */ + AS2( shr ecx, 16) /* 8,9 */ + XOR( eax, dl, 3) /* 15 */ + XOR( ebx, dh, 2) /* 14 */ + AS2( shr edx, 16) /* 12,13 */ + XOR( edi, ch, 0) /* 8 */ + XOR( ebx, cl, 1) /* 9 */ + XOR( edi, dl, 1) /* 13 */ + MXOR( 0, dh, 0) /* 12 */ + + AS2( movd ecx, xmm2) + AS2( MOVD edx, MM(1)) + AS2( MOVD [L_SAVED_X+3*4], MM(0)) + AS2( mov [L_SAVED_X+0*4], eax) + AS2( mov [L_SAVED_X+1*4], ebx) + AS2( mov [L_SAVED_X+2*4], edi) + ATT_NOPREFIX + ASJ( jmp, 5, f) + INTEL_NOPREFIX + ASL(3) + // non-counter mode per-block setup + AS2( MOVD MM(1), [L_KEY12+0*4]) // 0,1,2,3 + AS2( mov ebx, [L_KEY12+1*4]) // 4,5,6,7 + AS2( mov ecx, [L_KEY12+2*4]) // 8,9,10,11 + AS2( mov edx, [L_KEY12+3*4]) // 12,13,14,15 + ASL(8) + AS2( mov WORD_REG(ax), [L_INBLOCKS]) + AS2( movdqu xmm2, [WORD_REG(ax)]) + AS2( mov WORD_REG(si), [L_INXORBLOCKS]) + AS2( movdqu xmm5, [WORD_REG(si)]) + AS2( pxor xmm2, xmm1) + AS2( pxor xmm2, xmm5) + + // first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: eax, ebx, ecx, edx + AS2( movd eax, xmm2) + AS2( psrldq xmm2, 4) + AS2( movd edi, xmm2) + AS2( psrldq xmm2, 4) + MXOR( 1, al, 0) // 0 + XOR( edx, ah, 1) // 1 + AS2( shr eax, 16) + XOR( ecx, al, 2) // 2 + XOR( ebx, ah, 3) // 3 + AS2( mov eax, edi) + AS2( movd edi, xmm2) + AS2( psrldq xmm2, 4) + XOR( ebx, al, 0) // 4 + MXOR( 1, ah, 1) // 5 + AS2( shr eax, 16) + XOR( edx, al, 2) // 6 + XOR( ecx, ah, 3) // 7 + AS2( mov eax, edi) + AS2( movd edi, xmm2) + XOR( ecx, al, 0) // 8 + XOR( ebx, ah, 1) // 9 + AS2( shr eax, 16) + MXOR( 1, al, 2) // 10 + XOR( edx, ah, 3) // 11 + AS2( mov eax, edi) + XOR( edx, al, 0) // 12 + XOR( ecx, ah, 1) // 13 + AS2( shr eax, 16) + XOR( ebx, al, 2) // 14 + MXOR( 1, ah, 3) // 15 + AS2( MOVD eax, MM(1)) + + AS2( add L_REG, [L_KEYS_BEGIN]) + AS2( add L_REG, 4*16) + ATT_NOPREFIX + ASJ( jmp, 2, f) + INTEL_NOPREFIX + ASL(1) + // counter-mode per-block setup + AS2( MOVD ecx, MM(2)) + AS2( MOVD edx, MM(1)) + AS2( mov eax, [L_SAVED_X+0*4]) + AS2( mov ebx, [L_SAVED_X+1*4]) + AS2( xor cl, ch) + AS2( and WORD_REG(cx), 255) + ASL(5) +#if CRYPTOPP_BOOL_X86 + AS2( paddb MM(2), mm3) +#else + AS2( add MM(2), 1) +#endif + // remaining part of second round, in: edx(previous round),esi(keyed counter byte) eax,ebx,[L_SAVED_X+2*4],[L_SAVED_X+3*4], out: eax,ebx,ecx,edx + AS2( xor edx, DWORD PTR [AS_REG_7+WORD_REG(cx)*8+3]) + XOR( ebx, dl, 3) + MOV( ecx, dh, 2) + AS2( shr edx, 16) + AS2( xor ecx, [L_SAVED_X+2*4]) + XOR( eax, dh, 0) + MOV( edx, dl, 1) + AS2( xor edx, [L_SAVED_X+3*4]) + + AS2( add L_REG, [L_KEYS_BEGIN]) + AS2( add L_REG, 3*16) + ATT_NOPREFIX + ASJ( jmp, 4, f) + INTEL_NOPREFIX + +// in: eax(0,1,2,3), ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15) +// out: eax, ebx, edi, mm0 +#define ROUND() \ + MXOR( 0, cl, 3) /* 11 */\ + AS2( mov cl, al) /* 8,9,10,3 */\ + XOR( edi, ah, 2) /* 2 */\ + AS2( shr eax, 16) /* 0,1 */\ + XOR( edi, bl, 3) /* 7 */\ + MXOR( 0, bh, 2) /* 6 */\ + AS2( shr ebx, 16) /* 4,5 */\ + MXOR( 0, al, 1) /* 1 */\ + MOV( eax, ah, 0) /* 0 */\ + XOR( eax, bl, 1) /* 5 */\ + MOV( ebx, bh, 0) /* 4 */\ + XOR( eax, ch, 2) /* 10 */\ + XOR( ebx, cl, 3) /* 3 */\ + AS2( shr ecx, 16) /* 8,9 */\ + XOR( eax, dl, 3) /* 15 */\ + XOR( ebx, dh, 2) /* 14 */\ + AS2( shr edx, 16) /* 12,13 */\ + XOR( edi, ch, 0) /* 8 */\ + XOR( ebx, cl, 1) /* 9 */\ + XOR( edi, dl, 1) /* 13 */\ + MXOR( 0, dh, 0) /* 12 */\ + + ASL(2) // 2-round loop + AS2( MOVD MM(0), [L_SUBKEYS-4*16+3*4]) + AS2( mov edi, [L_SUBKEYS-4*16+2*4]) + ROUND() + AS2( mov ecx, edi) + AS2( xor eax, [L_SUBKEYS-4*16+0*4]) + AS2( xor ebx, [L_SUBKEYS-4*16+1*4]) + AS2( MOVD edx, MM(0)) + + ASL(4) + AS2( MOVD MM(0), [L_SUBKEYS-4*16+7*4]) + AS2( mov edi, [L_SUBKEYS-4*16+6*4]) + ROUND() + AS2( mov ecx, edi) + AS2( xor eax, [L_SUBKEYS-4*16+4*4]) + AS2( xor ebx, [L_SUBKEYS-4*16+5*4]) + AS2( MOVD edx, MM(0)) + + AS2( add L_REG, 32) + AS2( test L_REG, 255) + ATT_NOPREFIX + ASJ( jnz, 2, b) + INTEL_NOPREFIX + AS2( sub L_REG, 16*16) + +#define LAST(a, b, c) \ + AS2( movzx esi, a )\ + AS2( movzx edi, BYTE PTR [AS_REG_7+WORD_REG(si)*8+1] )\ + AS2( movzx esi, b )\ + AS2( xor edi, DWORD PTR [AS_REG_7+WORD_REG(si)*8+0] )\ + AS2( mov WORD PTR [L_LASTROUND+c], di )\ + + // last round + LAST(ch, dl, 2) + LAST(dh, al, 6) + AS2( shr edx, 16) + LAST(ah, bl, 10) + AS2( shr eax, 16) + LAST(bh, cl, 14) + AS2( shr ebx, 16) + LAST(dh, al, 12) + AS2( shr ecx, 16) + LAST(ah, bl, 0) + LAST(bh, cl, 4) + LAST(ch, dl, 8) + + AS2( mov WORD_REG(ax), [L_OUTXORBLOCKS]) + AS2( mov WORD_REG(bx), [L_OUTBLOCKS]) + + AS2( mov WORD_REG(cx), [L_LENGTH]) + AS2( sub WORD_REG(cx), 16) + + AS2( movdqu xmm2, [WORD_REG(ax)]) + AS2( pxor xmm2, xmm4) + +#if CRYPTOPP_BOOL_X86 + AS2( movdqa xmm0, [L_INCREMENTS]) + AS2( paddd xmm0, [L_INBLOCKS]) + AS2( movdqa [L_INBLOCKS], xmm0) +#else + AS2( movdqa xmm0, [L_INCREMENTS+16]) + AS2( paddq xmm0, [L_INBLOCKS+16]) + AS2( movdqa [L_INBLOCKS+16], xmm0) +#endif + + AS2( pxor xmm2, [L_LASTROUND]) + AS2( movdqu [WORD_REG(bx)], xmm2) + + ATT_NOPREFIX + ASJ( jle, 7, f) + INTEL_NOPREFIX + AS2( mov [L_LENGTH], WORD_REG(cx)) + AS2( test WORD_REG(cx), 1) + ATT_NOPREFIX + ASJ( jnz, 1, b) + INTEL_NOPREFIX +#if CRYPTOPP_BOOL_X64 + AS2( movdqa xmm0, [L_INCREMENTS]) + AS2( paddq xmm0, [L_INBLOCKS]) + AS2( movdqa [L_INBLOCKS], xmm0) +#endif + ATT_NOPREFIX + ASJ( jmp, 3, b) + INTEL_NOPREFIX + + ASL(7) + // erase keys on stack + AS2( xorps xmm0, xmm0) + AS2( lea WORD_REG(ax), [L_SUBKEYS+7*16]) + AS2( movaps [WORD_REG(ax)-7*16], xmm0) + AS2( movaps [WORD_REG(ax)-6*16], xmm0) + AS2( movaps [WORD_REG(ax)-5*16], xmm0) + AS2( movaps [WORD_REG(ax)-4*16], xmm0) + AS2( movaps [WORD_REG(ax)-3*16], xmm0) + AS2( movaps [WORD_REG(ax)-2*16], xmm0) + AS2( movaps [WORD_REG(ax)-1*16], xmm0) + AS2( movaps [WORD_REG(ax)+0*16], xmm0) + AS2( movaps [WORD_REG(ax)+1*16], xmm0) + AS2( movaps [WORD_REG(ax)+2*16], xmm0) + AS2( movaps [WORD_REG(ax)+3*16], xmm0) + AS2( movaps [WORD_REG(ax)+4*16], xmm0) + AS2( movaps [WORD_REG(ax)+5*16], xmm0) + AS2( movaps [WORD_REG(ax)+6*16], xmm0) +#if CRYPTOPP_BOOL_X86 + AS2( mov esp, [L_SP]) + AS1( emms) +#endif + AS_POP_IF86(bp) + AS_POP_IF86(bx) +#if defined(_MSC_VER) && CRYPTOPP_BOOL_X86 + AS_POP_IF86(di) + AS_POP_IF86(si) + AS1(ret) +#endif +#ifdef CRYPTOPP_GENERATE_X64_MASM + pop r12 + pop rbx + pop rdi + pop rsi + ret + Rijndael_Enc_AdvancedProcessBlocks ENDP +#endif +#ifdef __GNUC__ + ATT_PREFIX + : + : "c" (locals), "d" (k), "S" (Te), "D" (g_cacheLineSize) + : "memory", "cc", "%eax" + #if CRYPTOPP_BOOL_X64 + , "%rbx", "%r8", "%r9", "%r10", "%r11", "%r12" + #endif + ); +#endif +} + +#endif + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void Rijndael_Enc_AdvancedProcessBlocks_SSE2(void *locals, const word32 *k); +} +#endif + +#if CRYPTOPP_RIJNDAEL_ADVANCED_PROCESS_BLOCKS +size_t Rijndael::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const +{ +#if CRYPTOPP_AESNI_AVAILABLE + if (HasAESNI()) + return Rijndael_Enc_AdvancedProcessBlocks_AESNI(m_key, m_rounds, inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if CRYPTOPP_ARM_AES_AVAILABLE + if (HasAES()) + return Rijndael_Enc_AdvancedProcessBlocks_ARMV8(m_key, m_rounds, inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if CRYPTOPP_POWER8_AES_AVAILABLE + if (HasAES()) + return Rijndael_Enc_AdvancedProcessBlocks128_6x1_ALTIVEC(m_key, m_rounds, inBlocks, xorBlocks, outBlocks, length, flags); +#endif + +#if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_RIJNDAEL_ASM) + if (HasSSE2()) + { + if (length < BLOCKSIZE) + return length; + + static const byte *zeros = (const byte*)(Te+256); + m_aliasBlock.SetMark(m_aliasBlock.size()); + byte *space = NULLPTR, *originalSpace = const_cast(m_aliasBlock.data()); + + // round up to nearest 256 byte boundary + space = originalSpace + (s_aliasBlockSize - (uintptr_t)originalSpace % s_aliasBlockSize) % s_aliasBlockSize; + while (AliasedWithTable(space, space + sizeof(Locals))) + { + space += 256; + CRYPTOPP_ASSERT(space < (originalSpace + s_aliasPageSize)); + } + + size_t increment = BLOCKSIZE; + if (flags & BT_ReverseDirection) + { + CRYPTOPP_ASSERT(length % BLOCKSIZE == 0); + inBlocks += length - BLOCKSIZE; + xorBlocks += length - BLOCKSIZE; + outBlocks += length - BLOCKSIZE; + increment = 0-increment; + } + + Locals &locals = *(Locals *)(void *)space; + + locals.inBlocks = inBlocks; + locals.inXorBlocks = (flags & BT_XorInput) && xorBlocks ? xorBlocks : zeros; + locals.outXorBlocks = (flags & BT_XorInput) || !xorBlocks ? zeros : xorBlocks; + locals.outBlocks = outBlocks; + + locals.inIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : increment; + locals.inXorIncrement = (flags & BT_XorInput) && xorBlocks ? increment : 0; + locals.outXorIncrement = (flags & BT_XorInput) || !xorBlocks ? 0 : increment; + locals.outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : increment; + + locals.lengthAndCounterFlag = length - (length%16) - bool(flags & BT_InBlockIsCounter); + int keysToCopy = m_rounds - (flags & BT_InBlockIsCounter ? 3 : 2); + locals.keysBegin = (12-keysToCopy)*16; + + Rijndael_Enc_AdvancedProcessBlocks_SSE2(&locals, m_key); + + return length % BLOCKSIZE; + } +#endif + + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t Rijndael::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const +{ +#if CRYPTOPP_AESNI_AVAILABLE + if (HasAESNI()) + return Rijndael_Dec_AdvancedProcessBlocks_AESNI(m_key, m_rounds, inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if CRYPTOPP_ARM_AES_AVAILABLE + if (HasAES()) + return Rijndael_Dec_AdvancedProcessBlocks_ARMV8(m_key, m_rounds, inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if CRYPTOPP_POWER8_AES_AVAILABLE + if (HasAES()) + return Rijndael_Dec_AdvancedProcessBlocks128_6x1_ALTIVEC(m_key, m_rounds, inBlocks, xorBlocks, outBlocks, length, flags); +#endif + + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_RIJNDAEL_ADVANCED_PROCESS_BLOCKS + +NAMESPACE_END + +#endif +#endif diff --git a/external/ours/library/crypto/src/shared/original/rijndael.h b/external/ours/library/crypto/src/shared/original/rijndael.h new file mode 100755 index 000000000..bfb80fa12 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/rijndael_simd.cpp b/external/ours/library/crypto/src/shared/original/rijndael_simd.cpp new file mode 100755 index 000000000..c3421b3e9 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rijndael_simd.cpp @@ -0,0 +1,734 @@ +// rijndael_simd.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// AES-NI code originally written by Wei Dai. +// +// This source file uses intrinsics and built-ins to gain access to +// AES-NI, ARMv8a AES and Power8 AES instructions. A separate source +// file is needed because additional CXXFLAGS are required to enable +// the appropriate instructions sets in some build configurations. +// +// ARMv8a AES code based on CriticalBlue code from Johannes Schneiders, +// Skip Hovsmith and Barry O'Rourke for the mbedTLS project. Stepping +// mbedTLS under a debugger was helped for us to determine problems +// with our subkey generation and scheduling. +// +// AltiVec and Power8 code based on http://github.com/noloader/AES-Intrinsics and +// http://www.ibm.com/developerworks/library/se-power8-in-core-cryptography/ +// For Power8 do not remove the casts, even when const-ness is cast away. It causes +// failed compiles and a 0.3 to 0.6 cpb drop in performance. The IBM documentation +// absolutely sucks. Thanks to Andy Polyakov, Paul R and Trudeaun for answering +// questions and filling the gaps in the IBM documentation. +// + +#include "pch.h" +#include "config.h" +#include "misc.h" + +#if (CRYPTOPP_AESNI_AVAILABLE) +# include "adv_simd.h" +# include +# include +# include +#endif + +// Android makes available with ARMv7-a +#if (CRYPTOPP_BOOL_ARMV8) +# include "adv_simd.h" +# if (CRYPTOPP_ARM_NEON_HEADER) +# include +# endif +# if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +# endif +#endif + +#if defined(_M_ARM64) +# include "adv_simd.h" +#endif + +#if defined(CRYPTOPP_POWER8_AES_AVAILABLE) +# include "adv_simd.h" +# include "ppc_simd.h" +#endif + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#ifndef EXCEPTION_EXECUTE_HANDLER +# define EXCEPTION_EXECUTE_HANDLER 1 +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char RIJNDAEL_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +// ************************* Feature Probes ************************* // + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); + + static jmp_buf s_jmpSIGILL; + static void SigIllHandler(int) + { + longjmp(s_jmpSIGILL, 1); + } +} +#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY + +#if (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8) +bool CPU_ProbeAES() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (CRYPTOPP_ARM_AES_AVAILABLE) +# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) + volatile bool result = true; + __try + { + // AES encrypt and decrypt + uint8x16_t data = vdupq_n_u8(0), key = vdupq_n_u8(0); + uint8x16_t r1 = vaeseq_u8(data, key); + uint8x16_t r2 = vaesdq_u8(data, key); + r1 = vaesmcq_u8(r1); + r2 = vaesimcq_u8(r2); + + result = !!(vgetq_lane_u8(r1,0) | vgetq_lane_u8(r2,7)); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + return result; +# else + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + uint8x16_t data = vdupq_n_u8(0), key = vdupq_n_u8(0); + uint8x16_t r1 = vaeseq_u8(data, key); + uint8x16_t r2 = vaesdq_u8(data, key); + r1 = vaesmcq_u8(r1); + r2 = vaesimcq_u8(r2); + + // Hack... GCC optimizes away the code and returns true + result = !!(vgetq_lane_u8(r1,0) | vgetq_lane_u8(r2,7)); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_ARM_AES_AVAILABLE +} +#endif // ARM32 or ARM64 + +// ***************************** ARMv8 ***************************** // + +#if (CRYPTOPP_ARM_AES_AVAILABLE) + +ANONYMOUS_NAMESPACE_BEGIN + +inline void ARMV8_Enc_Block(uint64x2_t &data, const word32 *subkeys, unsigned int rounds) +{ + CRYPTOPP_ASSERT(subkeys); + const byte *keys = reinterpret_cast(subkeys); + uint8x16_t block = vreinterpretq_u8_u64(data); + + // AES single round encryption + block = vaeseq_u8(block, vld1q_u8(keys+0*16)); + // AES mix columns + block = vaesmcq_u8(block); + + for (unsigned int i=1; i(subkeys); + + uint8x16_t block0 = vreinterpretq_u8_u64(data0); + uint8x16_t block1 = vreinterpretq_u8_u64(data1); + uint8x16_t block2 = vreinterpretq_u8_u64(data2); + uint8x16_t block3 = vreinterpretq_u8_u64(data3); + uint8x16_t block4 = vreinterpretq_u8_u64(data4); + uint8x16_t block5 = vreinterpretq_u8_u64(data5); + + uint8x16_t key; + for (unsigned int i=0; i(subkeys); + uint8x16_t block = vreinterpretq_u8_u64(data); + + // AES single round decryption + block = vaesdq_u8(block, vld1q_u8(keys+0*16)); + // AES inverse mix columns + block = vaesimcq_u8(block); + + for (unsigned int i=1; i(subkeys); + + uint8x16_t block0 = vreinterpretq_u8_u64(data0); + uint8x16_t block1 = vreinterpretq_u8_u64(data1); + uint8x16_t block2 = vreinterpretq_u8_u64(data2); + uint8x16_t block3 = vreinterpretq_u8_u64(data3); + uint8x16_t block4 = vreinterpretq_u8_u64(data4); + uint8x16_t block5 = vreinterpretq_u8_u64(data5); + + uint8x16_t key; + for (unsigned int i=0; i(subkeys); + + block = _mm_xor_si128(block, skeys[0]); + for (unsigned int i=1; i(subkeys); + + __m128i rk = skeys[0]; + block0 = _mm_xor_si128(block0, rk); + block1 = _mm_xor_si128(block1, rk); + block2 = _mm_xor_si128(block2, rk); + block3 = _mm_xor_si128(block3, rk); + for (unsigned int i=1; i(subkeys); + + block = _mm_xor_si128(block, skeys[0]); + for (unsigned int i=1; i(subkeys); + + __m128i rk = skeys[0]; + block0 = _mm_xor_si128(block0, rk); + block1 = _mm_xor_si128(block1, rk); + block2 = _mm_xor_si128(block2, rk); + block3 = _mm_xor_si128(block3, rk); + for (unsigned int i=1; i(subkeys); + + uint32x4_p k = VecLoadAligned(keys); + block = VecXor(block, k); + + for (size_t i=1; i(subkeys); + + uint32x4_p k = VecLoadAligned(keys); + block0 = VecXor(block0, k); + block1 = VecXor(block1, k); + block2 = VecXor(block2, k); + block3 = VecXor(block3, k); + block4 = VecXor(block4, k); + block5 = VecXor(block5, k); + + for (size_t i=1; i(subkeys); + + uint32x4_p k = VecLoadAligned(rounds*16, keys); + block = VecXor(block, k); + + for (size_t i=rounds-1; i>1; i-=2) + { + block = VecDecrypt(block, VecLoadAligned( i*16, keys)); + block = VecDecrypt(block, VecLoadAligned((i-1)*16, keys)); + } + + block = VecDecrypt(block, VecLoadAligned(16, keys)); + block = VecDecryptLast(block, VecLoadAligned(0, keys)); +} + +inline void POWER8_Dec_6_Blocks(uint32x4_p &block0, uint32x4_p &block1, + uint32x4_p &block2, uint32x4_p &block3, uint32x4_p &block4, + uint32x4_p &block5, const word32 *subkeys, unsigned int rounds) +{ + CRYPTOPP_ASSERT(IsAlignedOn(subkeys, 16)); + const byte *keys = reinterpret_cast(subkeys); + + uint32x4_p k = VecLoadAligned(rounds*16, keys); + block0 = VecXor(block0, k); + block1 = VecXor(block1, k); + block2 = VecXor(block2, k); + block3 = VecXor(block3, k); + block4 = VecXor(block4, k); + block5 = VecXor(block5, k); + + for (size_t i=rounds-1; i>0; --i) + { + k = VecLoadAligned(i*16, keys); + block0 = VecDecrypt(block0, k); + block1 = VecDecrypt(block1, k); + block2 = VecDecrypt(block2, k); + block3 = VecDecrypt(block3, k); + block4 = VecDecrypt(block4, k); + block5 = VecDecrypt(block5, k); + } + + k = VecLoadAligned(0, keys); + block0 = VecDecryptLast(block0, k); + block1 = VecDecryptLast(block1, k); + block2 = VecDecryptLast(block2, k); + block3 = VecDecryptLast(block3, k); + block4 = VecDecryptLast(block4, k); + block5 = VecDecryptLast(block5, k); +} + +ANONYMOUS_NAMESPACE_END + +void Rijndael_UncheckedSetKey_POWER8(const byte* userKey, size_t keyLen, word32* rk, const byte* Se) +{ + const size_t rounds = keyLen / 4 + 6; + const word32 *rc = s_rconBE; + word32 *rkey = rk, temp; + + GetUserKey(BIG_ENDIAN_ORDER, rkey, keyLen/4, userKey, keyLen); + + // keySize: m_key allocates 4*(rounds+1) word32's. + const size_t keySize = 4*(rounds+1); + const word32* end = rkey + keySize; + + while (true) + { + temp = rkey[keyLen/4-1]; + word32 x = (word32(Se[GETBYTE(temp, 2)]) << 24) ^ (word32(Se[GETBYTE(temp, 1)]) << 16) ^ + (word32(Se[GETBYTE(temp, 0)]) << 8) ^ Se[GETBYTE(temp, 3)]; + rkey[keyLen/4] = rkey[0] ^ x ^ *(rc++); + rkey[keyLen/4+1] = rkey[1] ^ rkey[keyLen/4]; + rkey[keyLen/4+2] = rkey[2] ^ rkey[keyLen/4+1]; + rkey[keyLen/4+3] = rkey[3] ^ rkey[keyLen/4+2]; + + if (rkey + keyLen/4 + 4 == end) + break; + + if (keyLen == 24) + { + rkey[10] = rkey[ 4] ^ rkey[ 9]; + rkey[11] = rkey[ 5] ^ rkey[10]; + } + else if (keyLen == 32) + { + temp = rkey[11]; + rkey[12] = rkey[ 4] ^ (word32(Se[GETBYTE(temp, 3)]) << 24) ^ (word32(Se[GETBYTE(temp, 2)]) << 16) ^ (word32(Se[GETBYTE(temp, 1)]) << 8) ^ Se[GETBYTE(temp, 0)]; + rkey[13] = rkey[ 5] ^ rkey[12]; + rkey[14] = rkey[ 6] ^ rkey[13]; + rkey[15] = rkey[ 7] ^ rkey[14]; + } + rkey += keyLen/4; + } + +#if (CRYPTOPP_LITTLE_ENDIAN) + rkey = rk; + const uint8x16_p mask = {12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3}; + + unsigned int i=0; + for (i=0; i((word32)c) + +void RIPEMD160::InitState(HashWordType *state) +{ + state[0] = 0x67452301L; + state[1] = 0xefcdab89L; + state[2] = 0x98badcfeL; + state[3] = 0x10325476L; + state[4] = 0xc3d2e1f0L; +} + +void RIPEMD160::Transform (word32 *digest, const word32 *X) +{ + unsigned long a1, b1, c1, d1, e1, a2, b2, c2, d2, e2; + a1 = a2 = digest[0]; + b1 = b2 = digest[1]; + c1 = c2 = digest[2]; + d1 = d2 = digest[3]; + e1 = e2 = digest[4]; + + Subround(F, a1, b1, c1, d1, e1, X[ 0], 11, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 1], 14, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 2], 15, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 3], 12, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 4], 5, k0); + Subround(F, a1, b1, c1, d1, e1, X[ 5], 8, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 6], 7, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 7], 9, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 8], 11, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 9], 13, k0); + Subround(F, a1, b1, c1, d1, e1, X[10], 14, k0); + Subround(F, e1, a1, b1, c1, d1, X[11], 15, k0); + Subround(F, d1, e1, a1, b1, c1, X[12], 6, k0); + Subround(F, c1, d1, e1, a1, b1, X[13], 7, k0); + Subround(F, b1, c1, d1, e1, a1, X[14], 9, k0); + Subround(F, a1, b1, c1, d1, e1, X[15], 8, k0); + + Subround(G, e1, a1, b1, c1, d1, X[ 7], 7, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 4], 6, k1); + Subround(G, c1, d1, e1, a1, b1, X[13], 8, k1); + Subround(G, b1, c1, d1, e1, a1, X[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, e1, X[10], 11, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 6], 9, k1); + Subround(G, d1, e1, a1, b1, c1, X[15], 7, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 3], 15, k1); + Subround(G, b1, c1, d1, e1, a1, X[12], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[ 0], 12, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 9], 15, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 5], 9, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 2], 11, k1); + Subround(G, b1, c1, d1, e1, a1, X[14], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[11], 13, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 8], 12, k1); + + Subround(H, d1, e1, a1, b1, c1, X[ 3], 11, k2); + Subround(H, c1, d1, e1, a1, b1, X[10], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[14], 6, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 4], 7, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 9], 14, k2); + Subround(H, d1, e1, a1, b1, c1, X[15], 9, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 8], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 2], 14, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 7], 8, k2); + Subround(H, d1, e1, a1, b1, c1, X[ 0], 13, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 6], 6, k2); + Subround(H, b1, c1, d1, e1, a1, X[13], 5, k2); + Subround(H, a1, b1, c1, d1, e1, X[11], 12, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 5], 7, k2); + Subround(H, d1, e1, a1, b1, c1, X[12], 5, k2); + + Subround(I, c1, d1, e1, a1, b1, X[ 1], 11, k3); + Subround(I, b1, c1, d1, e1, a1, X[ 9], 12, k3); + Subround(I, a1, b1, c1, d1, e1, X[11], 14, k3); + Subround(I, e1, a1, b1, c1, d1, X[10], 15, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 0], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 8], 15, k3); + Subround(I, b1, c1, d1, e1, a1, X[12], 9, k3); + Subround(I, a1, b1, c1, d1, e1, X[ 4], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[13], 9, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 3], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 7], 5, k3); + Subround(I, b1, c1, d1, e1, a1, X[15], 6, k3); + Subround(I, a1, b1, c1, d1, e1, X[14], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[ 5], 6, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 6], 5, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 2], 12, k3); + + Subround(J, b1, c1, d1, e1, a1, X[ 4], 9, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 0], 15, k4); + Subround(J, e1, a1, b1, c1, d1, X[ 5], 5, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 9], 11, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 7], 6, k4); + Subround(J, b1, c1, d1, e1, a1, X[12], 8, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 2], 13, k4); + Subround(J, e1, a1, b1, c1, d1, X[10], 12, k4); + Subround(J, d1, e1, a1, b1, c1, X[14], 5, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 1], 12, k4); + Subround(J, b1, c1, d1, e1, a1, X[ 3], 13, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 8], 14, k4); + Subround(J, e1, a1, b1, c1, d1, X[11], 11, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 6], 8, k4); + Subround(J, c1, d1, e1, a1, b1, X[15], 5, k4); + Subround(J, b1, c1, d1, e1, a1, X[13], 6, k4); + + Subround(J, a2, b2, c2, d2, e2, X[ 5], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[14], 9, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 7], 9, k5); + Subround(J, c2, d2, e2, a2, b2, X[ 0], 11, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 9], 13, k5); + Subround(J, a2, b2, c2, d2, e2, X[ 2], 15, k5); + Subround(J, e2, a2, b2, c2, d2, X[11], 15, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 4], 5, k5); + Subround(J, c2, d2, e2, a2, b2, X[13], 7, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 6], 7, k5); + Subround(J, a2, b2, c2, d2, e2, X[15], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[ 8], 11, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 1], 14, k5); + Subround(J, c2, d2, e2, a2, b2, X[10], 14, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 3], 12, k5); + Subround(J, a2, b2, c2, d2, e2, X[12], 6, k5); + + Subround(I, e2, a2, b2, c2, d2, X[ 6], 9, k6); + Subround(I, d2, e2, a2, b2, c2, X[11], 13, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 3], 15, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 7], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 0], 12, k6); + Subround(I, e2, a2, b2, c2, d2, X[13], 8, k6); + Subround(I, d2, e2, a2, b2, c2, X[ 5], 9, k6); + Subround(I, c2, d2, e2, a2, b2, X[10], 11, k6); + Subround(I, b2, c2, d2, e2, a2, X[14], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[15], 7, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 8], 12, k6); + Subround(I, d2, e2, a2, b2, c2, X[12], 7, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 4], 6, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 9], 15, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 1], 13, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 2], 11, k6); + + Subround(H, d2, e2, a2, b2, c2, X[15], 9, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 5], 7, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 1], 15, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 3], 11, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 7], 8, k7); + Subround(H, d2, e2, a2, b2, c2, X[14], 6, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 6], 6, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 9], 14, k7); + Subround(H, a2, b2, c2, d2, e2, X[11], 12, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 8], 13, k7); + Subround(H, d2, e2, a2, b2, c2, X[12], 5, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 2], 14, k7); + Subround(H, b2, c2, d2, e2, a2, X[10], 13, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 0], 13, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 4], 7, k7); + Subround(H, d2, e2, a2, b2, c2, X[13], 5, k7); + + Subround(G, c2, d2, e2, a2, b2, X[ 8], 15, k8); + Subround(G, b2, c2, d2, e2, a2, X[ 6], 5, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 4], 8, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 1], 11, k8); + Subround(G, d2, e2, a2, b2, c2, X[ 3], 14, k8); + Subround(G, c2, d2, e2, a2, b2, X[11], 14, k8); + Subround(G, b2, c2, d2, e2, a2, X[15], 6, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 0], 14, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 5], 6, k8); + Subround(G, d2, e2, a2, b2, c2, X[12], 9, k8); + Subround(G, c2, d2, e2, a2, b2, X[ 2], 12, k8); + Subround(G, b2, c2, d2, e2, a2, X[13], 9, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 9], 12, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 7], 5, k8); + Subround(G, d2, e2, a2, b2, c2, X[10], 15, k8); + Subround(G, c2, d2, e2, a2, b2, X[14], 8, k8); + + Subround(F, b2, c2, d2, e2, a2, X[12], 8, k9); + Subround(F, a2, b2, c2, d2, e2, X[15], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[10], 12, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 4], 9, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 1], 12, k9); + Subround(F, b2, c2, d2, e2, a2, X[ 5], 5, k9); + Subround(F, a2, b2, c2, d2, e2, X[ 8], 14, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 7], 6, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 6], 8, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 2], 13, k9); + Subround(F, b2, c2, d2, e2, a2, X[13], 6, k9); + Subround(F, a2, b2, c2, d2, e2, X[14], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 0], 15, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 3], 13, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 9], 11, k9); + Subround(F, b2, c2, d2, e2, a2, X[11], 11, k9); + + c1 = digest[1] + c1 + d2; + digest[1] = digest[2] + d1 + e2; + digest[2] = digest[3] + e1 + a2; + digest[3] = digest[4] + a1 + b2; + digest[4] = digest[0] + b1 + c2; + digest[0] = c1; +} + +// ************************************************************* + +void RIPEMD320::InitState(HashWordType *state) +{ + state[0] = 0x67452301L; + state[1] = 0xefcdab89L; + state[2] = 0x98badcfeL; + state[3] = 0x10325476L; + state[4] = 0xc3d2e1f0L; + state[5] = 0x76543210L; + state[6] = 0xfedcba98L; + state[7] = 0x89abcdefL; + state[8] = 0x01234567L; + state[9] = 0x3c2d1e0fL; +} + +void RIPEMD320::Transform (word32 *digest, const word32 *X) +{ + unsigned long a1, b1, c1, d1, e1, a2, b2, c2, d2, e2, t; + a1 = digest[0]; + b1 = digest[1]; + c1 = digest[2]; + d1 = digest[3]; + e1 = digest[4]; + a2 = digest[5]; + b2 = digest[6]; + c2 = digest[7]; + d2 = digest[8]; + e2 = digest[9]; + + Subround(F, a1, b1, c1, d1, e1, X[ 0], 11, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 1], 14, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 2], 15, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 3], 12, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 4], 5, k0); + Subround(F, a1, b1, c1, d1, e1, X[ 5], 8, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 6], 7, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 7], 9, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 8], 11, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 9], 13, k0); + Subround(F, a1, b1, c1, d1, e1, X[10], 14, k0); + Subround(F, e1, a1, b1, c1, d1, X[11], 15, k0); + Subround(F, d1, e1, a1, b1, c1, X[12], 6, k0); + Subround(F, c1, d1, e1, a1, b1, X[13], 7, k0); + Subround(F, b1, c1, d1, e1, a1, X[14], 9, k0); + Subround(F, a1, b1, c1, d1, e1, X[15], 8, k0); + + Subround(J, a2, b2, c2, d2, e2, X[ 5], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[14], 9, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 7], 9, k5); + Subround(J, c2, d2, e2, a2, b2, X[ 0], 11, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 9], 13, k5); + Subround(J, a2, b2, c2, d2, e2, X[ 2], 15, k5); + Subround(J, e2, a2, b2, c2, d2, X[11], 15, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 4], 5, k5); + Subround(J, c2, d2, e2, a2, b2, X[13], 7, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 6], 7, k5); + Subround(J, a2, b2, c2, d2, e2, X[15], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[ 8], 11, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 1], 14, k5); + Subround(J, c2, d2, e2, a2, b2, X[10], 14, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 3], 12, k5); + Subround(J, a2, b2, c2, d2, e2, X[12], 6, k5); + + t = a1; a1 = a2; a2 = t; + + Subround(G, e1, a1, b1, c1, d1, X[ 7], 7, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 4], 6, k1); + Subround(G, c1, d1, e1, a1, b1, X[13], 8, k1); + Subround(G, b1, c1, d1, e1, a1, X[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, e1, X[10], 11, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 6], 9, k1); + Subround(G, d1, e1, a1, b1, c1, X[15], 7, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 3], 15, k1); + Subround(G, b1, c1, d1, e1, a1, X[12], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[ 0], 12, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 9], 15, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 5], 9, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 2], 11, k1); + Subround(G, b1, c1, d1, e1, a1, X[14], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[11], 13, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 8], 12, k1); + + Subround(I, e2, a2, b2, c2, d2, X[ 6], 9, k6); + Subround(I, d2, e2, a2, b2, c2, X[11], 13, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 3], 15, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 7], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 0], 12, k6); + Subround(I, e2, a2, b2, c2, d2, X[13], 8, k6); + Subround(I, d2, e2, a2, b2, c2, X[ 5], 9, k6); + Subround(I, c2, d2, e2, a2, b2, X[10], 11, k6); + Subround(I, b2, c2, d2, e2, a2, X[14], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[15], 7, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 8], 12, k6); + Subround(I, d2, e2, a2, b2, c2, X[12], 7, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 4], 6, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 9], 15, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 1], 13, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 2], 11, k6); + + t = b1; b1 = b2; b2 = t; + + Subround(H, d1, e1, a1, b1, c1, X[ 3], 11, k2); + Subround(H, c1, d1, e1, a1, b1, X[10], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[14], 6, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 4], 7, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 9], 14, k2); + Subround(H, d1, e1, a1, b1, c1, X[15], 9, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 8], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 2], 14, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 7], 8, k2); + Subround(H, d1, e1, a1, b1, c1, X[ 0], 13, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 6], 6, k2); + Subround(H, b1, c1, d1, e1, a1, X[13], 5, k2); + Subround(H, a1, b1, c1, d1, e1, X[11], 12, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 5], 7, k2); + Subround(H, d1, e1, a1, b1, c1, X[12], 5, k2); + + Subround(H, d2, e2, a2, b2, c2, X[15], 9, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 5], 7, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 1], 15, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 3], 11, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 7], 8, k7); + Subround(H, d2, e2, a2, b2, c2, X[14], 6, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 6], 6, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 9], 14, k7); + Subround(H, a2, b2, c2, d2, e2, X[11], 12, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 8], 13, k7); + Subround(H, d2, e2, a2, b2, c2, X[12], 5, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 2], 14, k7); + Subround(H, b2, c2, d2, e2, a2, X[10], 13, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 0], 13, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 4], 7, k7); + Subround(H, d2, e2, a2, b2, c2, X[13], 5, k7); + + t = c1; c1 = c2; c2 = t; + + Subround(I, c1, d1, e1, a1, b1, X[ 1], 11, k3); + Subround(I, b1, c1, d1, e1, a1, X[ 9], 12, k3); + Subround(I, a1, b1, c1, d1, e1, X[11], 14, k3); + Subround(I, e1, a1, b1, c1, d1, X[10], 15, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 0], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 8], 15, k3); + Subround(I, b1, c1, d1, e1, a1, X[12], 9, k3); + Subround(I, a1, b1, c1, d1, e1, X[ 4], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[13], 9, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 3], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 7], 5, k3); + Subround(I, b1, c1, d1, e1, a1, X[15], 6, k3); + Subround(I, a1, b1, c1, d1, e1, X[14], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[ 5], 6, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 6], 5, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 2], 12, k3); + + Subround(G, c2, d2, e2, a2, b2, X[ 8], 15, k8); + Subround(G, b2, c2, d2, e2, a2, X[ 6], 5, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 4], 8, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 1], 11, k8); + Subround(G, d2, e2, a2, b2, c2, X[ 3], 14, k8); + Subround(G, c2, d2, e2, a2, b2, X[11], 14, k8); + Subround(G, b2, c2, d2, e2, a2, X[15], 6, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 0], 14, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 5], 6, k8); + Subround(G, d2, e2, a2, b2, c2, X[12], 9, k8); + Subround(G, c2, d2, e2, a2, b2, X[ 2], 12, k8); + Subround(G, b2, c2, d2, e2, a2, X[13], 9, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 9], 12, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 7], 5, k8); + Subround(G, d2, e2, a2, b2, c2, X[10], 15, k8); + Subround(G, c2, d2, e2, a2, b2, X[14], 8, k8); + + t = d1; d1 = d2; d2 = t; + + Subround(J, b1, c1, d1, e1, a1, X[ 4], 9, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 0], 15, k4); + Subround(J, e1, a1, b1, c1, d1, X[ 5], 5, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 9], 11, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 7], 6, k4); + Subround(J, b1, c1, d1, e1, a1, X[12], 8, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 2], 13, k4); + Subround(J, e1, a1, b1, c1, d1, X[10], 12, k4); + Subround(J, d1, e1, a1, b1, c1, X[14], 5, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 1], 12, k4); + Subround(J, b1, c1, d1, e1, a1, X[ 3], 13, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 8], 14, k4); + Subround(J, e1, a1, b1, c1, d1, X[11], 11, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 6], 8, k4); + Subround(J, c1, d1, e1, a1, b1, X[15], 5, k4); + Subround(J, b1, c1, d1, e1, a1, X[13], 6, k4); + + Subround(F, b2, c2, d2, e2, a2, X[12], 8, k9); + Subround(F, a2, b2, c2, d2, e2, X[15], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[10], 12, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 4], 9, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 1], 12, k9); + Subround(F, b2, c2, d2, e2, a2, X[ 5], 5, k9); + Subround(F, a2, b2, c2, d2, e2, X[ 8], 14, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 7], 6, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 6], 8, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 2], 13, k9); + Subround(F, b2, c2, d2, e2, a2, X[13], 6, k9); + Subround(F, a2, b2, c2, d2, e2, X[14], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 0], 15, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 3], 13, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 9], 11, k9); + Subround(F, b2, c2, d2, e2, a2, X[11], 11, k9); + + t = e1; e1 = e2; e2 = t; + + digest[0] += a1; + digest[1] += b1; + digest[2] += c1; + digest[3] += d1; + digest[4] += e1; + digest[5] += a2; + digest[6] += b2; + digest[7] += c2; + digest[8] += d2; + digest[9] += e2; +} + +#undef Subround + +// ************************************************************* + +// for 128 and 256 +#define Subround(f, a, b, c, d, x, s, k) \ + a += f(b, c, d) + x + k;\ + a = rotlVariable((word32)a, s); + +void RIPEMD128::InitState(HashWordType *state) +{ + state[0] = 0x67452301L; + state[1] = 0xefcdab89L; + state[2] = 0x98badcfeL; + state[3] = 0x10325476L; +} + +void RIPEMD128::Transform (word32 *digest, const word32 *X) +{ + unsigned long a1, b1, c1, d1, a2, b2, c2, d2; + a1 = a2 = digest[0]; + b1 = b2 = digest[1]; + c1 = c2 = digest[2]; + d1 = d2 = digest[3]; + + Subround(F, a1, b1, c1, d1, X[ 0], 11, k0); + Subround(F, d1, a1, b1, c1, X[ 1], 14, k0); + Subround(F, c1, d1, a1, b1, X[ 2], 15, k0); + Subround(F, b1, c1, d1, a1, X[ 3], 12, k0); + Subround(F, a1, b1, c1, d1, X[ 4], 5, k0); + Subround(F, d1, a1, b1, c1, X[ 5], 8, k0); + Subround(F, c1, d1, a1, b1, X[ 6], 7, k0); + Subround(F, b1, c1, d1, a1, X[ 7], 9, k0); + Subround(F, a1, b1, c1, d1, X[ 8], 11, k0); + Subround(F, d1, a1, b1, c1, X[ 9], 13, k0); + Subround(F, c1, d1, a1, b1, X[10], 14, k0); + Subround(F, b1, c1, d1, a1, X[11], 15, k0); + Subround(F, a1, b1, c1, d1, X[12], 6, k0); + Subround(F, d1, a1, b1, c1, X[13], 7, k0); + Subround(F, c1, d1, a1, b1, X[14], 9, k0); + Subround(F, b1, c1, d1, a1, X[15], 8, k0); + + Subround(G, a1, b1, c1, d1, X[ 7], 7, k1); + Subround(G, d1, a1, b1, c1, X[ 4], 6, k1); + Subround(G, c1, d1, a1, b1, X[13], 8, k1); + Subround(G, b1, c1, d1, a1, X[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, X[10], 11, k1); + Subround(G, d1, a1, b1, c1, X[ 6], 9, k1); + Subround(G, c1, d1, a1, b1, X[15], 7, k1); + Subround(G, b1, c1, d1, a1, X[ 3], 15, k1); + Subround(G, a1, b1, c1, d1, X[12], 7, k1); + Subround(G, d1, a1, b1, c1, X[ 0], 12, k1); + Subround(G, c1, d1, a1, b1, X[ 9], 15, k1); + Subround(G, b1, c1, d1, a1, X[ 5], 9, k1); + Subround(G, a1, b1, c1, d1, X[ 2], 11, k1); + Subround(G, d1, a1, b1, c1, X[14], 7, k1); + Subround(G, c1, d1, a1, b1, X[11], 13, k1); + Subround(G, b1, c1, d1, a1, X[ 8], 12, k1); + + Subround(H, a1, b1, c1, d1, X[ 3], 11, k2); + Subround(H, d1, a1, b1, c1, X[10], 13, k2); + Subround(H, c1, d1, a1, b1, X[14], 6, k2); + Subround(H, b1, c1, d1, a1, X[ 4], 7, k2); + Subround(H, a1, b1, c1, d1, X[ 9], 14, k2); + Subround(H, d1, a1, b1, c1, X[15], 9, k2); + Subround(H, c1, d1, a1, b1, X[ 8], 13, k2); + Subround(H, b1, c1, d1, a1, X[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, X[ 2], 14, k2); + Subround(H, d1, a1, b1, c1, X[ 7], 8, k2); + Subround(H, c1, d1, a1, b1, X[ 0], 13, k2); + Subround(H, b1, c1, d1, a1, X[ 6], 6, k2); + Subround(H, a1, b1, c1, d1, X[13], 5, k2); + Subround(H, d1, a1, b1, c1, X[11], 12, k2); + Subround(H, c1, d1, a1, b1, X[ 5], 7, k2); + Subround(H, b1, c1, d1, a1, X[12], 5, k2); + + Subround(I, a1, b1, c1, d1, X[ 1], 11, k3); + Subround(I, d1, a1, b1, c1, X[ 9], 12, k3); + Subround(I, c1, d1, a1, b1, X[11], 14, k3); + Subround(I, b1, c1, d1, a1, X[10], 15, k3); + Subround(I, a1, b1, c1, d1, X[ 0], 14, k3); + Subround(I, d1, a1, b1, c1, X[ 8], 15, k3); + Subround(I, c1, d1, a1, b1, X[12], 9, k3); + Subround(I, b1, c1, d1, a1, X[ 4], 8, k3); + Subround(I, a1, b1, c1, d1, X[13], 9, k3); + Subround(I, d1, a1, b1, c1, X[ 3], 14, k3); + Subround(I, c1, d1, a1, b1, X[ 7], 5, k3); + Subround(I, b1, c1, d1, a1, X[15], 6, k3); + Subround(I, a1, b1, c1, d1, X[14], 8, k3); + Subround(I, d1, a1, b1, c1, X[ 5], 6, k3); + Subround(I, c1, d1, a1, b1, X[ 6], 5, k3); + Subround(I, b1, c1, d1, a1, X[ 2], 12, k3); + + Subround(I, a2, b2, c2, d2, X[ 5], 8, k5); + Subround(I, d2, a2, b2, c2, X[14], 9, k5); + Subround(I, c2, d2, a2, b2, X[ 7], 9, k5); + Subround(I, b2, c2, d2, a2, X[ 0], 11, k5); + Subround(I, a2, b2, c2, d2, X[ 9], 13, k5); + Subround(I, d2, a2, b2, c2, X[ 2], 15, k5); + Subround(I, c2, d2, a2, b2, X[11], 15, k5); + Subround(I, b2, c2, d2, a2, X[ 4], 5, k5); + Subround(I, a2, b2, c2, d2, X[13], 7, k5); + Subround(I, d2, a2, b2, c2, X[ 6], 7, k5); + Subround(I, c2, d2, a2, b2, X[15], 8, k5); + Subround(I, b2, c2, d2, a2, X[ 8], 11, k5); + Subround(I, a2, b2, c2, d2, X[ 1], 14, k5); + Subround(I, d2, a2, b2, c2, X[10], 14, k5); + Subround(I, c2, d2, a2, b2, X[ 3], 12, k5); + Subround(I, b2, c2, d2, a2, X[12], 6, k5); + + Subround(H, a2, b2, c2, d2, X[ 6], 9, k6); + Subround(H, d2, a2, b2, c2, X[11], 13, k6); + Subround(H, c2, d2, a2, b2, X[ 3], 15, k6); + Subround(H, b2, c2, d2, a2, X[ 7], 7, k6); + Subround(H, a2, b2, c2, d2, X[ 0], 12, k6); + Subround(H, d2, a2, b2, c2, X[13], 8, k6); + Subround(H, c2, d2, a2, b2, X[ 5], 9, k6); + Subround(H, b2, c2, d2, a2, X[10], 11, k6); + Subround(H, a2, b2, c2, d2, X[14], 7, k6); + Subround(H, d2, a2, b2, c2, X[15], 7, k6); + Subround(H, c2, d2, a2, b2, X[ 8], 12, k6); + Subround(H, b2, c2, d2, a2, X[12], 7, k6); + Subround(H, a2, b2, c2, d2, X[ 4], 6, k6); + Subround(H, d2, a2, b2, c2, X[ 9], 15, k6); + Subround(H, c2, d2, a2, b2, X[ 1], 13, k6); + Subround(H, b2, c2, d2, a2, X[ 2], 11, k6); + + Subround(G, a2, b2, c2, d2, X[15], 9, k7); + Subround(G, d2, a2, b2, c2, X[ 5], 7, k7); + Subround(G, c2, d2, a2, b2, X[ 1], 15, k7); + Subround(G, b2, c2, d2, a2, X[ 3], 11, k7); + Subround(G, a2, b2, c2, d2, X[ 7], 8, k7); + Subround(G, d2, a2, b2, c2, X[14], 6, k7); + Subround(G, c2, d2, a2, b2, X[ 6], 6, k7); + Subround(G, b2, c2, d2, a2, X[ 9], 14, k7); + Subround(G, a2, b2, c2, d2, X[11], 12, k7); + Subround(G, d2, a2, b2, c2, X[ 8], 13, k7); + Subround(G, c2, d2, a2, b2, X[12], 5, k7); + Subround(G, b2, c2, d2, a2, X[ 2], 14, k7); + Subround(G, a2, b2, c2, d2, X[10], 13, k7); + Subround(G, d2, a2, b2, c2, X[ 0], 13, k7); + Subround(G, c2, d2, a2, b2, X[ 4], 7, k7); + Subround(G, b2, c2, d2, a2, X[13], 5, k7); + + Subround(F, a2, b2, c2, d2, X[ 8], 15, k9); + Subround(F, d2, a2, b2, c2, X[ 6], 5, k9); + Subround(F, c2, d2, a2, b2, X[ 4], 8, k9); + Subround(F, b2, c2, d2, a2, X[ 1], 11, k9); + Subround(F, a2, b2, c2, d2, X[ 3], 14, k9); + Subround(F, d2, a2, b2, c2, X[11], 14, k9); + Subround(F, c2, d2, a2, b2, X[15], 6, k9); + Subround(F, b2, c2, d2, a2, X[ 0], 14, k9); + Subround(F, a2, b2, c2, d2, X[ 5], 6, k9); + Subround(F, d2, a2, b2, c2, X[12], 9, k9); + Subround(F, c2, d2, a2, b2, X[ 2], 12, k9); + Subround(F, b2, c2, d2, a2, X[13], 9, k9); + Subround(F, a2, b2, c2, d2, X[ 9], 12, k9); + Subround(F, d2, a2, b2, c2, X[ 7], 5, k9); + Subround(F, c2, d2, a2, b2, X[10], 15, k9); + Subround(F, b2, c2, d2, a2, X[14], 8, k9); + + c1 = digest[1] + c1 + d2; + digest[1] = digest[2] + d1 + a2; + digest[2] = digest[3] + a1 + b2; + digest[3] = digest[0] + b1 + c2; + digest[0] = c1; +} + +// ************************************************************* + +void RIPEMD256::InitState(HashWordType *state) +{ + state[0] = 0x67452301L; + state[1] = 0xefcdab89L; + state[2] = 0x98badcfeL; + state[3] = 0x10325476L; + state[4] = 0x76543210L; + state[5] = 0xfedcba98L; + state[6] = 0x89abcdefL; + state[7] = 0x01234567L; +} + +void RIPEMD256::Transform (word32 *digest, const word32 *X) +{ + unsigned long a1, b1, c1, d1, a2, b2, c2, d2, t; + a1 = digest[0]; + b1 = digest[1]; + c1 = digest[2]; + d1 = digest[3]; + a2 = digest[4]; + b2 = digest[5]; + c2 = digest[6]; + d2 = digest[7]; + + Subround(F, a1, b1, c1, d1, X[ 0], 11, k0); + Subround(F, d1, a1, b1, c1, X[ 1], 14, k0); + Subround(F, c1, d1, a1, b1, X[ 2], 15, k0); + Subround(F, b1, c1, d1, a1, X[ 3], 12, k0); + Subround(F, a1, b1, c1, d1, X[ 4], 5, k0); + Subround(F, d1, a1, b1, c1, X[ 5], 8, k0); + Subround(F, c1, d1, a1, b1, X[ 6], 7, k0); + Subround(F, b1, c1, d1, a1, X[ 7], 9, k0); + Subround(F, a1, b1, c1, d1, X[ 8], 11, k0); + Subround(F, d1, a1, b1, c1, X[ 9], 13, k0); + Subround(F, c1, d1, a1, b1, X[10], 14, k0); + Subround(F, b1, c1, d1, a1, X[11], 15, k0); + Subround(F, a1, b1, c1, d1, X[12], 6, k0); + Subround(F, d1, a1, b1, c1, X[13], 7, k0); + Subround(F, c1, d1, a1, b1, X[14], 9, k0); + Subround(F, b1, c1, d1, a1, X[15], 8, k0); + + Subround(I, a2, b2, c2, d2, X[ 5], 8, k5); + Subround(I, d2, a2, b2, c2, X[14], 9, k5); + Subround(I, c2, d2, a2, b2, X[ 7], 9, k5); + Subround(I, b2, c2, d2, a2, X[ 0], 11, k5); + Subround(I, a2, b2, c2, d2, X[ 9], 13, k5); + Subround(I, d2, a2, b2, c2, X[ 2], 15, k5); + Subround(I, c2, d2, a2, b2, X[11], 15, k5); + Subround(I, b2, c2, d2, a2, X[ 4], 5, k5); + Subround(I, a2, b2, c2, d2, X[13], 7, k5); + Subround(I, d2, a2, b2, c2, X[ 6], 7, k5); + Subround(I, c2, d2, a2, b2, X[15], 8, k5); + Subround(I, b2, c2, d2, a2, X[ 8], 11, k5); + Subround(I, a2, b2, c2, d2, X[ 1], 14, k5); + Subround(I, d2, a2, b2, c2, X[10], 14, k5); + Subround(I, c2, d2, a2, b2, X[ 3], 12, k5); + Subround(I, b2, c2, d2, a2, X[12], 6, k5); + + t = a1; a1 = a2; a2 = t; + + Subround(G, a1, b1, c1, d1, X[ 7], 7, k1); + Subround(G, d1, a1, b1, c1, X[ 4], 6, k1); + Subround(G, c1, d1, a1, b1, X[13], 8, k1); + Subround(G, b1, c1, d1, a1, X[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, X[10], 11, k1); + Subround(G, d1, a1, b1, c1, X[ 6], 9, k1); + Subround(G, c1, d1, a1, b1, X[15], 7, k1); + Subround(G, b1, c1, d1, a1, X[ 3], 15, k1); + Subround(G, a1, b1, c1, d1, X[12], 7, k1); + Subround(G, d1, a1, b1, c1, X[ 0], 12, k1); + Subround(G, c1, d1, a1, b1, X[ 9], 15, k1); + Subround(G, b1, c1, d1, a1, X[ 5], 9, k1); + Subround(G, a1, b1, c1, d1, X[ 2], 11, k1); + Subround(G, d1, a1, b1, c1, X[14], 7, k1); + Subround(G, c1, d1, a1, b1, X[11], 13, k1); + Subround(G, b1, c1, d1, a1, X[ 8], 12, k1); + + Subround(H, a2, b2, c2, d2, X[ 6], 9, k6); + Subround(H, d2, a2, b2, c2, X[11], 13, k6); + Subround(H, c2, d2, a2, b2, X[ 3], 15, k6); + Subround(H, b2, c2, d2, a2, X[ 7], 7, k6); + Subround(H, a2, b2, c2, d2, X[ 0], 12, k6); + Subround(H, d2, a2, b2, c2, X[13], 8, k6); + Subround(H, c2, d2, a2, b2, X[ 5], 9, k6); + Subround(H, b2, c2, d2, a2, X[10], 11, k6); + Subround(H, a2, b2, c2, d2, X[14], 7, k6); + Subround(H, d2, a2, b2, c2, X[15], 7, k6); + Subround(H, c2, d2, a2, b2, X[ 8], 12, k6); + Subround(H, b2, c2, d2, a2, X[12], 7, k6); + Subround(H, a2, b2, c2, d2, X[ 4], 6, k6); + Subround(H, d2, a2, b2, c2, X[ 9], 15, k6); + Subround(H, c2, d2, a2, b2, X[ 1], 13, k6); + Subround(H, b2, c2, d2, a2, X[ 2], 11, k6); + + t = b1; b1 = b2; b2 = t; + + Subround(H, a1, b1, c1, d1, X[ 3], 11, k2); + Subround(H, d1, a1, b1, c1, X[10], 13, k2); + Subround(H, c1, d1, a1, b1, X[14], 6, k2); + Subround(H, b1, c1, d1, a1, X[ 4], 7, k2); + Subround(H, a1, b1, c1, d1, X[ 9], 14, k2); + Subround(H, d1, a1, b1, c1, X[15], 9, k2); + Subround(H, c1, d1, a1, b1, X[ 8], 13, k2); + Subround(H, b1, c1, d1, a1, X[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, X[ 2], 14, k2); + Subround(H, d1, a1, b1, c1, X[ 7], 8, k2); + Subround(H, c1, d1, a1, b1, X[ 0], 13, k2); + Subround(H, b1, c1, d1, a1, X[ 6], 6, k2); + Subround(H, a1, b1, c1, d1, X[13], 5, k2); + Subround(H, d1, a1, b1, c1, X[11], 12, k2); + Subround(H, c1, d1, a1, b1, X[ 5], 7, k2); + Subround(H, b1, c1, d1, a1, X[12], 5, k2); + + Subround(G, a2, b2, c2, d2, X[15], 9, k7); + Subround(G, d2, a2, b2, c2, X[ 5], 7, k7); + Subround(G, c2, d2, a2, b2, X[ 1], 15, k7); + Subround(G, b2, c2, d2, a2, X[ 3], 11, k7); + Subround(G, a2, b2, c2, d2, X[ 7], 8, k7); + Subround(G, d2, a2, b2, c2, X[14], 6, k7); + Subround(G, c2, d2, a2, b2, X[ 6], 6, k7); + Subround(G, b2, c2, d2, a2, X[ 9], 14, k7); + Subround(G, a2, b2, c2, d2, X[11], 12, k7); + Subround(G, d2, a2, b2, c2, X[ 8], 13, k7); + Subround(G, c2, d2, a2, b2, X[12], 5, k7); + Subround(G, b2, c2, d2, a2, X[ 2], 14, k7); + Subround(G, a2, b2, c2, d2, X[10], 13, k7); + Subround(G, d2, a2, b2, c2, X[ 0], 13, k7); + Subround(G, c2, d2, a2, b2, X[ 4], 7, k7); + Subround(G, b2, c2, d2, a2, X[13], 5, k7); + + t = c1; c1 = c2; c2 = t; + + Subround(I, a1, b1, c1, d1, X[ 1], 11, k3); + Subround(I, d1, a1, b1, c1, X[ 9], 12, k3); + Subround(I, c1, d1, a1, b1, X[11], 14, k3); + Subround(I, b1, c1, d1, a1, X[10], 15, k3); + Subround(I, a1, b1, c1, d1, X[ 0], 14, k3); + Subround(I, d1, a1, b1, c1, X[ 8], 15, k3); + Subround(I, c1, d1, a1, b1, X[12], 9, k3); + Subround(I, b1, c1, d1, a1, X[ 4], 8, k3); + Subround(I, a1, b1, c1, d1, X[13], 9, k3); + Subround(I, d1, a1, b1, c1, X[ 3], 14, k3); + Subround(I, c1, d1, a1, b1, X[ 7], 5, k3); + Subround(I, b1, c1, d1, a1, X[15], 6, k3); + Subround(I, a1, b1, c1, d1, X[14], 8, k3); + Subround(I, d1, a1, b1, c1, X[ 5], 6, k3); + Subround(I, c1, d1, a1, b1, X[ 6], 5, k3); + Subround(I, b1, c1, d1, a1, X[ 2], 12, k3); + + Subround(F, a2, b2, c2, d2, X[ 8], 15, k9); + Subround(F, d2, a2, b2, c2, X[ 6], 5, k9); + Subround(F, c2, d2, a2, b2, X[ 4], 8, k9); + Subround(F, b2, c2, d2, a2, X[ 1], 11, k9); + Subround(F, a2, b2, c2, d2, X[ 3], 14, k9); + Subround(F, d2, a2, b2, c2, X[11], 14, k9); + Subround(F, c2, d2, a2, b2, X[15], 6, k9); + Subround(F, b2, c2, d2, a2, X[ 0], 14, k9); + Subround(F, a2, b2, c2, d2, X[ 5], 6, k9); + Subround(F, d2, a2, b2, c2, X[12], 9, k9); + Subround(F, c2, d2, a2, b2, X[ 2], 12, k9); + Subround(F, b2, c2, d2, a2, X[13], 9, k9); + Subround(F, a2, b2, c2, d2, X[ 9], 12, k9); + Subround(F, d2, a2, b2, c2, X[ 7], 5, k9); + Subround(F, c2, d2, a2, b2, X[10], 15, k9); + Subround(F, b2, c2, d2, a2, X[14], 8, k9); + + t = d1; d1 = d2; d2 = t; + + digest[0] += a1; + digest[1] += b1; + digest[2] += c1; + digest[3] += d1; + digest[4] += a2; + digest[5] += b2; + digest[6] += c2; + digest[7] += d2; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/ripemd.h b/external/ours/library/crypto/src/shared/original/ripemd.h new file mode 100755 index 000000000..b5fbb4ae8 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/rng.cpp b/external/ours/library/crypto/src/shared/original/rng.cpp new file mode 100755 index 000000000..1bb525e90 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rng.cpp @@ -0,0 +1,166 @@ +// rng.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#include "rng.h" +#include "fips140.h" + +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +// linear congruential generator +// originally by William S. England + +// do not use for cryptographic purposes + +/* +** Original_numbers are the original published m and q in the +** ACM article above. John Burton has furnished numbers for +** a reportedly better generator. The new numbers are now +** used in this program by default. +*/ + +#ifndef LCRNG_ORIGINAL_NUMBERS +const word32 LC_RNG::m=2147483647L; +const word32 LC_RNG::q=44488L; + +const word16 LC_RNG::a=(unsigned int)48271L; +const word16 LC_RNG::r=3399; +#else +const word32 LC_RNG::m=2147483647L; +const word32 LC_RNG::q=127773L; + +const word16 LC_RNG::a=16807; +const word16 LC_RNG::r=2836; +#endif + +void LC_RNG::GenerateBlock(byte *output, size_t size) +{ + while (size--) + { + const word32 hi = seed/q; + const word32 lo = seed%q; + const sword64 test = a*lo - r*hi; + + if (test > 0) + seed = static_cast(test); + else + seed = static_cast(test + m); + + *output++ = byte((GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3))); + } +} + +// ******************************************************** + +#ifndef CRYPTOPP_IMPORTS + +X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *deterministicTimeVector) + : m_cipher(c), + m_size(m_cipher->BlockSize()), + m_datetime(m_size), + m_randseed(seed, m_size), + m_lastBlock(m_size), + m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? m_size : 0) +{ + // Valgrind finding, http://github.com/weidai11/cryptopp/issues/105 + // Garbage in the tail creates a non-conforming X9.17 or X9.31 generator. + if (m_size > 8) + { + memset(m_datetime, 0x00, m_size); + memset(m_lastBlock, 0x00, m_size); + } + + if (!deterministicTimeVector) + { + time_t tstamp1 = ::time(NULLPTR); + xorbuf(m_datetime, (byte *)&tstamp1, UnsignedMin(sizeof(tstamp1), m_size)); + m_cipher->ProcessBlock(m_datetime); + clock_t tstamp2 = clock(); + xorbuf(m_datetime, (byte *)&tstamp2, UnsignedMin(sizeof(tstamp2), m_size)); + m_cipher->ProcessBlock(m_datetime); + } + + // for FIPS 140-2 + // GenerateBlock(m_lastBlock, m_size); + + // Make explicit call to avoid virtual-dispatch findings in ctor + ArraySink target(m_lastBlock, m_size); + X917RNG::GenerateIntoBufferedTransformation(target, DEFAULT_CHANNEL, m_size); +} + +void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size) +{ + while (size > 0) + { + // calculate new enciphered timestamp + if (m_deterministicTimeVector.size()) + { + m_cipher->ProcessBlock(m_deterministicTimeVector, m_datetime); + IncrementCounterByOne(m_deterministicTimeVector, m_size); + } + else + { + clock_t c = clock(); + xorbuf(m_datetime, (byte *)&c, UnsignedMin(sizeof(c), m_size)); + time_t t = ::time(NULLPTR); + xorbuf(m_datetime+m_size-UnsignedMin(sizeof(t), m_size), (byte *)&t, UnsignedMin(sizeof(t), m_size)); + m_cipher->ProcessBlock(m_datetime); + } + + // combine enciphered timestamp with seed + xorbuf(m_randseed, m_datetime, m_size); + + // generate a new block of random bytes + m_cipher->ProcessBlock(m_randseed); + if (memcmp(m_lastBlock, m_randseed, m_size) == 0) + throw SelfTestFailure("X917RNG: Continuous random number generator test failed."); + + // output random bytes + size_t len = UnsignedMin(m_size, size); + target.ChannelPut(channel, m_randseed, len); + size -= len; + + // compute new seed vector + memcpy(m_lastBlock, m_randseed, m_size); + xorbuf(m_randseed, m_datetime, m_size); + m_cipher->ProcessBlock(m_randseed); + } +} + +#endif + +MaurerRandomnessTest::MaurerRandomnessTest() + : sum(0.0), n(0) +{ + for (unsigned i=0; i= Q) + sum += ::log(double(n - tab[inByte])); + tab[inByte] = n; + n++; + } + return 0; +} + +double MaurerRandomnessTest::GetTestValue() const +{ + if (BytesNeeded() > 0) + throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed"); + + double fTu = (sum/(n-Q))/::log(2.0); // this is the test value defined by Maurer + + double value = fTu * 0.1392; // arbitrarily normalize it to + return value > 1.0 ? 1.0 : value; // a number between 0 and 1 +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/rng.h b/external/ours/library/crypto/src/shared/original/rng.h new file mode 100755 index 000000000..7f982ab17 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 distrubuted 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/external/ours/library/crypto/src/shared/original/rsa.cpp b/external/ours/library/crypto/src/shared/original/rsa.cpp new file mode 100755 index 000000000..f3e668664 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rsa.cpp @@ -0,0 +1,330 @@ +// rsa.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "rsa.h" +#include "asn.h" +#include "sha.h" +#include "oids.h" +#include "modarith.h" +#include "nbtheory.h" +#include "algparam.h" +#include "fips140.h" +#include "pkcspad.h" + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) && !defined(CRYPTOPP_IS_DLL) +#include "sha3.h" +#include "pssr.h" +NAMESPACE_BEGIN(CryptoPP) +void RSA_TestInstantiations() +{ + RSASS::Verifier x1(1, 1); + RSASS::Signer x2(NullRNG(), 1); + RSASS::Verifier x3(x2); + RSASS::Verifier x4(x2.GetKey()); + RSASS::Verifier x5(x3); +#ifndef __MWERKS__ + RSASS::Signer x6 = x2; + x3 = x2; + x6 = x2; +#endif + RSAES::Encryptor x7(x2); +#ifndef __GNUC__ + RSAES::Encryptor x8(x3); +#endif + RSAES >::Encryptor x9(x2); + x4 = x2.GetKey(); + + RSASS::Verifier x10(1, 1); + RSASS::Signer x11(NullRNG(), 1); + RSASS::Verifier x12(x11); + RSASS::Verifier x13(x11.GetKey()); +} +NAMESPACE_END +#endif + +#ifndef CRYPTOPP_IMPORTS + +NAMESPACE_BEGIN(CryptoPP) + +OID RSAFunction::GetAlgorithmID() const +{ + return ASN1::rsaEncryption(); +} + +void RSAFunction::BERDecodePublicKey(BufferedTransformation &bt, bool, size_t) +{ + BERSequenceDecoder seq(bt); + m_n.BERDecode(seq); + m_e.BERDecode(seq); + seq.MessageEnd(); +} + +void RSAFunction::DEREncodePublicKey(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + m_n.DEREncode(seq); + m_e.DEREncode(seq); + seq.MessageEnd(); +} + +Integer RSAFunction::ApplyFunction(const Integer &x) const +{ + DoQuickSanityCheck(); + return a_exp_b_mod_c(x, m_e, m_n); +} + +bool RSAFunction::Validate(RandomNumberGenerator& rng, unsigned int level) const +{ + CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(level); + + bool pass = true; + pass = pass && m_n > Integer::One() && m_n.IsOdd(); + CRYPTOPP_ASSERT(pass); + pass = pass && m_e > Integer::One() && m_e.IsOdd() && m_e < m_n; + CRYPTOPP_ASSERT(pass); + return pass; +} + +bool RSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent) + ; +} + +void RSAFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent) + ; +} + +// ***************************************************************************** + +class RSAPrimeSelector : public PrimeSelector +{ +public: + RSAPrimeSelector(const Integer &e) : m_e(e) {} + bool IsAcceptable(const Integer &candidate) const {return RelativelyPrime(m_e, candidate-Integer::One());} + Integer m_e; +}; + +void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + int modulusSize = 2048; + alg.GetIntValue(Name::ModulusSize(), modulusSize) || alg.GetIntValue(Name::KeySize(), modulusSize); + + CRYPTOPP_ASSERT(modulusSize >= 16); + if (modulusSize < 16) + throw InvalidArgument("InvertibleRSAFunction: specified modulus size is too small"); + + m_e = alg.GetValueWithDefault(Name::PublicExponent(), Integer(17)); + + CRYPTOPP_ASSERT(m_e >= 3); CRYPTOPP_ASSERT(!m_e.IsEven()); + if (m_e < 3 || m_e.IsEven()) + throw InvalidArgument("InvertibleRSAFunction: invalid public exponent"); + + RSAPrimeSelector selector(m_e); + AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize) + (Name::PointerToPrimeSelector(), selector.GetSelectorPointer()); + m_p.GenerateRandom(rng, primeParam); + m_q.GenerateRandom(rng, primeParam); + + m_d = m_e.InverseMod(LCM(m_p-1, m_q-1)); + CRYPTOPP_ASSERT(m_d.IsPositive()); + + m_dp = m_d % (m_p-1); + m_dq = m_d % (m_q-1); + m_n = m_p * m_q; + m_u = m_q.InverseMod(m_p); + + if (FIPS_140_2_ComplianceEnabled()) + { + RSASS::Signer signer(*this); + RSASS::Verifier verifier(signer); + SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier); + + RSAES >::Decryptor decryptor(*this); + RSAES >::Encryptor encryptor(decryptor); + EncryptionPairwiseConsistencyTest_FIPS_140_Only(encryptor, decryptor); + } +} + +void InvertibleRSAFunction::Initialize(RandomNumberGenerator &rng, unsigned int keybits, const Integer &e) +{ + GenerateRandom(rng, MakeParameters(Name::ModulusSize(), (int)keybits)(Name::PublicExponent(), e+e.IsEven())); +} + +void InvertibleRSAFunction::Initialize(const Integer &n, const Integer &e, const Integer &d) +{ + if (n.IsEven() || e.IsEven() | d.IsEven()) + throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key"); + + m_n = n; + m_e = e; + m_d = d; + + Integer r = --(d*e); + unsigned int s = 0; + while (r.IsEven()) + { + r >>= 1; + s++; + } + + ModularArithmetic modn(n); + for (Integer i = 2; ; ++i) + { + Integer a = modn.Exponentiate(i, r); + if (a == 1) + continue; + Integer b; + unsigned int j = 0; + while (a != n-1) + { + b = modn.Square(a); + if (b == 1) + { + m_p = GCD(a-1, n); + m_q = n/m_p; + m_dp = m_d % (m_p-1); + m_dq = m_d % (m_q-1); + m_u = m_q.InverseMod(m_p); + return; + } + if (++j == s) + throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key"); + a = b; + } + } +} + +void InvertibleRSAFunction::BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t) +{ + BERSequenceDecoder privateKey(bt); + word32 version; + BERDecodeUnsigned(privateKey, version, INTEGER, 0, 0); // check version + m_n.BERDecode(privateKey); + m_e.BERDecode(privateKey); + m_d.BERDecode(privateKey); + m_p.BERDecode(privateKey); + m_q.BERDecode(privateKey); + m_dp.BERDecode(privateKey); + m_dq.BERDecode(privateKey); + m_u.BERDecode(privateKey); + privateKey.MessageEnd(); +} + +void InvertibleRSAFunction::DEREncodePrivateKey(BufferedTransformation &bt) const +{ + DERSequenceEncoder privateKey(bt); + DEREncodeUnsigned(privateKey, 0); // version + m_n.DEREncode(privateKey); + m_e.DEREncode(privateKey); + m_d.DEREncode(privateKey); + m_p.DEREncode(privateKey); + m_q.DEREncode(privateKey); + m_dp.DEREncode(privateKey); + m_dq.DEREncode(privateKey); + m_u.DEREncode(privateKey); + privateKey.MessageEnd(); +} + +Integer InvertibleRSAFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const +{ + DoQuickSanityCheck(); + ModularArithmetic modn(m_n); + Integer r, rInv; + do { // do this in a loop for people using small numbers for testing + r.Randomize(rng, Integer::One(), m_n - Integer::One()); + rInv = modn.MultiplicativeInverse(r); + } while (rInv.IsZero()); + Integer re = modn.Exponentiate(r, m_e); + re = modn.Multiply(re, x); // blind + // here we follow the notation of PKCS #1 and let u=q inverse mod p + // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q + Integer y = ModularRoot(re, m_dq, m_dp, m_q, m_p, m_u); + y = modn.Multiply(y, rInv); // unblind + if (modn.Exponentiate(y, m_e) != x) // check + throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: computational error during private key operation"); + return y; +} + +bool InvertibleRSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = RSAFunction::Validate(rng, level); + CRYPTOPP_ASSERT(pass); + pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_d > Integer::One() && m_d.IsOdd() && m_d < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_dp > Integer::One() && m_dp.IsOdd() && m_dp < m_p; + CRYPTOPP_ASSERT(pass); + pass = pass && m_dq > Integer::One() && m_dq.IsOdd() && m_dq < m_q; + CRYPTOPP_ASSERT(pass); + pass = pass && m_u.IsPositive() && m_u < m_p; + CRYPTOPP_ASSERT(pass); + if (level >= 1) + { + pass = pass && m_p * m_q == m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_e*m_d % LCM(m_p-1, m_q-1) == 1; + CRYPTOPP_ASSERT(pass); + pass = pass && m_dp == m_d%(m_p-1) && m_dq == m_d%(m_q-1); + CRYPTOPP_ASSERT(pass); + pass = pass && m_u * m_q % m_p == 1; + CRYPTOPP_ASSERT(pass); + } + if (level >= 2) + { + pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2); + CRYPTOPP_ASSERT(pass); + } + return pass; +} + +bool InvertibleRSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_GET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent) + CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime1PrivateExponent) + CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime2PrivateExponent) + CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; +} + +void InvertibleRSAFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent) + CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime1PrivateExponent) + CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime2PrivateExponent) + CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; +} + +// ***************************************************************************** + +Integer RSAFunction_ISO::ApplyFunction(const Integer &x) const +{ + Integer t = RSAFunction::ApplyFunction(x); + return t % 16 == 12 ? t : m_n - t; +} + +Integer InvertibleRSAFunction_ISO::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const +{ + Integer t = InvertibleRSAFunction::CalculateInverse(rng, x); + return STDMIN(t, m_n-t); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/rsa.h b/external/ours/library/crypto/src/shared/original/rsa.h new file mode 100755 index 000000000..62c1111ea --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rsa.h @@ -0,0 +1,263 @@ +// 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 +DOCUMENTED_TYPEDEF(RSAES::Decryptor, RSAES_PKCS1v15_Decryptor); +/// \brief \ref RSAES "RSAES::Encryptor" typedef +/// \details RSA encryption scheme defined in PKCS #1 v2.0 +DOCUMENTED_TYPEDEF(RSAES::Encryptor, RSAES_PKCS1v15_Encryptor); + +/// \brief \ref RSAES "RSAES>::Decryptor" typedef +/// \details RSA encryption scheme defined in PKCS #1 v2.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 +DOCUMENTED_TYPEDEF(RSAES >::Encryptor, RSAES_OAEP_SHA_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 {}; + +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; + +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/external/ours/library/crypto/src/shared/original/rw.cpp b/external/ours/library/crypto/src/shared/original/rw.cpp new file mode 100755 index 000000000..ab79358cb --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/rw.cpp @@ -0,0 +1,314 @@ +// rw.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#include "rw.h" +#include "asn.h" +#include "integer.h" +#include "nbtheory.h" +#include "modarith.h" +#include "asn.h" + +#ifndef CRYPTOPP_IMPORTS + +#if defined(_OPENMP) +# define CRYPTOPP_RW_USE_OMP 1 +#else +# define CRYPTOPP_RW_USE_OMP 0 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +void RWFunction::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + m_n.BERDecode(seq); + seq.MessageEnd(); +} + +void RWFunction::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + m_n.DEREncode(seq); + seq.MessageEnd(); +} + +Integer RWFunction::ApplyFunction(const Integer &in) const +{ + DoQuickSanityCheck(); + + Integer out = in.Squared()%m_n; + const word r = 12; + // this code was written to handle both r = 6 and r = 12, + // but now only r = 12 is used in P1363 + const word r2 = r/2; + const word r3a = (16 + 5 - r) % 16; // n%16 could be 5 or 13 + const word r3b = (16 + 13 - r) % 16; + const word r4 = (8 + 5 - r/2) % 8; // n%8 == 5 + switch (out % 16) + { + case r: + break; + case r2: + case r2+8: + out <<= 1; + break; + case r3a: + case r3b: + out.Negate(); + out += m_n; + break; + case r4: + case r4+8: + out.Negate(); + out += m_n; + out <<= 1; + break; + default: + out = Integer::Zero(); + } + return out; +} + +bool RWFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(level); + bool pass = true; + pass = pass && m_n > Integer::One() && m_n%8 == 5; + CRYPTOPP_ASSERT(pass); + return pass; +} + +bool RWFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Modulus) + ; +} + +void RWFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Modulus) + ; +} + +// ***************************************************************************** +// private key operations: + +// generate a random private key +void InvertibleRWFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + int modulusSize = 2048; + alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize); + + if (modulusSize < 16) + throw InvalidArgument("InvertibleRWFunction: specified modulus length is too small"); + + AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize); + m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("EquivalentTo", 3)("Mod", 8))); + m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("EquivalentTo", 7)("Mod", 8))); + + m_n = m_p * m_q; + m_u = m_q.InverseMod(m_p); + + Precompute(); +} + +void InvertibleRWFunction::Initialize(const Integer &n, const Integer &p, const Integer &q, const Integer &u) +{ + m_n = n; m_p = p; m_q = q; m_u = u; + + Precompute(); +} + +void InvertibleRWFunction::PrecomputeTweakedRoots() const +{ + ModularArithmetic modp(m_p), modq(m_q); + + // GCC warning bug, https://stackoverflow.com/q/12842306/608639 +#ifdef _OPENMP + #pragma omp parallel sections if(CRYPTOPP_RW_USE_OMP) + { + #pragma omp section + m_pre_2_9p = modp.Exponentiate(2, (9 * m_p - 11)/8); + #pragma omp section + m_pre_2_3q = modq.Exponentiate(2, (3 * m_q - 5)/8); + #pragma omp section + m_pre_q_p = modp.Exponentiate(m_q, m_p - 2); + } +#else + m_pre_2_9p = modp.Exponentiate(2, (9 * m_p - 11)/8); + m_pre_2_3q = modq.Exponentiate(2, (3 * m_q - 5)/8); + m_pre_q_p = modp.Exponentiate(m_q, m_p - 2); +#endif + + m_precompute = true; +} + +void InvertibleRWFunction::LoadPrecomputation(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + m_pre_2_9p.BERDecode(seq); + m_pre_2_3q.BERDecode(seq); + m_pre_q_p.BERDecode(seq); + seq.MessageEnd(); + + m_precompute = true; +} + +void InvertibleRWFunction::SavePrecomputation(BufferedTransformation &bt) const +{ + if(!m_precompute) + Precompute(); + + DERSequenceEncoder seq(bt); + m_pre_2_9p.DEREncode(seq); + m_pre_2_3q.DEREncode(seq); + m_pre_q_p.DEREncode(seq); + seq.MessageEnd(); +} + +void InvertibleRWFunction::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + m_n.BERDecode(seq); + m_p.BERDecode(seq); + m_q.BERDecode(seq); + m_u.BERDecode(seq); + seq.MessageEnd(); + + m_precompute = false; +} + +void InvertibleRWFunction::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + m_n.DEREncode(seq); + m_p.DEREncode(seq); + m_q.DEREncode(seq); + m_u.DEREncode(seq); + seq.MessageEnd(); +} + +// DJB's "RSA signatures and Rabin-Williams signatures..." (http://cr.yp.to/sigs/rwsota-20080131.pdf). +Integer InvertibleRWFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const +{ + DoQuickSanityCheck(); + + if(!m_precompute) + Precompute(); + + ModularArithmetic modn(m_n), modp(m_p), modq(m_q); + Integer r, rInv; + + do + { + // Do this in a loop for people using small numbers for testing + r.Randomize(rng, Integer::One(), m_n - Integer::One()); + // Fix for CVE-2015-2141. Thanks to Evgeny Sidorov for reporting. + // Squaring to satisfy Jacobi requirements suggested by Jean-Pierre Munch. + r = modn.Square(r); + rInv = modn.MultiplicativeInverse(r); + } while (rInv.IsZero()); + + Integer re = modn.Square(r); + re = modn.Multiply(re, x); // blind + + const Integer &h = re, &p = m_p, &q = m_q; + Integer e, f; + + const Integer U = modq.Exponentiate(h, (q+1)/8); + if(((modq.Exponentiate(U, 4) - h) % q).IsZero()) + e = Integer::One(); + else + e = -1; + + const Integer eh = e*h, V = modp.Exponentiate(eh, (p-3)/8); + if(((modp.Multiply(modp.Exponentiate(V, 4), modp.Exponentiate(eh, 2)) - eh) % p).IsZero()) + f = Integer::One(); + else + f = 2; + +#ifdef _OPENMP + Integer W, X; + #pragma omp parallel sections if(CRYPTOPP_RW_USE_OMP) + { + #pragma omp section + { + W = (f.IsUnit() ? U : modq.Multiply(m_pre_2_3q, U)); + } + #pragma omp section + { + const Integer t = modp.Multiply(modp.Exponentiate(V, 3), eh); + X = (f.IsUnit() ? t : modp.Multiply(m_pre_2_9p, t)); + } + } +#else + const Integer W = (f.IsUnit() ? U : modq.Multiply(m_pre_2_3q, U)); + const Integer t = modp.Multiply(modp.Exponentiate(V, 3), eh); + const Integer X = (f.IsUnit() ? t : modp.Multiply(m_pre_2_9p, t)); +#endif + + const Integer Y = W + q * modp.Multiply(m_pre_q_p, (X - W)); + + // Signature + Integer s = modn.Multiply(modn.Square(Y), rInv); + CRYPTOPP_ASSERT((e * f * s.Squared()) % m_n == x); + + // IEEE P1363, Section 8.2.8 IFSP-RW, p.44 + s = STDMIN(s, m_n - s); + if (ApplyFunction(s) != x) // check + throw Exception(Exception::OTHER_ERROR, "InvertibleRWFunction: computational error during private key operation"); + + return s; +} + +bool InvertibleRWFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = RWFunction::Validate(rng, level); + CRYPTOPP_ASSERT(pass); + pass = pass && m_p > Integer::One() && m_p%8 == 3 && m_p < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_q > Integer::One() && m_q%8 == 7 && m_q < m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_u.IsPositive() && m_u < m_p; + CRYPTOPP_ASSERT(pass); + if (level >= 1) + { + pass = pass && m_p * m_q == m_n; + CRYPTOPP_ASSERT(pass); + pass = pass && m_u * m_q % m_p == 1; + CRYPTOPP_ASSERT(pass); + } + if (level >= 2) + { + pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2); + CRYPTOPP_ASSERT(pass); + } + return pass; +} + +bool InvertibleRWFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_GET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; +} + +void InvertibleRWFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; + + m_precompute = false; +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/rw.h b/external/ours/library/crypto/src/shared/original/rw.h new file mode 100755 index 000000000..48aa28915 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/safer.cpp b/external/ours/library/crypto/src/shared/original/safer.cpp new file mode 100755 index 000000000..83f415175 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/safer.cpp @@ -0,0 +1,157 @@ +// safer.cpp - modified by by Wei Dai from Richard De Moliner's safer.c + +#include "pch.h" +#include "safer.h" +#include "misc.h" +#include "argnames.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4244) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +const byte SAFER::Base::exp_tab[256] = + {1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63, + 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247, + 64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, + 255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, + 241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, + 129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, + 4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, + 32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217, + 0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194, + 249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10, + 193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80, + 2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126, + 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237, + 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97, + 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5, + 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40}; + +const byte SAFER::Base::log_tab[256] = + {128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248, + 192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130, + 112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37, + 201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15, + 32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198, + 175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84, + 121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188, + 189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217, + 208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158, + 210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42, + 95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219, + 164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29, + 41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14, + 122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104, + 109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66, + 184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48}; + +#define EXP(x) exp_tab[(x)] +#define LOG(x) log_tab[(x)] +#define PHT(x, y) { y += x; x += y; } +#define IPHT(x, y) { x -= y; y -= x; } + +static const unsigned int BLOCKSIZE = 8; +static const unsigned int MAX_ROUNDS = 13; + +void SAFER::Base::UncheckedSetKey(const byte *userkey_1, unsigned int length, const NameValuePairs ¶ms) +{ + bool strengthened = Strengthened(); + unsigned int nof_rounds = params.GetIntValueWithDefault(Name::Rounds(), length == 8 ? (strengthened ? 8 : 6) : 10); + + const byte *userkey_2 = length == 8 ? userkey_1 : userkey_1 + 8; + keySchedule.New(1 + BLOCKSIZE * (1 + 2 * nof_rounds)); + + unsigned int i, j; + byte *key = keySchedule; + SecByteBlock ka(BLOCKSIZE + 1), kb(BLOCKSIZE + 1); + + if (MAX_ROUNDS < nof_rounds) + nof_rounds = MAX_ROUNDS; + *key++ = (unsigned char)nof_rounds; + ka[BLOCKSIZE] = 0; + kb[BLOCKSIZE] = 0; + for (j = 0; j < BLOCKSIZE; j++) + { + ka[BLOCKSIZE] ^= ka[j] = rotlConstant<5>(userkey_1[j]); + kb[BLOCKSIZE] ^= kb[j] = *key++ = userkey_2[j]; + } + + for (i = 1; i <= nof_rounds; i++) + { + for (j = 0; j < BLOCKSIZE + 1; j++) + { + ka[j] = rotlConstant<6>(ka[j]); + kb[j] = rotlConstant<6>(kb[j]); + } + for (j = 0; j < BLOCKSIZE; j++) + if (strengthened) + *key++ = (ka[(j + 2 * i - 1) % (BLOCKSIZE + 1)] + + exp_tab[exp_tab[18 * i + j + 1]]) & 0xFF; + else + *key++ = (ka[j] + exp_tab[exp_tab[18 * i + j + 1]]) & 0xFF; + for (j = 0; j < BLOCKSIZE; j++) + if (strengthened) + *key++ = (kb[(j + 2 * i) % (BLOCKSIZE + 1)] + + exp_tab[exp_tab[18 * i + j + 10]]) & 0xFF; + else + *key++ = (kb[j] + exp_tab[exp_tab[18 * i + j + 10]]) & 0xFF; + } +} + +typedef BlockGetAndPut Block; + +void SAFER::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + byte a, b, c, d, e, f, g, h, t; + const byte *key = keySchedule+1; + unsigned int round = keySchedule[0]; + + Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h); + while(round--) + { + a ^= key[0]; b += key[1]; c += key[2]; d ^= key[3]; + e ^= key[4]; f += key[5]; g += key[6]; h ^= key[7]; + a = EXP(a) + key[ 8]; b = LOG(b) ^ key[ 9]; + c = LOG(c) ^ key[10]; d = EXP(d) + key[11]; + e = EXP(e) + key[12]; f = LOG(f) ^ key[13]; + g = LOG(g) ^ key[14]; h = EXP(h) + key[15]; + key += 16; + PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h); + PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h); + PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h); + t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t; + } + a ^= key[0]; b += key[1]; c += key[2]; d ^= key[3]; + e ^= key[4]; f += key[5]; g += key[6]; h ^= key[7]; + Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h); +} + +void SAFER::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + byte a, b, c, d, e, f, g, h, t; + unsigned int round = keySchedule[0]; + const byte *key = keySchedule + BLOCKSIZE * (1 + 2 * round) - 7; + + Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h); + h ^= key[7]; g -= key[6]; f -= key[5]; e ^= key[4]; + d ^= key[3]; c -= key[2]; b -= key[1]; a ^= key[0]; + while (round--) + { + key -= 16; + t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t; + IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h); + IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h); + IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h); + h -= key[15]; g ^= key[14]; f ^= key[13]; e -= key[12]; + d -= key[11]; c ^= key[10]; b ^= key[9]; a -= key[8]; + h = LOG(h) ^ key[7]; g = EXP(g) - key[6]; + f = EXP(f) - key[5]; e = LOG(e) ^ key[4]; + d = LOG(d) ^ key[3]; c = EXP(c) - key[2]; + b = EXP(b) - key[1]; a = LOG(a) ^ key[0]; + } + Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/safer.h b/external/ours/library/crypto/src/shared/original/safer.h new file mode 100755 index 000000000..b28ad82cc --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/salsa.cpp b/external/ours/library/crypto/src/shared/original/salsa.cpp new file mode 100755 index 000000000..987cd3022 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/salsa.cpp @@ -0,0 +1,759 @@ +// salsa.cpp - originally written and placed in the public domain by Wei Dai + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM salsa.cpp" to generate MASM code + +#include "pch.h" +#include "config.h" + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#include "salsa.h" +#include "argnames.h" +#include "misc.h" +#include "cpu.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4702 4740) +#endif + +// Clang due to "Inline assembly operands don't work with .intel_syntax" +// https://llvm.org/bugs/show_bug.cgi?id=24232 +#if defined(CRYPTOPP_DISABLE_SALSA_ASM) +# undef CRYPTOPP_X86_ASM_AVAILABLE +# undef CRYPTOPP_X32_ASM_AVAILABLE +# undef CRYPTOPP_X64_ASM_AVAILABLE +# undef CRYPTOPP_SSE2_ASM_AVAILABLE +# undef CRYPTOPP_SSSE3_ASM_AVAILABLE +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +// Can't use GetAlignmentOf() because of C++11 and constexpr +// Can use 'const unsigned int' because of MSVC 2013 +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +# define ALIGN_SPEC 16 +#else +# define ALIGN_SPEC 4 +#endif + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void Salsa20_TestInstantiations() +{ + Salsa20::Encryption x1; + XSalsa20::Encryption x2; +} +#endif + +void Salsa20_Core(word32* data, unsigned int rounds) +{ + CRYPTOPP_ASSERT(data != NULLPTR); + CRYPTOPP_ASSERT(rounds % 2 == 0); + + CRYPTOPP_ALIGN_DATA(ALIGN_SPEC) word32 x[16]; + + for (size_t i = 0; i < 16; ++i) + x[i] = data[i]; + + // Rounds must be even + for (size_t i = 0; i < rounds; i += 2) + { + x[ 4] ^= rotlConstant< 7>(x[ 0]+x[12]); + x[ 8] ^= rotlConstant< 9>(x[ 4]+x[ 0]); + x[12] ^= rotlConstant<13>(x[ 8]+x[ 4]); + x[ 0] ^= rotlConstant<18>(x[12]+x[ 8]); + + x[ 9] ^= rotlConstant< 7>(x[ 5]+x[ 1]); + x[13] ^= rotlConstant< 9>(x[ 9]+x[ 5]); + x[ 1] ^= rotlConstant<13>(x[13]+x[ 9]); + x[ 5] ^= rotlConstant<18>(x[ 1]+x[13]); + + x[14] ^= rotlConstant< 7>(x[10]+x[ 6]); + x[ 2] ^= rotlConstant< 9>(x[14]+x[10]); + x[ 6] ^= rotlConstant<13>(x[ 2]+x[14]); + x[10] ^= rotlConstant<18>(x[ 6]+x[ 2]); + + x[ 3] ^= rotlConstant< 7>(x[15]+x[11]); + x[ 7] ^= rotlConstant< 9>(x[ 3]+x[15]); + x[11] ^= rotlConstant<13>(x[ 7]+x[ 3]); + x[15] ^= rotlConstant<18>(x[11]+x[ 7]); + + x[ 1] ^= rotlConstant< 7>(x[ 0]+x[ 3]); + x[ 2] ^= rotlConstant< 9>(x[ 1]+x[ 0]); + x[ 3] ^= rotlConstant<13>(x[ 2]+x[ 1]); + x[ 0] ^= rotlConstant<18>(x[ 3]+x[ 2]); + + x[ 6] ^= rotlConstant< 7>(x[ 5]+x[ 4]); + x[ 7] ^= rotlConstant< 9>(x[ 6]+x[ 5]); + x[ 4] ^= rotlConstant<13>(x[ 7]+x[ 6]); + x[ 5] ^= rotlConstant<18>(x[ 4]+x[ 7]); + + x[11] ^= rotlConstant< 7>(x[10]+x[ 9]); + x[ 8] ^= rotlConstant< 9>(x[11]+x[10]); + x[ 9] ^= rotlConstant<13>(x[ 8]+x[11]); + x[10] ^= rotlConstant<18>(x[ 9]+x[ 8]); + + x[12] ^= rotlConstant< 7>(x[15]+x[14]); + x[13] ^= rotlConstant< 9>(x[12]+x[15]); + x[14] ^= rotlConstant<13>(x[13]+x[12]); + x[15] ^= rotlConstant<18>(x[14]+x[13]); + } + +// OpenMP 4.0 released July 2013. +#if _OPENMP >= 201307 + #pragma omp simd + for (size_t i = 0; i < 16; ++i) + data[i] += x[i]; +#else + for (size_t i = 0; i < 16; ++i) + data[i] += x[i]; +#endif +} + +std::string Salsa20_Policy::AlgorithmProvider() const +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE && !defined(CRYPTOPP_DISABLE_SALSA_ASM) + if (HasSSE2()) + return "SSE2"; +#endif + return "C++"; +} + +void Salsa20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + // Use previous rounds as the default value + int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds); + if (rounds != 20 && rounds != 12 && rounds != 8) + throw InvalidRounds(Salsa20::StaticAlgorithmName(), rounds); + + // Latch a good value + m_rounds = rounds; + + // m_state is reordered for SSE2 + GetBlock get1(key); + get1(m_state[13])(m_state[10])(m_state[7])(m_state[4]); + GetBlock get2(key + length - 16); + get2(m_state[15])(m_state[12])(m_state[9])(m_state[6]); + + // "expand 16-byte k" or "expand 32-byte k" + m_state[0] = 0x61707865; + m_state[1] = (length == 16) ? 0x3120646e : 0x3320646e; + m_state[2] = (length == 16) ? 0x79622d36 : 0x79622d32; + m_state[3] = 0x6b206574; +} + +void Salsa20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length==8); + + GetBlock get(IV); + get(m_state[14])(m_state[11]); + m_state[8] = m_state[5] = 0; +} + +void Salsa20_Policy::SeekToIteration(lword iterationCount) +{ + m_state[8] = (word32)iterationCount; + m_state[5] = (word32)SafeRightShift<32>(iterationCount); +} + +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +unsigned int Salsa20_Policy::GetAlignment() const +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return 16; + else +#endif + return GetAlignmentOf(); +} + +unsigned int Salsa20_Policy::GetOptimalBlockSize() const +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return 4*BYTES_PER_ITERATION; + else +#endif + return BYTES_PER_ITERATION; +} +#endif + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void Salsa20_OperateKeystream(byte *output, const byte *input, size_t iterationCount, int rounds, void *state); +} +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code +#endif + +void Salsa20_Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ +#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE + Salsa20_OperateKeystream(output, input, iterationCount, m_rounds, m_state.data()); + return; +#endif + +#if CRYPTOPP_SSE2_ASM_AVAILABLE +#ifdef CRYPTOPP_GENERATE_X64_MASM + ALIGN 8 + Salsa20_OperateKeystream PROC FRAME + mov r10, [rsp + 5*8] ; state + alloc_stack(10*16 + 32*16 + 8) + save_xmm128 xmm6, 0200h + save_xmm128 xmm7, 0210h + save_xmm128 xmm8, 0220h + save_xmm128 xmm9, 0230h + save_xmm128 xmm10, 0240h + save_xmm128 xmm11, 0250h + save_xmm128 xmm12, 0260h + save_xmm128 xmm13, 0270h + save_xmm128 xmm14, 0280h + save_xmm128 xmm15, 0290h + .endprolog + + #define REG_output rcx + #define REG_input rdx + #define REG_iterationCount r8 + #define REG_state r10 + #define REG_rounds e9d + #define REG_roundsLeft eax + #define REG_temp32 r11d + #define REG_temp r11 + #define SSE2_WORKSPACE rsp +#else + if (HasSSE2()) + { + #if CRYPTOPP_BOOL_X64 + #define REG_output %1 + #define REG_input %0 + #define REG_iterationCount %2 + #define REG_state %4 /* constant */ + #define REG_rounds %3 /* constant */ + #define REG_roundsLeft eax + #define REG_temp32 edx + #define REG_temp rdx + #define SSE2_WORKSPACE %5 /* constant */ + + CRYPTOPP_ALIGN_DATA(16) byte workspace[16*32]; + #else + #define REG_output edi + #define REG_input eax + #define REG_iterationCount ecx + #define REG_state esi + #define REG_rounds edx + #define REG_roundsLeft ebx + #define REG_temp32 ebp + #define REG_temp ebp + #define SSE2_WORKSPACE esp + WORD_SZ + #endif + + #ifdef __GNUC__ + __asm__ __volatile__ + ( + INTEL_NOPREFIX + AS_PUSH_IF86( bx) + #else + void *s = m_state.data(); + word32 r = m_rounds; + + AS2( mov REG_iterationCount, iterationCount) + AS2( mov REG_input, input) + AS2( mov REG_output, output) + AS2( mov REG_state, s) + AS2( mov REG_rounds, r) + #endif +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM + + AS_PUSH_IF86( bp) + AS2( cmp REG_iterationCount, 4) + ASJ( jl, 5, f) + +#if CRYPTOPP_BOOL_X86 + AS2( mov ebx, esp) + AS2( and esp, -16) + AS2( sub esp, 32*16) + AS1( push ebx) +#endif + +#define SSE2_EXPAND_S(i, j) \ + ASS( pshufd xmm4, xmm##i, j, j, j, j) \ + AS2( movdqa [SSE2_WORKSPACE + (i*4+j)*16 + 256], xmm4) + + AS2( movdqa xmm0, [REG_state + 0*16]) + AS2( movdqa xmm1, [REG_state + 1*16]) + AS2( movdqa xmm2, [REG_state + 2*16]) + AS2( movdqa xmm3, [REG_state + 3*16]) + SSE2_EXPAND_S(0, 0) + SSE2_EXPAND_S(0, 1) + SSE2_EXPAND_S(0, 2) + SSE2_EXPAND_S(0, 3) + SSE2_EXPAND_S(1, 0) + SSE2_EXPAND_S(1, 2) + SSE2_EXPAND_S(1, 3) + SSE2_EXPAND_S(2, 1) + SSE2_EXPAND_S(2, 2) + SSE2_EXPAND_S(2, 3) + SSE2_EXPAND_S(3, 0) + SSE2_EXPAND_S(3, 1) + SSE2_EXPAND_S(3, 2) + SSE2_EXPAND_S(3, 3) + +#define SSE2_EXPAND_S85(i) \ + AS2( mov dword ptr [SSE2_WORKSPACE + 8*16 + i*4 + 256], REG_roundsLeft) \ + AS2( mov dword ptr [SSE2_WORKSPACE + 5*16 + i*4 + 256], REG_temp32) \ + AS2( add REG_roundsLeft, 1) \ + AS2( adc REG_temp32, 0) + + ASL(1) + AS2( mov REG_roundsLeft, dword ptr [REG_state + 8*4]) + AS2( mov REG_temp32, dword ptr [REG_state + 5*4]) + SSE2_EXPAND_S85(0) + SSE2_EXPAND_S85(1) + SSE2_EXPAND_S85(2) + SSE2_EXPAND_S85(3) + AS2( mov dword ptr [REG_state + 8*4], REG_roundsLeft) + AS2( mov dword ptr [REG_state + 5*4], REG_temp32) + +#ifdef __XOP__ +#define SSE2_QUARTER_ROUND(a, b, d, i) \ + AS2( movdqa xmm4, xmm##d) \ + AS2( paddd xmm4, xmm##a) \ + AS3( vprotd xmm4, xmm4, i) \ + AS2( pxor xmm##b, xmm4) +#else +#define SSE2_QUARTER_ROUND(a, b, d, i) \ + AS2( movdqa xmm4, xmm##d) \ + AS2( paddd xmm4, xmm##a) \ + AS2( movdqa xmm5, xmm4) \ + AS2( pslld xmm4, i) \ + AS2( psrld xmm5, 32-i) \ + AS2( pxor xmm##b, xmm4) \ + AS2( pxor xmm##b, xmm5) +#endif + +#define L01(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##A, [SSE2_WORKSPACE + d*16 + i*256]) /* y3 */ +#define L02(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##C, [SSE2_WORKSPACE + a*16 + i*256]) /* y0 */ +#define L03(A,B,C,D,a,b,c,d,i) AS2( paddd xmm##A, xmm##C) /* y0+y3 */ + +#ifdef __XOP__ +#define L04(A,B,C,D,a,b,c,d,i) +#define L05(A,B,C,D,a,b,c,d,i) AS3( vprotd xmm##A, xmm##A, 7) +#define L06(A,B,C,D,a,b,c,d,i) +#define L07(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, [SSE2_WORKSPACE + b*16 + i*256]) +#define L08(A,B,C,D,a,b,c,d,i) +#else +#define L04(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##B, xmm##A) +#define L05(A,B,C,D,a,b,c,d,i) AS2( pslld xmm##A, 7) +#define L06(A,B,C,D,a,b,c,d,i) AS2( psrld xmm##B, 32-7) +#define L07(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, [SSE2_WORKSPACE + b*16 + i*256]) +#define L08(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##B) /* z1 */ +#endif + +#define L09(A,B,C,D,a,b,c,d,i) AS2( movdqa [SSE2_WORKSPACE + b*16], xmm##A) +#define L10(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##B, xmm##A) +#define L11(A,B,C,D,a,b,c,d,i) AS2( paddd xmm##A, xmm##C) /* z1+y0 */ + +#ifdef __XOP__ +#define L12(A,B,C,D,a,b,c,d,i) +#define L13(A,B,C,D,a,b,c,d,i) AS3( vprotd xmm##A, xmm##A, 9) +#define L14(A,B,C,D,a,b,c,d,i) +#define L15(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, [SSE2_WORKSPACE + c*16 + i*256]) +#define L16(A,B,C,D,a,b,c,d,i) +#else +#define L12(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##D, xmm##A) +#define L13(A,B,C,D,a,b,c,d,i) AS2( pslld xmm##A, 9) +#define L14(A,B,C,D,a,b,c,d,i) AS2( psrld xmm##D, 32-9) +#define L15(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, [SSE2_WORKSPACE + c*16 + i*256]) +#define L16(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##D) /* z2 */ +#endif + +#define L17(A,B,C,D,a,b,c,d,i) AS2( movdqa [SSE2_WORKSPACE + c*16], xmm##A) +#define L18(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##D, xmm##A) +#define L19(A,B,C,D,a,b,c,d,i) AS2( paddd xmm##A, xmm##B) /* z2+z1 */ + +#ifdef __XOP__ +#define L20(A,B,C,D,a,b,c,d,i) +#define L21(A,B,C,D,a,b,c,d,i) AS3( vprotd xmm##A, xmm##A, 13) +#define L22(A,B,C,D,a,b,c,d,i) +#define L23(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, [SSE2_WORKSPACE + d*16 + i*256]) +#define L24(A,B,C,D,a,b,c,d,i) +#else +#define L20(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##B, xmm##A) +#define L21(A,B,C,D,a,b,c,d,i) AS2( pslld xmm##A, 13) +#define L22(A,B,C,D,a,b,c,d,i) AS2( psrld xmm##B, 32-13) +#define L23(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, [SSE2_WORKSPACE + d*16 + i*256]) +#define L24(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##B) /* z3 */ +#endif + +#define L25(A,B,C,D,a,b,c,d,i) AS2( movdqa [SSE2_WORKSPACE + d*16], xmm##A) +#define L26(A,B,C,D,a,b,c,d,i) AS2( paddd xmm##A, xmm##D) /* z3+z2 */ + +#ifdef __XOP__ +#define L27(A,B,C,D,a,b,c,d,i) +#define L28(A,B,C,D,a,b,c,d,i) AS3( vprotd xmm##A, xmm##A, 18) +#define L29(A,B,C,D,a,b,c,d,i) +#define L30(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##C) /* xor y0 */ +#define L31(A,B,C,D,a,b,c,d,i) +#else +#define L27(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##D, xmm##A) +#define L28(A,B,C,D,a,b,c,d,i) AS2( pslld xmm##A, 18) +#define L29(A,B,C,D,a,b,c,d,i) AS2( psrld xmm##D, 32-18) +#define L30(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##C) /* xor y0 */ +#define L31(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##D) /* z0 */ +#endif + +#define L32(A,B,C,D,a,b,c,d,i) AS2( movdqa [SSE2_WORKSPACE + a*16], xmm##A) + +#define SSE2_QUARTER_ROUND_X8(i, a, b, c, d, e, f, g, h) \ + L01(0,1,2,3, a,b,c,d, i) L01(4,5,6,7, e,f,g,h, i) \ + L02(0,1,2,3, a,b,c,d, i) L02(4,5,6,7, e,f,g,h, i) \ + L03(0,1,2,3, a,b,c,d, i) L03(4,5,6,7, e,f,g,h, i) \ + L04(0,1,2,3, a,b,c,d, i) L04(4,5,6,7, e,f,g,h, i) \ + L05(0,1,2,3, a,b,c,d, i) L05(4,5,6,7, e,f,g,h, i) \ + L06(0,1,2,3, a,b,c,d, i) L06(4,5,6,7, e,f,g,h, i) \ + L07(0,1,2,3, a,b,c,d, i) L07(4,5,6,7, e,f,g,h, i) \ + L08(0,1,2,3, a,b,c,d, i) L08(4,5,6,7, e,f,g,h, i) \ + L09(0,1,2,3, a,b,c,d, i) L09(4,5,6,7, e,f,g,h, i) \ + L10(0,1,2,3, a,b,c,d, i) L10(4,5,6,7, e,f,g,h, i) \ + L11(0,1,2,3, a,b,c,d, i) L11(4,5,6,7, e,f,g,h, i) \ + L12(0,1,2,3, a,b,c,d, i) L12(4,5,6,7, e,f,g,h, i) \ + L13(0,1,2,3, a,b,c,d, i) L13(4,5,6,7, e,f,g,h, i) \ + L14(0,1,2,3, a,b,c,d, i) L14(4,5,6,7, e,f,g,h, i) \ + L15(0,1,2,3, a,b,c,d, i) L15(4,5,6,7, e,f,g,h, i) \ + L16(0,1,2,3, a,b,c,d, i) L16(4,5,6,7, e,f,g,h, i) \ + L17(0,1,2,3, a,b,c,d, i) L17(4,5,6,7, e,f,g,h, i) \ + L18(0,1,2,3, a,b,c,d, i) L18(4,5,6,7, e,f,g,h, i) \ + L19(0,1,2,3, a,b,c,d, i) L19(4,5,6,7, e,f,g,h, i) \ + L20(0,1,2,3, a,b,c,d, i) L20(4,5,6,7, e,f,g,h, i) \ + L21(0,1,2,3, a,b,c,d, i) L21(4,5,6,7, e,f,g,h, i) \ + L22(0,1,2,3, a,b,c,d, i) L22(4,5,6,7, e,f,g,h, i) \ + L23(0,1,2,3, a,b,c,d, i) L23(4,5,6,7, e,f,g,h, i) \ + L24(0,1,2,3, a,b,c,d, i) L24(4,5,6,7, e,f,g,h, i) \ + L25(0,1,2,3, a,b,c,d, i) L25(4,5,6,7, e,f,g,h, i) \ + L26(0,1,2,3, a,b,c,d, i) L26(4,5,6,7, e,f,g,h, i) \ + L27(0,1,2,3, a,b,c,d, i) L27(4,5,6,7, e,f,g,h, i) \ + L28(0,1,2,3, a,b,c,d, i) L28(4,5,6,7, e,f,g,h, i) \ + L29(0,1,2,3, a,b,c,d, i) L29(4,5,6,7, e,f,g,h, i) \ + L30(0,1,2,3, a,b,c,d, i) L30(4,5,6,7, e,f,g,h, i) \ + L31(0,1,2,3, a,b,c,d, i) L31(4,5,6,7, e,f,g,h, i) \ + L32(0,1,2,3, a,b,c,d, i) L32(4,5,6,7, e,f,g,h, i) + +#define SSE2_QUARTER_ROUND_X16(i, a, b, c, d, e, f, g, h, A, B, C, D, E, F, G, H) \ + L01(0,1,2,3, a,b,c,d, i) L01(4,5,6,7, e,f,g,h, i) L01(8,9,10,11, A,B,C,D, i) L01(12,13,14,15, E,F,G,H, i) \ + L02(0,1,2,3, a,b,c,d, i) L02(4,5,6,7, e,f,g,h, i) L02(8,9,10,11, A,B,C,D, i) L02(12,13,14,15, E,F,G,H, i) \ + L03(0,1,2,3, a,b,c,d, i) L03(4,5,6,7, e,f,g,h, i) L03(8,9,10,11, A,B,C,D, i) L03(12,13,14,15, E,F,G,H, i) \ + L04(0,1,2,3, a,b,c,d, i) L04(4,5,6,7, e,f,g,h, i) L04(8,9,10,11, A,B,C,D, i) L04(12,13,14,15, E,F,G,H, i) \ + L05(0,1,2,3, a,b,c,d, i) L05(4,5,6,7, e,f,g,h, i) L05(8,9,10,11, A,B,C,D, i) L05(12,13,14,15, E,F,G,H, i) \ + L06(0,1,2,3, a,b,c,d, i) L06(4,5,6,7, e,f,g,h, i) L06(8,9,10,11, A,B,C,D, i) L06(12,13,14,15, E,F,G,H, i) \ + L07(0,1,2,3, a,b,c,d, i) L07(4,5,6,7, e,f,g,h, i) L07(8,9,10,11, A,B,C,D, i) L07(12,13,14,15, E,F,G,H, i) \ + L08(0,1,2,3, a,b,c,d, i) L08(4,5,6,7, e,f,g,h, i) L08(8,9,10,11, A,B,C,D, i) L08(12,13,14,15, E,F,G,H, i) \ + L09(0,1,2,3, a,b,c,d, i) L09(4,5,6,7, e,f,g,h, i) L09(8,9,10,11, A,B,C,D, i) L09(12,13,14,15, E,F,G,H, i) \ + L10(0,1,2,3, a,b,c,d, i) L10(4,5,6,7, e,f,g,h, i) L10(8,9,10,11, A,B,C,D, i) L10(12,13,14,15, E,F,G,H, i) \ + L11(0,1,2,3, a,b,c,d, i) L11(4,5,6,7, e,f,g,h, i) L11(8,9,10,11, A,B,C,D, i) L11(12,13,14,15, E,F,G,H, i) \ + L12(0,1,2,3, a,b,c,d, i) L12(4,5,6,7, e,f,g,h, i) L12(8,9,10,11, A,B,C,D, i) L12(12,13,14,15, E,F,G,H, i) \ + L13(0,1,2,3, a,b,c,d, i) L13(4,5,6,7, e,f,g,h, i) L13(8,9,10,11, A,B,C,D, i) L13(12,13,14,15, E,F,G,H, i) \ + L14(0,1,2,3, a,b,c,d, i) L14(4,5,6,7, e,f,g,h, i) L14(8,9,10,11, A,B,C,D, i) L14(12,13,14,15, E,F,G,H, i) \ + L15(0,1,2,3, a,b,c,d, i) L15(4,5,6,7, e,f,g,h, i) L15(8,9,10,11, A,B,C,D, i) L15(12,13,14,15, E,F,G,H, i) \ + L16(0,1,2,3, a,b,c,d, i) L16(4,5,6,7, e,f,g,h, i) L16(8,9,10,11, A,B,C,D, i) L16(12,13,14,15, E,F,G,H, i) \ + L17(0,1,2,3, a,b,c,d, i) L17(4,5,6,7, e,f,g,h, i) L17(8,9,10,11, A,B,C,D, i) L17(12,13,14,15, E,F,G,H, i) \ + L18(0,1,2,3, a,b,c,d, i) L18(4,5,6,7, e,f,g,h, i) L18(8,9,10,11, A,B,C,D, i) L18(12,13,14,15, E,F,G,H, i) \ + L19(0,1,2,3, a,b,c,d, i) L19(4,5,6,7, e,f,g,h, i) L19(8,9,10,11, A,B,C,D, i) L19(12,13,14,15, E,F,G,H, i) \ + L20(0,1,2,3, a,b,c,d, i) L20(4,5,6,7, e,f,g,h, i) L20(8,9,10,11, A,B,C,D, i) L20(12,13,14,15, E,F,G,H, i) \ + L21(0,1,2,3, a,b,c,d, i) L21(4,5,6,7, e,f,g,h, i) L21(8,9,10,11, A,B,C,D, i) L21(12,13,14,15, E,F,G,H, i) \ + L22(0,1,2,3, a,b,c,d, i) L22(4,5,6,7, e,f,g,h, i) L22(8,9,10,11, A,B,C,D, i) L22(12,13,14,15, E,F,G,H, i) \ + L23(0,1,2,3, a,b,c,d, i) L23(4,5,6,7, e,f,g,h, i) L23(8,9,10,11, A,B,C,D, i) L23(12,13,14,15, E,F,G,H, i) \ + L24(0,1,2,3, a,b,c,d, i) L24(4,5,6,7, e,f,g,h, i) L24(8,9,10,11, A,B,C,D, i) L24(12,13,14,15, E,F,G,H, i) \ + L25(0,1,2,3, a,b,c,d, i) L25(4,5,6,7, e,f,g,h, i) L25(8,9,10,11, A,B,C,D, i) L25(12,13,14,15, E,F,G,H, i) \ + L26(0,1,2,3, a,b,c,d, i) L26(4,5,6,7, e,f,g,h, i) L26(8,9,10,11, A,B,C,D, i) L26(12,13,14,15, E,F,G,H, i) \ + L27(0,1,2,3, a,b,c,d, i) L27(4,5,6,7, e,f,g,h, i) L27(8,9,10,11, A,B,C,D, i) L27(12,13,14,15, E,F,G,H, i) \ + L28(0,1,2,3, a,b,c,d, i) L28(4,5,6,7, e,f,g,h, i) L28(8,9,10,11, A,B,C,D, i) L28(12,13,14,15, E,F,G,H, i) \ + L29(0,1,2,3, a,b,c,d, i) L29(4,5,6,7, e,f,g,h, i) L29(8,9,10,11, A,B,C,D, i) L29(12,13,14,15, E,F,G,H, i) \ + L30(0,1,2,3, a,b,c,d, i) L30(4,5,6,7, e,f,g,h, i) L30(8,9,10,11, A,B,C,D, i) L30(12,13,14,15, E,F,G,H, i) \ + L31(0,1,2,3, a,b,c,d, i) L31(4,5,6,7, e,f,g,h, i) L31(8,9,10,11, A,B,C,D, i) L31(12,13,14,15, E,F,G,H, i) \ + L32(0,1,2,3, a,b,c,d, i) L32(4,5,6,7, e,f,g,h, i) L32(8,9,10,11, A,B,C,D, i) L32(12,13,14,15, E,F,G,H, i) + +#if CRYPTOPP_BOOL_X64 + SSE2_QUARTER_ROUND_X16(1, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15) +#else + SSE2_QUARTER_ROUND_X8(1, 2, 6, 10, 14, 3, 7, 11, 15) + SSE2_QUARTER_ROUND_X8(1, 0, 4, 8, 12, 1, 5, 9, 13) +#endif + AS2( mov REG_roundsLeft, REG_rounds) + ASJ( jmp, 2, f) + + ASL(SSE2_Salsa_Output) + AS2( movdqa xmm0, xmm4) + AS2( punpckldq xmm4, xmm5) + AS2( movdqa xmm1, xmm6) + AS2( punpckldq xmm6, xmm7) + AS2( movdqa xmm2, xmm4) + AS2( punpcklqdq xmm4, xmm6) // e + AS2( punpckhqdq xmm2, xmm6) // f + AS2( punpckhdq xmm0, xmm5) + AS2( punpckhdq xmm1, xmm7) + AS2( movdqa xmm6, xmm0) + AS2( punpcklqdq xmm0, xmm1) // g + AS2( punpckhqdq xmm6, xmm1) // h + AS_XMM_OUTPUT4(SSE2_Salsa_Output_A, REG_input, REG_output, 4, 2, 0, 6, 1, 0, 4, 8, 12, 1) + AS1( ret) + + ASL(6) +#if CRYPTOPP_BOOL_X64 + SSE2_QUARTER_ROUND_X16(0, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15) + ASL(2) + SSE2_QUARTER_ROUND_X16(0, 0, 13, 10, 7, 1, 14, 11, 4, 2, 15, 8, 5, 3, 12, 9, 6) +#else + SSE2_QUARTER_ROUND_X8(0, 2, 6, 10, 14, 3, 7, 11, 15) + SSE2_QUARTER_ROUND_X8(0, 0, 4, 8, 12, 1, 5, 9, 13) + ASL(2) + SSE2_QUARTER_ROUND_X8(0, 2, 15, 8, 5, 3, 12, 9, 6) + SSE2_QUARTER_ROUND_X8(0, 0, 13, 10, 7, 1, 14, 11, 4) +#endif + AS2( sub REG_roundsLeft, 2) + ASJ( jnz, 6, b) + +#define SSE2_OUTPUT_4(a, b, c, d) \ + AS2( movdqa xmm4, [SSE2_WORKSPACE + a*16 + 256])\ + AS2( paddd xmm4, [SSE2_WORKSPACE + a*16])\ + AS2( movdqa xmm5, [SSE2_WORKSPACE + b*16 + 256])\ + AS2( paddd xmm5, [SSE2_WORKSPACE + b*16])\ + AS2( movdqa xmm6, [SSE2_WORKSPACE + c*16 + 256])\ + AS2( paddd xmm6, [SSE2_WORKSPACE + c*16])\ + AS2( movdqa xmm7, [SSE2_WORKSPACE + d*16 + 256])\ + AS2( paddd xmm7, [SSE2_WORKSPACE + d*16])\ + ASC( call, SSE2_Salsa_Output) + + SSE2_OUTPUT_4(0, 13, 10, 7) + SSE2_OUTPUT_4(4, 1, 14, 11) + SSE2_OUTPUT_4(8, 5, 2, 15) + SSE2_OUTPUT_4(12, 9, 6, 3) + AS2( test REG_input, REG_input) + ASJ( jz, 9, f) + AS2( add REG_input, 12*16) + ASL(9) + AS2( add REG_output, 12*16) + AS2( sub REG_iterationCount, 4) + AS2( cmp REG_iterationCount, 4) + ASJ( jge, 1, b) + AS_POP_IF86( sp) + + ASL(5) + AS2( sub REG_iterationCount, 1) + ASJ( jl, 4, f) + AS2( movdqa xmm0, [REG_state + 0*16]) + AS2( movdqa xmm1, [REG_state + 1*16]) + AS2( movdqa xmm2, [REG_state + 2*16]) + AS2( movdqa xmm3, [REG_state + 3*16]) + AS2( mov REG_roundsLeft, REG_rounds) + + ASL(0) + SSE2_QUARTER_ROUND(0, 1, 3, 7) + SSE2_QUARTER_ROUND(1, 2, 0, 9) + SSE2_QUARTER_ROUND(2, 3, 1, 13) + SSE2_QUARTER_ROUND(3, 0, 2, 18) + ASS( pshufd xmm1, xmm1, 2, 1, 0, 3) + ASS( pshufd xmm2, xmm2, 1, 0, 3, 2) + ASS( pshufd xmm3, xmm3, 0, 3, 2, 1) + SSE2_QUARTER_ROUND(0, 3, 1, 7) + SSE2_QUARTER_ROUND(3, 2, 0, 9) + SSE2_QUARTER_ROUND(2, 1, 3, 13) + SSE2_QUARTER_ROUND(1, 0, 2, 18) + ASS( pshufd xmm1, xmm1, 0, 3, 2, 1) + ASS( pshufd xmm2, xmm2, 1, 0, 3, 2) + ASS( pshufd xmm3, xmm3, 2, 1, 0, 3) + AS2( sub REG_roundsLeft, 2) + ASJ( jnz, 0, b) + + AS2( paddd xmm0, [REG_state + 0*16]) + AS2( paddd xmm1, [REG_state + 1*16]) + AS2( paddd xmm2, [REG_state + 2*16]) + AS2( paddd xmm3, [REG_state + 3*16]) + + AS2( add dword ptr [REG_state + 8*4], 1) + AS2( adc dword ptr [REG_state + 5*4], 0) + + AS2( pcmpeqb xmm6, xmm6) // all ones + AS2( psrlq xmm6, 32) // lo32 mask + ASS( pshufd xmm7, xmm6, 0, 1, 2, 3) // hi32 mask + AS2( movdqa xmm4, xmm0) + AS2( movdqa xmm5, xmm3) + AS2( pand xmm0, xmm7) + AS2( pand xmm4, xmm6) + AS2( pand xmm3, xmm6) + AS2( pand xmm5, xmm7) + AS2( por xmm4, xmm5) // 0,13,2,15 + AS2( movdqa xmm5, xmm1) + AS2( pand xmm1, xmm7) + AS2( pand xmm5, xmm6) + AS2( por xmm0, xmm5) // 4,1,6,3 + AS2( pand xmm6, xmm2) + AS2( pand xmm2, xmm7) + AS2( por xmm1, xmm6) // 8,5,10,7 + AS2( por xmm2, xmm3) // 12,9,14,11 + + AS2( movdqa xmm5, xmm4) + AS2( movdqa xmm6, xmm0) + AS3( shufpd xmm4, xmm1, 2) // 0,13,10,7 + AS3( shufpd xmm0, xmm2, 2) // 4,1,14,11 + AS3( shufpd xmm1, xmm5, 2) // 8,5,2,15 + AS3( shufpd xmm2, xmm6, 2) // 12,9,6,3 + + // output keystream + AS_XMM_OUTPUT4(SSE2_Salsa_Output_B, REG_input, REG_output, 4, 0, 1, 2, 3, 0, 1, 2, 3, 4) + ASJ( jmp, 5, b) + ASL(4) + + AS_POP_IF86( bp) +#ifdef __GNUC__ + AS_POP_IF86( bx) + ATT_PREFIX + #if CRYPTOPP_BOOL_X64 + : "+r" (input), "+r" (output), "+r" (iterationCount) + : "r" (m_rounds), "r" (m_state.begin()), "r" (workspace) + : "%eax", "%rdx", "memory", "cc", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + #else + : "+a" (input), "+D" (output), "+c" (iterationCount) + : "d" (m_rounds), "S" (m_state.begin()) + : "memory", "cc" + #endif + ); +#endif +#ifdef CRYPTOPP_GENERATE_X64_MASM + movdqa xmm6, [rsp + 0200h] + movdqa xmm7, [rsp + 0210h] + movdqa xmm8, [rsp + 0220h] + movdqa xmm9, [rsp + 0230h] + movdqa xmm10, [rsp + 0240h] + movdqa xmm11, [rsp + 0250h] + movdqa xmm12, [rsp + 0260h] + movdqa xmm13, [rsp + 0270h] + movdqa xmm14, [rsp + 0280h] + movdqa xmm15, [rsp + 0290h] + add rsp, 10*16 + 32*16 + 8 + ret +Salsa20_OperateKeystream ENDP +#else + } + else +#endif +#endif +#ifndef CRYPTOPP_GENERATE_X64_MASM + { + word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + + while (iterationCount--) + { + x0 = m_state[0]; x1 = m_state[1]; x2 = m_state[2]; x3 = m_state[3]; + x4 = m_state[4]; x5 = m_state[5]; x6 = m_state[6]; x7 = m_state[7]; + x8 = m_state[8]; x9 = m_state[9]; x10 = m_state[10]; x11 = m_state[11]; + x12 = m_state[12]; x13 = m_state[13]; x14 = m_state[14]; x15 = m_state[15]; + + for (int i=m_rounds; i>0; i-=2) + { + #define QUARTER_ROUND(a, b, c, d) \ + b = b ^ rotlConstant<7>(a + d); \ + c = c ^ rotlConstant<9>(b + a); \ + d = d ^ rotlConstant<13>(c + b); \ + a = a ^ rotlConstant<18>(d + c); + + QUARTER_ROUND(x0, x4, x8, x12) + QUARTER_ROUND(x1, x5, x9, x13) + QUARTER_ROUND(x2, x6, x10, x14) + QUARTER_ROUND(x3, x7, x11, x15) + + QUARTER_ROUND(x0, x13, x10, x7) + QUARTER_ROUND(x1, x14, x11, x4) + QUARTER_ROUND(x2, x15, x8, x5) + QUARTER_ROUND(x3, x12, x9, x6) + } + +#ifndef CRYPTOPP_DOXYGEN_PROCESSING + #define SALSA_OUTPUT(x) {\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, x0 + m_state[0]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x13 + m_state[13]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x10 + m_state[10]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x7 + m_state[7]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + m_state[4]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x1 + m_state[1]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x14 + m_state[14]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x11 + m_state[11]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + m_state[8]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x5 + m_state[5]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x2 + m_state[2]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x15 + m_state[15]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + m_state[12]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x9 + m_state[9]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x6 + m_state[6]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x3 + m_state[3]);} + + CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(SALSA_OUTPUT, BYTES_PER_ITERATION); + #undef SALSA_OUTPUT +#endif + + if (++m_state[8] == 0) + ++m_state[5]; + } + } +} // see comment above if an internal compiler error occurs here + +void XSalsa20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + m_rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds); + if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20)) + throw InvalidRounds(XSalsa20::StaticAlgorithmName(), m_rounds); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_key.begin(), m_key.size(), key, length); + if (length == 16) + memcpy(m_key.begin()+4, m_key.begin(), 16); + + // "expand 32-byte k" + m_state[0] = 0x61707865; + m_state[1] = 0x3320646e; + m_state[2] = 0x79622d32; + m_state[3] = 0x6b206574; +} + +void XSalsa20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length==24); + + word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + + GetBlock get(IV); + get(x14)(x11)(x8)(x5)(m_state[14])(m_state[11]); + + x13 = m_key[0]; x10 = m_key[1]; x7 = m_key[2]; x4 = m_key[3]; + x15 = m_key[4]; x12 = m_key[5]; x9 = m_key[6]; x6 = m_key[7]; + x0 = m_state[0]; x1 = m_state[1]; x2 = m_state[2]; x3 = m_state[3]; + + for (int i=m_rounds; i>0; i-=2) + { + QUARTER_ROUND(x0, x4, x8, x12) + QUARTER_ROUND(x1, x5, x9, x13) + QUARTER_ROUND(x2, x6, x10, x14) + QUARTER_ROUND(x3, x7, x11, x15) + + QUARTER_ROUND(x0, x13, x10, x7) + QUARTER_ROUND(x1, x14, x11, x4) + QUARTER_ROUND(x2, x15, x8, x5) + QUARTER_ROUND(x3, x12, x9, x6) + } + + m_state[13] = x0; m_state[10] = x1; m_state[7] = x2; m_state[4] = x3; + m_state[15] = x14; m_state[12] = x11; m_state[9] = x8; m_state[6] = x5; + m_state[8] = m_state[5] = 0; +} + +NAMESPACE_END + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM diff --git a/external/ours/library/crypto/src/shared/original/salsa.h b/external/ours/library/crypto/src/shared/original/salsa.h new file mode 100755 index 000000000..1468d8c1c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/scrypt.cpp b/external/ours/library/crypto/src/shared/original/scrypt.cpp new file mode 100755 index 000000000..3b995813f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/scrypt.cpp @@ -0,0 +1,329 @@ +// scrypt.cpp - written and placed in public domain by Jeffrey Walton. +// Based on reference source code by Colin Percival for +// Scrypt and Daniel Bernstein for Salsa20 core. + +#include "pch.h" + +#include "scrypt.h" +#include "algparam.h" +#include "argnames.h" +#include "pwdbased.h" +#include "stdcpp.h" +#include "salsa.h" +#include "misc.h" +#include "sha.h" + +#include +#include + +#ifdef _OPENMP +# include +#endif + +// https://github.com/weidai11/cryptopp/issues/777 +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# if defined(__clang__) +# pragma GCC diagnostic ignored "-Wtautological-compare" +# elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wtype-limits" +# endif +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::GetWord; +using CryptoPP::PutWord; +using CryptoPP::Salsa20_Core; +using CryptoPP::rotlConstant; +using CryptoPP::LITTLE_ENDIAN_ORDER; +using CryptoPP::AlignedSecByteBlock; + +inline void LE32ENC(byte* out, word32 in) +{ + PutWord(false, LITTLE_ENDIAN_ORDER, out, in); +} + +inline word32 LE32DEC(const byte* in) +{ + return GetWord(false, LITTLE_ENDIAN_ORDER, in); +} + +inline word64 LE64DEC(const byte* in) +{ + return GetWord(false, LITTLE_ENDIAN_ORDER, in); +} + +inline void BlockCopy(byte* dest, byte* src, size_t len) +{ +// OpenMP 4.0 released July 2013. +#if _OPENMP >= 201307 + #pragma omp simd + for (size_t i = 0; i < len; ++i) + dest[i] = src[i]; +#else + for (size_t i = 0; i < len; ++i) + dest[i] = src[i]; +#endif +} + +inline void BlockXOR(byte* dest, byte* src, size_t len) +{ +// OpenMP 4.0 released July 2013. +#if _OPENMP >= 201307 + #pragma omp simd + for (size_t i = 0; i < len; ++i) + dest[i] ^= src[i]; +#else + for (size_t i = 0; i < len; ++i) + dest[i] ^= src[i]; +#endif +} + +inline void PBKDF2_SHA256(byte* buf, size_t dkLen, + const byte* passwd, size_t passwdlen, + const byte* salt, size_t saltlen, byte count) +{ + using CryptoPP::SHA256; + using CryptoPP::PKCS5_PBKDF2_HMAC; + + PKCS5_PBKDF2_HMAC pbkdf; + pbkdf.DeriveKey(buf, dkLen, 0, passwd, passwdlen, salt, saltlen, count, 0.0f); +} + +inline void Salsa20_8(byte B[64]) +{ + word32 B32[16]; + + for (size_t i = 0; i < 16; ++i) + B32[i] = LE32DEC(&B[i * 4]); + + Salsa20_Core(B32, 8); + + for (size_t i = 0; i < 16; ++i) + LE32ENC(&B[4 * i], B32[i]); +} + +inline void BlockMix(byte* B, byte* Y, size_t r) +{ + byte X[64]; + + // 1: X <-- B_{2r - 1} + BlockCopy(X, &B[(2 * r - 1) * 64], 64); + + // 2: for i = 0 to 2r - 1 do + for (size_t i = 0; i < 2 * r; ++i) + { + // 3: X <-- H(X \xor B_i) + BlockXOR(X, &B[i * 64], 64); + Salsa20_8(X); + + // 4: Y_i <-- X + BlockCopy(&Y[i * 64], X, 64); + } + + // 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) + for (size_t i = 0; i < r; ++i) + BlockCopy(&B[i * 64], &Y[(i * 2) * 64], 64); + + for (size_t i = 0; i < r; ++i) + BlockCopy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64); +} + +inline word64 Integerify(byte* B, size_t r) +{ + byte* X = &B[(2 * r - 1) * 64]; + return LE64DEC(X); +} + +inline void Smix(byte* B, size_t r, word64 N, byte* V, byte* XY) +{ + byte* X = XY; + byte* Y = XY+128*r; + + // 1: X <-- B + BlockCopy(X, B, 128 * r); + + // 2: for i = 0 to N - 1 do + for (word64 i = 0; i < N; ++i) + { + // 3: V_i <-- X + BlockCopy(&V[i * (128 * r)], X, 128 * r); + + // 4: X <-- H(X) + BlockMix(X, Y, r); + } + + // 6: for i = 0 to N - 1 do + for (word64 i = 0; i < N; ++i) + { + // 7: j <-- Integerify(X) mod N + word64 j = Integerify(X, r) & (N - 1); + + // 8: X <-- H(X \xor V_j) + BlockXOR(X, &V[j * (128 * r)], 128 * r); + BlockMix(X, Y, r); + } + + // 10: B' <-- X + BlockCopy(B, X, 128 * r); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +size_t Scrypt::GetValidDerivedLength(size_t keylength) const +{ + if (keylength > MaxDerivedKeyLength()) + return MaxDerivedKeyLength(); + return keylength; +} + +void Scrypt::ValidateParameters(size_t derivedLen, word64 cost, word64 blockSize, word64 parallelization) const +{ + // https://github.com/weidai11/cryptopp/issues/842 + CRYPTOPP_ASSERT(derivedLen != 0); + CRYPTOPP_ASSERT(cost != 0); + CRYPTOPP_ASSERT(blockSize != 0); + CRYPTOPP_ASSERT(parallelization != 0); + + if (cost == 0) + throw InvalidArgument("Scrypt: cost cannot be 0"); + + if (blockSize == 0) + throw InvalidArgument("Scrypt: block size cannot be 0"); + + if (parallelization == 0) + throw InvalidArgument("Scrypt: parallelization cannot be 0"); + + // Optimizer should remove this on 32-bit platforms + if (std::numeric_limits::max() > std::numeric_limits::max()) + { + const word64 maxLen = ((static_cast(1) << 32) - 1) * 32; + if (derivedLen > maxLen) { + std::ostringstream oss; + oss << "derivedLen " << derivedLen << " is larger than " << maxLen; + throw InvalidArgument("Scrypt: " + oss.str()); + } + } + + // https://github.com/weidai11/cryptopp/issues/787 + CRYPTOPP_ASSERT(parallelization <= static_cast(std::numeric_limits::max())); + if (parallelization > static_cast(std::numeric_limits::max())) + { + std::ostringstream oss; + oss << " parallelization " << parallelization << " is larger than "; + oss << std::numeric_limits::max(); + throw InvalidArgument("Scrypt: " + oss.str()); + } + + CRYPTOPP_ASSERT(IsPowerOf2(cost)); + if (IsPowerOf2(cost) == false) + throw InvalidArgument("Scrypt: cost must be a power of 2"); + + const word64 prod = static_cast(blockSize) * parallelization; + CRYPTOPP_ASSERT(prod < (1U << 30)); + + if (prod >= (1U << 30)) { + std::ostringstream oss; + oss << "r*p " << prod << " is larger than " << (1U << 30); + throw InvalidArgument("Scrypt: " + oss.str()); + } + + // Scrypt has several tests that effectively verify allocations like + // '128 * r * N' and '128 * r * p' do not overflow. They are the tests + // that set errno to ENOMEM. We can make the logic a little more clear + // using word128. At first blush the word128 may seem like overkill. + // However, this alogirthm is dominated by slow moving parts, so a + // one-time check is insignificant in the bigger picture. +#if defined(CRYPTOPP_WORD128_AVAILABLE) + const word128 maxElems = static_cast(SIZE_MAX); + bool bLimit = (maxElems >= static_cast(cost) * blockSize * 128U); + bool xyLimit = (maxElems >= static_cast(parallelization) * blockSize * 128U); + bool vLimit = (maxElems >= static_cast(blockSize) * 256U + 64U); +#else + const word64 maxElems = static_cast(SIZE_MAX); + bool bLimit = (blockSize < maxElems / 128U / cost); + bool xyLimit = (blockSize < maxElems / 128U / parallelization); + bool vLimit = (blockSize < (maxElems - 64U) / 256U); +#endif + + CRYPTOPP_ASSERT(bLimit); CRYPTOPP_ASSERT(xyLimit); CRYPTOPP_ASSERT(vLimit); + if (!bLimit || !xyLimit || !vLimit) + throw std::bad_alloc(); +} + +size_t Scrypt::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()); + + word64 cost=0, blockSize=0, parallelization=0; + if(params.GetValue("Cost", cost) == false) + cost = defaultCost; + + if(params.GetValue("BlockSize", blockSize) == false) + blockSize = defaultBlockSize; + + if(params.GetValue("Parallelization", parallelization) == false) + parallelization = defaultParallelization; + + ConstByteArrayParameter salt; + (void)params.GetValue("Salt", salt); + + return DeriveKey(derived, derivedLen, secret, secretLen, salt.begin(), salt.size(), cost, blockSize, parallelization); +} + +size_t Scrypt::DeriveKey(byte*derived, size_t derivedLen, const byte*secret, size_t secretLen, + const byte*salt, size_t saltLen, word64 cost, word64 blockSize, word64 parallel) const +{ + CRYPTOPP_ASSERT(secret /*&& secretLen*/); + CRYPTOPP_ASSERT(derived && derivedLen); + CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength()); + + ThrowIfInvalidDerivedKeyLength(derivedLen); + ValidateParameters(derivedLen, cost, blockSize, parallel); + + AlignedSecByteBlock B(static_cast(blockSize * parallel * 128U)); + + // 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) + PBKDF2_SHA256(B, B.size(), secret, secretLen, salt, saltLen, 1); + + // Visual Studio and OpenMP 2.0 fixup. We must use int, not size_t. + int maxParallel=0; + if (!SafeConvert(parallel, maxParallel)) + maxParallel = std::numeric_limits::max(); + + #ifdef _OPENMP + int threads = STDMIN(omp_get_max_threads(), maxParallel); + #endif + + // http://stackoverflow.com/q/49604260/608639 + #pragma omp parallel num_threads(threads) + { + // Each thread gets its own copy + AlignedSecByteBlock XY(static_cast(blockSize * 256U)); + AlignedSecByteBlock V(static_cast(blockSize * cost * 128U)); + + // 2: for i = 0 to p - 1 do + #pragma omp for + for (int i = 0; i < maxParallel; ++i) + { + // 3: B_i <-- MF(B_i, N) + const ptrdiff_t offset = static_cast(blockSize*i*128); + Smix(B+offset, static_cast(blockSize), cost, V, XY); + } + } + + // 5: DK <-- PBKDF2(P, B, 1, dkLen) + PBKDF2_SHA256(derived, derivedLen, secret, secretLen, B, B.size(), 1); + + return 1; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/scrypt.h b/external/ours/library/crypto/src/shared/original/scrypt.h new file mode 100755 index 000000000..924c1f187 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/seal.cpp b/external/ours/library/crypto/src/shared/original/seal.cpp new file mode 100755 index 000000000..fea047e7d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/seal.cpp @@ -0,0 +1,222 @@ +// seal.cpp - originally written and placed in the public domain by Wei Dai +// updated to SEAL 3.0 by Leonard Janke + +#include "pch.h" + +#include "seal.h" +#include "cpu.h" +#include "sha.h" +#include "misc.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void SEAL_TestInstantiations() +{ + SEAL<>::Encryption x; +} +#endif + +struct SEAL_Gamma +{ + SEAL_Gamma(const byte *key) + : H(5), Z(5), D(16), lastIndex(0xffffffff) + { + GetUserKey(BIG_ENDIAN_ORDER, H.begin(), 5, key, 20); + memset(D, 0, 64); + } + + word32 Apply(word32 i); + + SecBlock H, Z, D; + word32 lastIndex; +}; + +word32 SEAL_Gamma::Apply(word32 i) +{ + word32 shaIndex = i/5; + if (shaIndex != lastIndex) + { + memcpy(Z, H, 20); + D[0] = shaIndex; + SHA1::Transform(Z, D); + lastIndex = shaIndex; + } + + return Z[i%5]; +} + +template +void SEAL_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + CRYPTOPP_UNUSED(length); + m_insideCounter = m_outsideCounter = m_startCount = 0; + + unsigned int L = params.GetIntValueWithDefault("NumberOfOutputBitsPerPositionIndex", 32*1024); + m_iterationsPerCount = L / 8192; + + SEAL_Gamma gamma(key); + unsigned int i; + + for (i=0; i<512; i++) + m_T[i] = gamma.Apply(i); + + for (i=0; i<256; i++) + m_S[i] = gamma.Apply(0x1000+i); + + m_R.New(4*(L/8192)); + + for (i=0; i +void SEAL_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(IV), CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length==4); + + m_outsideCounter = IV ? GetWord(false, BIG_ENDIAN_ORDER, IV) : 0; + m_startCount = m_outsideCounter; + m_insideCounter = 0; +} + +template +void SEAL_Policy::SeekToIteration(lword iterationCount) +{ + m_outsideCounter = m_startCount + (unsigned int)(iterationCount / m_iterationsPerCount); + m_insideCounter = (unsigned int)(iterationCount % m_iterationsPerCount); +} + +template +void SEAL_Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ + word32 a, b, c, d, n1, n2, n3, n4; + unsigned int p, q; + + CRYPTOPP_ASSERT(IsAlignedOn(m_T.begin(),GetAlignmentOf())); + for (size_t iteration = 0; iteration < iterationCount; ++iteration) + { + #define Ttab(x) *(word32 *)(void*)((byte *)m_T.begin()+x) + + a = m_outsideCounter ^ m_R[4*m_insideCounter]; + b = rotrConstant<8>(m_outsideCounter) ^ m_R[4*m_insideCounter+1]; + c = rotrConstant<16>(m_outsideCounter) ^ m_R[4 * m_insideCounter + 2]; + d = rotrConstant<24>(m_outsideCounter) ^ m_R[4 * m_insideCounter + 3]; + + for (unsigned int j=0; j<2; j++) + { + p = a & 0x7fc; + b += Ttab(p); + a = rotrConstant<9>(a); + + p = b & 0x7fc; + c += Ttab(p); + b = rotrConstant<9>(b); + + p = c & 0x7fc; + d += Ttab(p); + c = rotrConstant<9>(c); + + p = d & 0x7fc; + a += Ttab(p); + d = rotrConstant<9>(d); + } + + n1 = d, n2 = b, n3 = a, n4 = c; + + p = a & 0x7fc; + b += Ttab(p); + a = rotrConstant<9>(a); + + p = b & 0x7fc; + c += Ttab(p); + b = rotrConstant<9>(b); + + p = c & 0x7fc; + d += Ttab(p); + c = rotrConstant<9>(c); + + p = d & 0x7fc; + a += Ttab(p); + d = rotrConstant<9>(d); + + // generate 8192 bits + for (unsigned int i=0; i<64; i++) + { + p = a & 0x7fc; + a = rotrConstant<9>(a); + b += Ttab(p); + b ^= a; + + q = b & 0x7fc; + b = rotrConstant<9>(b); + c ^= Ttab(q); + c += b; + + p = (p+c) & 0x7fc; + c = rotrConstant<9>(c); + d += Ttab(p); + d ^= c; + + q = (q+d) & 0x7fc; + d = rotrConstant<9>(d); + a ^= Ttab(q); + a += d; + + p = (p+a) & 0x7fc; + b ^= Ttab(p); + a = rotrConstant<9>(a); + + q = (q+b) & 0x7fc; + c += Ttab(q); + b = rotrConstant<9>(b); + + p = (p+c) & 0x7fc; + d ^= Ttab(p); + c = rotrConstant<9>(c); + + q = (q+d) & 0x7fc; + d = rotrConstant<9>(d); + a += Ttab(q); + +#define SEAL_OUTPUT(x) \ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 0, b + m_S[4*i+0]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 1, c ^ m_S[4*i+1]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 2, d + m_S[4*i+2]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 3, a ^ m_S[4*i+3]); + + CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(SEAL_OUTPUT, 4*4); + + if (i & 1) + { + a += n3; + b += n4; + c ^= n3; + d ^= n4; + } + else + { + a += n1; + b += n2; + c ^= n1; + d ^= n2; + } + } + + if (++m_insideCounter == m_iterationsPerCount) + { + ++m_outsideCounter; + m_insideCounter = 0; + } + } + + a = b = c = d = n1 = n2 = n3 = n4 = 0; + p = q = 0; +} + +template class SEAL_Policy; +template class SEAL_Policy; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/seal.h b/external/ours/library/crypto/src/shared/original/seal.h new file mode 100755 index 000000000..d8826aecf --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/secblock.h b/external/ours/library/crypto/src/shared/original/secblock.h new file mode 100755 index 000000000..56b5be6d0 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 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(_MSC_VER) && (_MSC_VER <= 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 _MSC_VER >= 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(_MSC_VER) && (_MSC_VER <= 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) + 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 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 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 CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/external/ours/library/crypto/src/shared/original/secblockfwd.h b/external/ours/library/crypto/src/shared/original/secblockfwd.h new file mode 100755 index 000000000..d17068ee7 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/seckey.h b/external/ours/library/crypto/src/shared/original/seckey.h new file mode 100755 index 000000000..2b0b2b89a --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/seed.cpp b/external/ours/library/crypto/src/shared/original/seed.cpp new file mode 100755 index 000000000..4e99d759d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/seed.cpp @@ -0,0 +1,113 @@ +// seed.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "seed.h" +#include "misc.h" +#include "stdcpp.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; + +const word32 s_kc[16] = { + 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf, + 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b}; + +const byte s_s0[256] = { + 0xA9, 0x85, 0xD6, 0xD3, 0x54, 0x1D, 0xAC, 0x25, 0x5D, 0x43, 0x18, 0x1E, 0x51, 0xFC, 0xCA, 0x63, 0x28, + 0x44, 0x20, 0x9D, 0xE0, 0xE2, 0xC8, 0x17, 0xA5, 0x8F, 0x03, 0x7B, 0xBB, 0x13, 0xD2, 0xEE, 0x70, 0x8C, + 0x3F, 0xA8, 0x32, 0xDD, 0xF6, 0x74, 0xEC, 0x95, 0x0B, 0x57, 0x5C, 0x5B, 0xBD, 0x01, 0x24, 0x1C, 0x73, + 0x98, 0x10, 0xCC, 0xF2, 0xD9, 0x2C, 0xE7, 0x72, 0x83, 0x9B, 0xD1, 0x86, 0xC9, 0x60, 0x50, 0xA3, 0xEB, + 0x0D, 0xB6, 0x9E, 0x4F, 0xB7, 0x5A, 0xC6, 0x78, 0xA6, 0x12, 0xAF, 0xD5, 0x61, 0xC3, 0xB4, 0x41, 0x52, + 0x7D, 0x8D, 0x08, 0x1F, 0x99, 0x00, 0x19, 0x04, 0x53, 0xF7, 0xE1, 0xFD, 0x76, 0x2F, 0x27, 0xB0, 0x8B, + 0x0E, 0xAB, 0xA2, 0x6E, 0x93, 0x4D, 0x69, 0x7C, 0x09, 0x0A, 0xBF, 0xEF, 0xF3, 0xC5, 0x87, 0x14, 0xFE, + 0x64, 0xDE, 0x2E, 0x4B, 0x1A, 0x06, 0x21, 0x6B, 0x66, 0x02, 0xF5, 0x92, 0x8A, 0x0C, 0xB3, 0x7E, 0xD0, + 0x7A, 0x47, 0x96, 0xE5, 0x26, 0x80, 0xAD, 0xDF, 0xA1, 0x30, 0x37, 0xAE, 0x36, 0x15, 0x22, 0x38, 0xF4, + 0xA7, 0x45, 0x4C, 0x81, 0xE9, 0x84, 0x97, 0x35, 0xCB, 0xCE, 0x3C, 0x71, 0x11, 0xC7, 0x89, 0x75, 0xFB, + 0xDA, 0xF8, 0x94, 0x59, 0x82, 0xC4, 0xFF, 0x49, 0x39, 0x67, 0xC0, 0xCF, 0xD7, 0xB8, 0x0F, 0x8E, 0x42, + 0x23, 0x91, 0x6C, 0xDB, 0xA4, 0x34, 0xF1, 0x48, 0xC2, 0x6F, 0x3D, 0x2D, 0x40, 0xBE, 0x3E, 0xBC, 0xC1, + 0xAA, 0xBA, 0x4E, 0x55, 0x3B, 0xDC, 0x68, 0x7F, 0x9C, 0xD8, 0x4A, 0x56, 0x77, 0xA0, 0xED, 0x46, 0xB5, + 0x2B, 0x65, 0xFA, 0xE3, 0xB9, 0xB1, 0x9F, 0x5E, 0xF9, 0xE6, 0xB2, 0x31, 0xEA, 0x6D, 0x5F, 0xE4, 0xF0, + 0xCD, 0x88, 0x16, 0x3A, 0x58, 0xD4, 0x62, 0x29, 0x07, 0x33, 0xE8, 0x1B, 0x05, 0x79, 0x90, 0x6A, 0x2A, + 0x9A}; + +static const byte s_s1[256] = { + 0x38, 0xE8, 0x2D, 0xA6, 0xCF, 0xDE, 0xB3, 0xB8, 0xAF, 0x60, 0x55, 0xC7, 0x44, 0x6F, 0x6B, 0x5B, 0xC3, + 0x62, 0x33, 0xB5, 0x29, 0xA0, 0xE2, 0xA7, 0xD3, 0x91, 0x11, 0x06, 0x1C, 0xBC, 0x36, 0x4B, 0xEF, 0x88, + 0x6C, 0xA8, 0x17, 0xC4, 0x16, 0xF4, 0xC2, 0x45, 0xE1, 0xD6, 0x3F, 0x3D, 0x8E, 0x98, 0x28, 0x4E, 0xF6, + 0x3E, 0xA5, 0xF9, 0x0D, 0xDF, 0xD8, 0x2B, 0x66, 0x7A, 0x27, 0x2F, 0xF1, 0x72, 0x42, 0xD4, 0x41, 0xC0, + 0x73, 0x67, 0xAC, 0x8B, 0xF7, 0xAD, 0x80, 0x1F, 0xCA, 0x2C, 0xAA, 0x34, 0xD2, 0x0B, 0xEE, 0xE9, 0x5D, + 0x94, 0x18, 0xF8, 0x57, 0xAE, 0x08, 0xC5, 0x13, 0xCD, 0x86, 0xB9, 0xFF, 0x7D, 0xC1, 0x31, 0xF5, 0x8A, + 0x6A, 0xB1, 0xD1, 0x20, 0xD7, 0x02, 0x22, 0x04, 0x68, 0x71, 0x07, 0xDB, 0x9D, 0x99, 0x61, 0xBE, 0xE6, + 0x59, 0xDD, 0x51, 0x90, 0xDC, 0x9A, 0xA3, 0xAB, 0xD0, 0x81, 0x0F, 0x47, 0x1A, 0xE3, 0xEC, 0x8D, 0xBF, + 0x96, 0x7B, 0x5C, 0xA2, 0xA1, 0x63, 0x23, 0x4D, 0xC8, 0x9E, 0x9C, 0x3A, 0x0C, 0x2E, 0xBA, 0x6E, 0x9F, + 0x5A, 0xF2, 0x92, 0xF3, 0x49, 0x78, 0xCC, 0x15, 0xFB, 0x70, 0x75, 0x7F, 0x35, 0x10, 0x03, 0x64, 0x6D, + 0xC6, 0x74, 0xD5, 0xB4, 0xEA, 0x09, 0x76, 0x19, 0xFE, 0x40, 0x12, 0xE0, 0xBD, 0x05, 0xFA, 0x01, 0xF0, + 0x2A, 0x5E, 0xA9, 0x56, 0x43, 0x85, 0x14, 0x89, 0x9B, 0xB0, 0xE5, 0x48, 0x79, 0x97, 0xFC, 0x1E, 0x82, + 0x21, 0x8C, 0x1B, 0x5F, 0x77, 0x54, 0xB2, 0x1D, 0x25, 0x4F, 0x00, 0x46, 0xED, 0x58, 0x52, 0xEB, 0x7E, + 0xDA, 0xC9, 0xFD, 0x30, 0x95, 0x65, 0x3C, 0xB6, 0xE4, 0xBB, 0x7C, 0x0E, 0x50, 0x39, 0x26, 0x32, 0x84, + 0x69, 0x93, 0x37, 0xE7, 0x24, 0xA4, 0xCB, 0x53, 0x0A, 0x87, 0xD9, 0x4C, 0x83, 0x8F, 0xCE, 0x3B, 0x4A, + 0xB7}; + +#define SS0(x) ((s_s0[x]*0x01010101UL) & 0x3FCFF3FC) +#define SS1(x) ((s_s1[x]*0x01010101UL) & 0xFC3FCFF3) +#define SS2(x) ((s_s0[x]*0x01010101UL) & 0xF3FC3FCF) +#define SS3(x) ((s_s1[x]*0x01010101UL) & 0xCFF3FC3F) +#define G(x) (SS0(GETBYTE(x, 0)) ^ SS1(GETBYTE(x, 1)) ^ SS2(GETBYTE(x, 2)) ^ SS3(GETBYTE(x, 3))) + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void SEED::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs& /*params*/) +{ + AssertValidKeyLength(length); + + word64 key01, key23; + GetBlock get(userKey); + get(key01)(key23); + word32 *k = m_k; + ptrdiff_t kInc = 2; + + if (!IsForwardTransformation()) + { + k = k+30; + kInc = 0-kInc; + } + + for (unsigned int i=0; i>32) + word32(key23>>32) - s_kc[i]; + word32 t1 = word32(key01) - word32(key23) + s_kc[i]; + k[0] = G(t0); + k[1] = G(t1); + k+=kInc; + if (i&1) + key23 = rotlConstant<8,word64>(key23); + else + key01 = rotrConstant<8,word64>(key01); + } +} + +void SEED::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + typedef BlockGetAndPut Block; + word32 a0, a1, b0, b1, t0, t1; + Block::Get(inBlock)(a0)(a1)(b0)(b1); + + for (int i=0; i, 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/external/ours/library/crypto/src/shared/original/serpent.cpp b/external/ours/library/crypto/src/shared/original/serpent.cpp new file mode 100755 index 000000000..351186ce8 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/serpent.cpp @@ -0,0 +1,125 @@ +// serpent.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#include "serpent.h" +#include "secblock.h" +#include "misc.h" + +#include "serpentp.h" + +NAMESPACE_BEGIN(CryptoPP) + +void Serpent_KeySchedule(word32 *k, unsigned int rounds, const byte *userKey, size_t keylen) +{ + FixedSizeSecBlock k0; + GetUserKey(LITTLE_ENDIAN_ORDER, k0.begin(), 8, userKey, keylen); + if (keylen < 32) + k0[keylen/4] |= word32(1) << ((keylen%4)*8); + + word32 t = k0[7]; + unsigned int i; + for (i = 0; i < 8; ++i) + k[i] = k0[i] = t = rotlConstant<11>(k0[i] ^ k0[(i + 3) % 8] ^ k0[(i + 5) % 8] ^ t ^ 0x9e3779b9 ^ i); + for (i = 8; i < 4*(rounds+1); ++i) + k[i] = t = rotlConstant<11>(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i); + k -= 20; + + word32 a,b,c,d,e; + for (i=0; i Block; + +void Serpent::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 a, b, c, d, e; + + Block::Get(inBlock)(a)(b)(c)(d); + + const word32 *k = m_key; + unsigned int i=1; + + do + { + beforeS0(KX); beforeS0(S0); afterS0(LT); + afterS0(KX); afterS0(S1); afterS1(LT); + afterS1(KX); afterS1(S2); afterS2(LT); + afterS2(KX); afterS2(S3); afterS3(LT); + afterS3(KX); afterS3(S4); afterS4(LT); + afterS4(KX); afterS4(S5); afterS5(LT); + afterS5(KX); afterS5(S6); afterS6(LT); + afterS6(KX); afterS6(S7); + + if (i == 4) + break; + + ++i; + c = b; + b = e; + e = d; + d = a; + a = e; + k += 32; + beforeS0(LT); + } + while (true); + + afterS7(KX); + + Block::Put(xorBlock, outBlock)(d)(e)(b)(a); +} + +void Serpent::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 a, b, c, d, e=0; + + Block::Get(inBlock)(a)(b)(c)(d); + + const word32 *k = m_key + 96; + unsigned int i=4; + + beforeI7(KX); + goto start; + + do + { + c = b; + b = d; + d = e; + k -= 32; + beforeI7(ILT); +start: + beforeI7(I7); afterI7(KX); + afterI7(ILT); afterI7(I6); afterI6(KX); + afterI6(ILT); afterI6(I5); afterI5(KX); + afterI5(ILT); afterI5(I4); afterI4(KX); + afterI4(ILT); afterI4(I3); afterI3(KX); + afterI3(ILT); afterI3(I2); afterI2(KX); + afterI2(ILT); afterI2(I1); afterI1(KX); + afterI1(ILT); afterI1(I0); afterI0(KX); + } + while (--i != 0); + + Block::Put(xorBlock, outBlock)(a)(d)(b)(e); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/serpent.h b/external/ours/library/crypto/src/shared/original/serpent.h new file mode 100755 index 000000000..bd3cedbe5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/serpentp.h b/external/ours/library/crypto/src/shared/original/serpentp.h new file mode 100755 index 000000000..8df3cb8a8 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/sha.cpp b/external/ours/library/crypto/src/shared/original/sha.cpp new file mode 100755 index 000000000..30d6529f7 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/sha.cpp @@ -0,0 +1,1414 @@ +// sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c + +// Steve Reid implemented SHA-1. Wei Dai implemented SHA-2. Jeffrey +// Walton implemented Intel SHA extensions based on Intel articles and code +// by Sean Gulley. Jeffrey Walton implemented ARM SHA-1 and SHA-256 based +// on ARM code and code from Johannes Schneiders, Skip Hovsmith and +// Barry O'Rourke. Jeffrey Walton and Bill Schmidt implemented Power8 +// SHA-256 and SHA-512. All code is in the public domain. + +// In August 2017 JW reworked the internals to align all the +// implementations. Formerly all hashes were software based, IterHashBase +// handled endian conversions, and IterHashBase dispatched a single to +// block SHA{N}::Transform. SHA{N}::Transform then performed the single +// block hashing. It was repeated for multiple blocks. +// +// The rework added SHA{N}::HashMultipleBlocks (class) and +// SHA{N}_HashMultipleBlocks (free standing). There are also hardware +// accelerated variations. Callers enter SHA{N}::HashMultipleBlocks (class) +// and the function calls SHA{N}_HashMultipleBlocks (free standing) or +// SHA{N}_HashBlock (free standing) as a fallback. +// +// An added wrinkle is hardware is little endian, C++ is big endian, and +// callers use big endian, so SHA{N}_HashMultipleBlock accepts a ByteOrder +// for the incoming data arrangement. Hardware based SHA{N}_HashMultipleBlock +// can often perform the endian swap much easier by setting an EPI mask. +// Endian swap incurs no penalty on Intel SHA, and 4-instruction penalty on +// ARM SHA. Under C++ the full software based swap penalty is incurred due +// to use of ReverseBytes(). +// +// In May 2019 JW added Cryptogams ARMv7 and NEON implementations for SHA1, +// SHA256 and SHA512. The Cryptogams code closed a performance gap on modern +// 32-bit ARM devices. Cryptogams is Andy Polyakov's project used to create +// high speed crypto algorithms and share them with other developers. Andy's +// code runs 30% to 50% faster than C/C++ code. The Cryptogams code can be +// disabled in config_asm.h. An example of integrating Andy's code is at +// https://wiki.openssl.org/index.php/Cryptogams_SHA. + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sha.cpp" to generate MASM code + +#include "pch.h" +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4100 4731) +#endif + +#ifndef CRYPTOPP_IMPORTS +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#include "secblock.h" +#include "sha.h" +#include "misc.h" +#include "cpu.h" + +#if defined(CRYPTOPP_DISABLE_SHA_ASM) +# undef CRYPTOPP_X86_ASM_AVAILABLE +# undef CRYPTOPP_X32_ASM_AVAILABLE +# undef CRYPTOPP_X64_ASM_AVAILABLE +# undef CRYPTOPP_SSE2_ASM_AVAILABLE +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if CRYPTOPP_SHANI_AVAILABLE +extern void SHA1_HashMultipleBlocks_SHANI(word32 *state, const word32 *data, size_t length, ByteOrder order); +extern void SHA256_HashMultipleBlocks_SHANI(word32 *state, const word32 *data, size_t length, ByteOrder order); +#endif + +#if CRYPTOGAMS_ARM_SHA1 +extern "C" void cryptogams_sha1_block_data_order(word32* state, const word32 *data, size_t blocks); +extern "C" void cryptogams_sha1_block_data_order_neon(word32* state, const word32 *data, size_t blocks); +#endif + +#if CRYPTOPP_ARM_SHA1_AVAILABLE +extern void SHA1_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order); +#endif + +#if CRYPTOPP_ARM_SHA2_AVAILABLE +extern void SHA256_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order); +#endif + +#if CRYPTOGAMS_ARM_SHA256 +extern "C" void cryptogams_sha256_block_data_order(word32* state, const word32 *data, size_t blocks); +extern "C" void cryptogams_sha256_block_data_order_neon(word32* state, const word32 *data, size_t blocks); +#endif + +#if CRYPTOPP_ARM_SHA512_AVAILABLE +extern void SHA512_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order); +#endif + +#if CRYPTOPP_POWER8_SHA_AVAILABLE +extern void SHA256_HashMultipleBlocks_POWER8(word32 *state, const word32 *data, size_t length, ByteOrder order); +extern void SHA512_HashMultipleBlocks_POWER8(word64 *state, const word64 *data, size_t length, ByteOrder order); +#endif + +#if CRYPTOGAMS_ARM_SHA512 +extern "C" void cryptogams_sha512_block_data_order(word64* state, const word64 *data, size_t blocks); +extern "C" void cryptogams_sha512_block_data_order_neon(word64* state, const word64 *data, size_t blocks); +#endif + +// We add extern to export table to sha_simd.cpp, but it +// cleared http://github.com/weidai11/cryptopp/issues/502 +extern const word32 SHA256_K[64]; +extern const word64 SHA512_K[80]; + +CRYPTOPP_ALIGN_DATA(16) +const word64 SHA512_K[80] = { + W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), + W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), + W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), + W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), + W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), + W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), + W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), + W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), + W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), + W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), + W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), + W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), + W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), + W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), + W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), + W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), + W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), + W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), + W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), + W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), + W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), + W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), + W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), + W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), + W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), + W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), + W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), + W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), + W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), + W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), + W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), + W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), + W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), + W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), + W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), + W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), + W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), + W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), + W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), + W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) +}; + +CRYPTOPP_ALIGN_DATA(16) +const word32 SHA256_K[64] = { + + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +//////////////////////////////// +// start of Steve Reid's code // +//////////////////////////////// + +ANONYMOUS_NAMESPACE_BEGIN + +#define blk0(i) (W[i] = data[i]) +#define blk1(i) (W[i&15] = rotlConstant<1>(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15])) + +#define f1(x,y,z) (z^(x&(y^z))) +#define f2(x,y,z) (x^y^z) +#define f3(x,y,z) ((x&y)|(z&(x|y))) +#define f4(x,y,z) (x^y^z) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlConstant<5>(v);w=rotlConstant<30>(w); +#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlConstant<5>(v);w=rotlConstant<30>(w); +#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlConstant<5>(v);w=rotlConstant<30>(w); +#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlConstant<5>(v);w=rotlConstant<30>(w); +#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlConstant<5>(v);w=rotlConstant<30>(w); + +void SHA1_HashBlock_CXX(word32 *state, const word32 *data) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + + word32 W[16]; + /* Copy context->state[] to working vars */ + word32 a = state[0]; + word32 b = state[1]; + word32 c = state[2]; + word32 d = state[3]; + word32 e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; +} + +#undef blk0 +#undef blk1 +#undef f1 +#undef f2 +#undef f3 +#undef f4 +#undef R1 +#undef R2 +#undef R3 +#undef R4 + +ANONYMOUS_NAMESPACE_END + +////////////////////////////// +// end of Steve Reid's code // +////////////////////////////// + +std::string SHA1::AlgorithmProvider() const +{ +#if CRYPTOPP_SHANI_AVAILABLE + if (HasSHA()) + return "SHANI"; +#endif +#if CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return "SSE2"; +#endif +#if CRYPTOGAMS_ARM_SHA1 + if (HasNEON()) + return "NEON"; + if (HasARMv7()) + return "ARMv7"; +#endif +#if CRYPTOPP_ARM_SHA1_AVAILABLE + if (HasSHA1()) + return "ARMv8"; +#endif + return "C++"; +} + +void SHA1::InitState(HashWordType *state) +{ + state[0] = 0x67452301; + state[1] = 0xEFCDAB89; + state[2] = 0x98BADCFE; + state[3] = 0x10325476; + state[4] = 0xC3D2E1F0; +} + +void SHA1::Transform(word32 *state, const word32 *data) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + +#if CRYPTOPP_SHANI_AVAILABLE + if (HasSHA()) + { + SHA1_HashMultipleBlocks_SHANI(state, data, SHA1::BLOCKSIZE, LITTLE_ENDIAN_ORDER); + return; + } +#endif +#if CRYPTOGAMS_ARM_SHA1 && 0 + if (HasNEON()) + { +# if defined(CRYPTOPP_LITTLE_ENDIAN) + word32 dataBuf[16]; + ByteReverse(dataBuf, data, SHA1::BLOCKSIZE); + cryptogams_sha1_block_data_order_neon(state, data, 1); +# else + cryptogams_sha1_block_data_order_neon(state, data, 1); +# endif + return; + } + if (HasARMv7()) + { +# if defined(CRYPTOPP_LITTLE_ENDIAN) + word32 dataBuf[16]; + ByteReverse(dataBuf, data, SHA1::BLOCKSIZE); + cryptogams_sha1_block_data_order(state, data, 1); +# else + cryptogams_sha1_block_data_order(state, data, 1); +# endif + return; + } +#endif +#if CRYPTOPP_ARM_SHA1_AVAILABLE + if (HasSHA1()) + { + SHA1_HashMultipleBlocks_ARMV8(state, data, SHA1::BLOCKSIZE, LITTLE_ENDIAN_ORDER); + return; + } +#endif + + SHA1_HashBlock_CXX(state, data); +} + +size_t SHA1::HashMultipleBlocks(const word32 *input, size_t length) +{ + CRYPTOPP_ASSERT(input); + CRYPTOPP_ASSERT(length >= SHA1::BLOCKSIZE); + +#if CRYPTOPP_SHANI_AVAILABLE + if (HasSHA()) + { + SHA1_HashMultipleBlocks_SHANI(m_state, input, length, BIG_ENDIAN_ORDER); + return length & (SHA1::BLOCKSIZE - 1); + } +#endif +#if CRYPTOGAMS_ARM_SHA1 + if (HasNEON()) + { + cryptogams_sha1_block_data_order_neon(m_state, input, length / SHA1::BLOCKSIZE); + return length & (SHA1::BLOCKSIZE - 1); + } + if (HasARMv7()) + { + cryptogams_sha1_block_data_order(m_state, input, length / SHA1::BLOCKSIZE); + return length & (SHA1::BLOCKSIZE - 1); + } +#endif +#if CRYPTOPP_ARM_SHA1_AVAILABLE + if (HasSHA1()) + { + SHA1_HashMultipleBlocks_ARMV8(m_state, input, length, BIG_ENDIAN_ORDER); + return length & (SHA1::BLOCKSIZE - 1); + } +#endif + + const bool noReverse = NativeByteOrderIs(this->GetByteOrder()); + word32 *dataBuf = this->DataBuf(); + do + { + if (noReverse) + { + SHA1_HashBlock_CXX(m_state, input); + } + else + { + ByteReverse(dataBuf, input, SHA1::BLOCKSIZE); + SHA1_HashBlock_CXX(m_state, dataBuf); + } + + input += SHA1::BLOCKSIZE/sizeof(word32); + length -= SHA1::BLOCKSIZE; + } + while (length >= SHA1::BLOCKSIZE); + return length; +} + +// ************************************************************* + +ANONYMOUS_NAMESPACE_BEGIN + +#define a(i) T[(0-i)&7] +#define b(i) T[(1-i)&7] +#define c(i) T[(2-i)&7] +#define d(i) T[(3-i)&7] +#define e(i) T[(4-i)&7] +#define f(i) T[(5-i)&7] +#define g(i) T[(6-i)&7] +#define h(i) T[(7-i)&7] + +#define blk0(i) (W[i] = data[i]) +#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) (y^((x^y)&(y^z))) + +#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\ + d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) + +// for SHA256 +#define s0(x) (rotrConstant<7>(x)^rotrConstant<18>(x)^(x>>3)) +#define s1(x) (rotrConstant<17>(x)^rotrConstant<19>(x)^(x>>10)) +#define S0(x) (rotrConstant<2>(x)^rotrConstant<13>(x)^rotrConstant<22>(x)) +#define S1(x) (rotrConstant<6>(x)^rotrConstant<11>(x)^rotrConstant<25>(x)) + +void SHA256_HashBlock_CXX(word32 *state, const word32 *data) +{ + word32 W[16]={0}, T[8]; + /* Copy context->state[] to working vars */ + memcpy(T, state, sizeof(T)); + /* 64 operations, partially loop unrolled */ + for (unsigned int j=0; j<64; j+=16) + { + R( 0); R( 1); R( 2); R( 3); + R( 4); R( 5); R( 6); R( 7); + R( 8); R( 9); R(10); R(11); + R(12); R(13); R(14); R(15); + } + /* Add the working vars back into context.state[] */ + state[0] += a(0); + state[1] += b(0); + state[2] += c(0); + state[3] += d(0); + state[4] += e(0); + state[5] += f(0); + state[6] += g(0); + state[7] += h(0); +} + +#undef Ch +#undef Maj +#undef s0 +#undef s1 +#undef S0 +#undef S1 +#undef blk0 +#undef blk1 +#undef blk2 +#undef R + +#undef a +#undef b +#undef c +#undef d +#undef e +#undef f +#undef g +#undef h + +ANONYMOUS_NAMESPACE_END + +std::string SHA256_AlgorithmProvider() +{ +#if CRYPTOPP_SHANI_AVAILABLE + if (HasSHA()) + return "SHANI"; +#endif +#if CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return "SSE2"; +#endif +#if CRYPTOGAMS_ARM_SHA256 + if (HasNEON()) + return "NEON"; + if (HasARMv7()) + return "ARMv7"; +#endif +#if CRYPTOPP_ARM_SHA2_AVAILABLE + if (HasSHA2()) + return "ARMv8"; +#endif +#if (CRYPTOPP_POWER8_SHA_AVAILABLE) + if (HasSHA256()) + return "Power8"; +#endif + return "C++"; +} + +std::string SHA224::AlgorithmProvider() const +{ + return SHA256_AlgorithmProvider(); +} + +void SHA224::InitState(HashWordType *state) +{ + static const word32 s[8] = { + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}; + memcpy(state, s, sizeof(s)); +} + +void SHA256::InitState(HashWordType *state) +{ + static const word32 s[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + memcpy(state, s, sizeof(s)); +} +#endif // Not CRYPTOPP_GENERATE_X64_MASM + +#if defined(CRYPTOPP_X86_ASM_AVAILABLE) + +ANONYMOUS_NAMESPACE_BEGIN + +void CRYPTOPP_FASTCALL SHA256_HashMultipleBlocks_SSE2(word32 *state, const word32 *data, size_t len) +{ + #define LOCALS_SIZE 8*4 + 16*4 + 4*WORD_SZ + #define H(i) [BASE+ASM_MOD(1024+7-(i),8)*4] + #define G(i) H(i+1) + #define F(i) H(i+2) + #define E(i) H(i+3) + #define D(i) H(i+4) + #define C(i) H(i+5) + #define B(i) H(i+6) + #define A(i) H(i+7) + #define Wt(i) BASE+8*4+ASM_MOD(1024+15-(i),16)*4 + #define Wt_2(i) Wt((i)-2) + #define Wt_15(i) Wt((i)-15) + #define Wt_7(i) Wt((i)-7) + #define K_END [BASE+8*4+16*4+0*WORD_SZ] + #define STATE_SAVE [BASE+8*4+16*4+1*WORD_SZ] + #define DATA_SAVE [BASE+8*4+16*4+2*WORD_SZ] + #define DATA_END [BASE+8*4+16*4+3*WORD_SZ] + #define Kt(i) WORD_REG(si)+(i)*4 +#if CRYPTOPP_BOOL_X86 + #define BASE esp+4 +#elif defined(__GNUC__) + #define BASE r8 +#else + #define BASE rsp +#endif + +#define RA0(i, edx, edi) \ + AS2( add edx, [Kt(i)] )\ + AS2( add edx, [Wt(i)] )\ + AS2( add edx, H(i) )\ + +#define RA1(i, edx, edi) + +#define RB0(i, edx, edi) + +#define RB1(i, edx, edi) \ + AS2( mov AS_REG_7d, [Wt_2(i)] )\ + AS2( mov edi, [Wt_15(i)])\ + AS2( mov ebx, AS_REG_7d )\ + AS2( shr AS_REG_7d, 10 )\ + AS2( ror ebx, 17 )\ + AS2( xor AS_REG_7d, ebx )\ + AS2( ror ebx, 2 )\ + AS2( xor ebx, AS_REG_7d )/* s1(W_t-2) */\ + AS2( add ebx, [Wt_7(i)])\ + AS2( mov AS_REG_7d, edi )\ + AS2( shr AS_REG_7d, 3 )\ + AS2( ror edi, 7 )\ + AS2( add ebx, [Wt(i)])/* s1(W_t-2) + W_t-7 + W_t-16 */\ + AS2( xor AS_REG_7d, edi )\ + AS2( add edx, [Kt(i)])\ + AS2( ror edi, 11 )\ + AS2( add edx, H(i) )\ + AS2( xor AS_REG_7d, edi )/* s0(W_t-15) */\ + AS2( add AS_REG_7d, ebx )/* W_t = s1(W_t-2) + W_t-7 + s0(W_t-15) W_t-16*/\ + AS2( mov [Wt(i)], AS_REG_7d)\ + AS2( add edx, AS_REG_7d )\ + +#define ROUND(i, r, eax, ecx, edi, edx)\ + /* in: edi = E */\ + /* unused: eax, ecx, temp: ebx, AS_REG_7d, out: edx = T1 */\ + AS2( mov edx, F(i) )\ + AS2( xor edx, G(i) )\ + AS2( and edx, edi )\ + AS2( xor edx, G(i) )/* Ch(E,F,G) = (G^(E&(F^G))) */\ + AS2( mov AS_REG_7d, edi )\ + AS2( ror edi, 6 )\ + AS2( ror AS_REG_7d, 25 )\ + RA##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\ + AS2( xor AS_REG_7d, edi )\ + AS2( ror edi, 5 )\ + AS2( xor AS_REG_7d, edi )/* S1(E) */\ + AS2( add edx, AS_REG_7d )/* T1 = S1(E) + Ch(E,F,G) + H + Wt + Kt */\ + RB##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\ + /* in: ecx = A, eax = B^C, edx = T1 */\ + /* unused: edx, temp: ebx, AS_REG_7d, out: eax = A, ecx = B^C, edx = E */\ + AS2( mov ebx, ecx )\ + AS2( xor ecx, B(i) )/* A^B */\ + AS2( and eax, ecx )\ + AS2( xor eax, B(i) )/* Maj(A,B,C) = B^((A^B)&(B^C) */\ + AS2( mov AS_REG_7d, ebx )\ + AS2( ror ebx, 2 )\ + AS2( add eax, edx )/* T1 + Maj(A,B,C) */\ + AS2( add edx, D(i) )\ + AS2( mov D(i), edx )\ + AS2( ror AS_REG_7d, 22 )\ + AS2( xor AS_REG_7d, ebx )\ + AS2( ror ebx, 11 )\ + AS2( xor AS_REG_7d, ebx )\ + AS2( add eax, AS_REG_7d )/* T1 + S0(A) + Maj(A,B,C) */\ + AS2( mov H(i), eax )\ + +// Unroll the use of CRYPTOPP_BOOL_X64 in assembler math. The GAS assembler on X32 (version 2.25) +// complains "Error: invalid operands (*ABS* and *UND* sections) for `*` and `-`" +#if CRYPTOPP_BOOL_X64 +#define SWAP_COPY(i) \ + AS2( mov WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\ + AS1( bswap WORD_REG(bx))\ + AS2( mov [Wt(i*2+1)], WORD_REG(bx)) +#else // X86 and X32 +#define SWAP_COPY(i) \ + AS2( mov WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\ + AS1( bswap WORD_REG(bx))\ + AS2( mov [Wt(i)], WORD_REG(bx)) +#endif + +#if defined(__GNUC__) + #if CRYPTOPP_BOOL_X64 + FixedSizeAlignedSecBlock workspace; + #endif + __asm__ __volatile__ + ( + #if CRYPTOPP_BOOL_X64 + "lea %4, %%r8;" + #endif + INTEL_NOPREFIX +#elif defined(CRYPTOPP_GENERATE_X64_MASM) + ALIGN 8 + SHA256_HashMultipleBlocks_SSE2 PROC FRAME + rex_push_reg rsi + push_reg rdi + push_reg rbx + push_reg rbp + alloc_stack(LOCALS_SIZE+8) + .endprolog + mov rdi, r8 + lea rsi, [?SHA256_K@CryptoPP@@3QBIB + 48*4] +#endif + +#if CRYPTOPP_BOOL_X86 + #ifndef __GNUC__ + AS2( mov edi, [len]) + AS2( lea WORD_REG(si), [SHA256_K+48*4]) + #endif + #if !defined(_MSC_VER) || (_MSC_VER < 1400) + AS_PUSH_IF86(bx) + #endif + + AS_PUSH_IF86(bp) + AS2( mov ebx, esp) + AS2( and esp, -16) + AS2( sub WORD_REG(sp), LOCALS_SIZE) + AS_PUSH_IF86(bx) +#endif + AS2( mov STATE_SAVE, WORD_REG(cx)) + AS2( mov DATA_SAVE, WORD_REG(dx)) + AS2( lea WORD_REG(ax), [WORD_REG(di) + WORD_REG(dx)]) + AS2( mov DATA_END, WORD_REG(ax)) + AS2( mov K_END, WORD_REG(si)) + +#if CRYPTOPP_SSE2_ASM_AVAILABLE +#if CRYPTOPP_BOOL_X86 + AS2( test edi, 1) + ASJ( jnz, 2, f) + AS1( dec DWORD PTR K_END) +#endif + AS2( movdqu xmm0, XMMWORD_PTR [WORD_REG(cx)+0*16]) + AS2( movdqu xmm1, XMMWORD_PTR [WORD_REG(cx)+1*16]) +#endif + +#if CRYPTOPP_BOOL_X86 +#if CRYPTOPP_SSE2_ASM_AVAILABLE + ASJ( jmp, 0, f) +#endif + ASL(2) // non-SSE2 + AS2( mov esi, ecx) + AS2( lea edi, A(0)) + AS2( mov ecx, 8) +ATT_NOPREFIX + AS1( rep movsd) +INTEL_NOPREFIX + AS2( mov esi, K_END) + ASJ( jmp, 3, f) +#endif + +#if CRYPTOPP_SSE2_ASM_AVAILABLE + ASL(0) + AS2( movdqu E(0), xmm1) + AS2( movdqu A(0), xmm0) +#endif +#if CRYPTOPP_BOOL_X86 + ASL(3) +#endif + AS2( sub WORD_REG(si), 48*4) + SWAP_COPY(0) SWAP_COPY(1) SWAP_COPY(2) SWAP_COPY(3) + SWAP_COPY(4) SWAP_COPY(5) SWAP_COPY(6) SWAP_COPY(7) +#if CRYPTOPP_BOOL_X86 + SWAP_COPY(8) SWAP_COPY(9) SWAP_COPY(10) SWAP_COPY(11) + SWAP_COPY(12) SWAP_COPY(13) SWAP_COPY(14) SWAP_COPY(15) +#endif + AS2( mov edi, E(0)) // E + AS2( mov eax, B(0)) // B + AS2( xor eax, C(0)) // B^C + AS2( mov ecx, A(0)) // A + + ROUND(0, 0, eax, ecx, edi, edx) + ROUND(1, 0, ecx, eax, edx, edi) + ROUND(2, 0, eax, ecx, edi, edx) + ROUND(3, 0, ecx, eax, edx, edi) + ROUND(4, 0, eax, ecx, edi, edx) + ROUND(5, 0, ecx, eax, edx, edi) + ROUND(6, 0, eax, ecx, edi, edx) + ROUND(7, 0, ecx, eax, edx, edi) + ROUND(8, 0, eax, ecx, edi, edx) + ROUND(9, 0, ecx, eax, edx, edi) + ROUND(10, 0, eax, ecx, edi, edx) + ROUND(11, 0, ecx, eax, edx, edi) + ROUND(12, 0, eax, ecx, edi, edx) + ROUND(13, 0, ecx, eax, edx, edi) + ROUND(14, 0, eax, ecx, edi, edx) + ROUND(15, 0, ecx, eax, edx, edi) + + ASL(1) + AS2(add WORD_REG(si), 4*16) + ROUND(0, 1, eax, ecx, edi, edx) + ROUND(1, 1, ecx, eax, edx, edi) + ROUND(2, 1, eax, ecx, edi, edx) + ROUND(3, 1, ecx, eax, edx, edi) + ROUND(4, 1, eax, ecx, edi, edx) + ROUND(5, 1, ecx, eax, edx, edi) + ROUND(6, 1, eax, ecx, edi, edx) + ROUND(7, 1, ecx, eax, edx, edi) + ROUND(8, 1, eax, ecx, edi, edx) + ROUND(9, 1, ecx, eax, edx, edi) + ROUND(10, 1, eax, ecx, edi, edx) + ROUND(11, 1, ecx, eax, edx, edi) + ROUND(12, 1, eax, ecx, edi, edx) + ROUND(13, 1, ecx, eax, edx, edi) + ROUND(14, 1, eax, ecx, edi, edx) + ROUND(15, 1, ecx, eax, edx, edi) + AS2( cmp WORD_REG(si), K_END) + ATT_NOPREFIX + ASJ( jb, 1, b) + INTEL_NOPREFIX + + AS2( mov WORD_REG(dx), DATA_SAVE) + AS2( add WORD_REG(dx), 64) + AS2( mov AS_REG_7, STATE_SAVE) + AS2( mov DATA_SAVE, WORD_REG(dx)) + +#if CRYPTOPP_SSE2_ASM_AVAILABLE +#if CRYPTOPP_BOOL_X86 + AS2( test DWORD PTR K_END, 1) + ASJ( jz, 4, f) +#endif + AS2( movdqu xmm1, XMMWORD_PTR [AS_REG_7+1*16]) + AS2( movdqu xmm0, XMMWORD_PTR [AS_REG_7+0*16]) + AS2( paddd xmm1, E(0)) + AS2( paddd xmm0, A(0)) + AS2( movdqu [AS_REG_7+1*16], xmm1) + AS2( movdqu [AS_REG_7+0*16], xmm0) + AS2( cmp WORD_REG(dx), DATA_END) + ATT_NOPREFIX + ASJ( jb, 0, b) + INTEL_NOPREFIX +#endif + +#if CRYPTOPP_BOOL_X86 +#if CRYPTOPP_SSE2_ASM_AVAILABLE + ASJ( jmp, 5, f) + ASL(4) // non-SSE2 +#endif + AS2( add [AS_REG_7+0*4], ecx) // A + AS2( add [AS_REG_7+4*4], edi) // E + AS2( mov eax, B(0)) + AS2( mov ebx, C(0)) + AS2( mov ecx, D(0)) + AS2( add [AS_REG_7+1*4], eax) + AS2( add [AS_REG_7+2*4], ebx) + AS2( add [AS_REG_7+3*4], ecx) + AS2( mov eax, F(0)) + AS2( mov ebx, G(0)) + AS2( mov ecx, H(0)) + AS2( add [AS_REG_7+5*4], eax) + AS2( add [AS_REG_7+6*4], ebx) + AS2( add [AS_REG_7+7*4], ecx) + AS2( mov ecx, AS_REG_7d) + AS2( cmp WORD_REG(dx), DATA_END) + ASJ( jb, 2, b) +#if CRYPTOPP_SSE2_ASM_AVAILABLE + ASL(5) +#endif +#endif + + AS_POP_IF86(sp) + AS_POP_IF86(bp) + #if !defined(_MSC_VER) || (_MSC_VER < 1400) + AS_POP_IF86(bx) + #endif + +#ifdef CRYPTOPP_GENERATE_X64_MASM + add rsp, LOCALS_SIZE+8 + pop rbp + pop rbx + pop rdi + pop rsi + ret + SHA256_HashMultipleBlocks_SSE2 ENDP +#endif + +#ifdef __GNUC__ + ATT_PREFIX + : + : "c" (state), "d" (data), "S" (SHA256_K+48), "D" (len) + #if CRYPTOPP_BOOL_X64 + , "m" (workspace[0]) + #endif + : "memory", "cc", "%eax" + #if CRYPTOPP_BOOL_X64 + , "%rbx", "%r8", "%r10" + #endif + ); +#endif +} + +ANONYMOUS_NAMESPACE_END + +#endif // CRYPTOPP_X86_ASM_AVAILABLE + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void CRYPTOPP_FASTCALL SHA256_HashMultipleBlocks_SSE2(word32 *state, const word32 *data, size_t len); +} +#endif + +std::string SHA256::AlgorithmProvider() const +{ + return SHA256_AlgorithmProvider(); +} + +void SHA256::Transform(word32 *state, const word32 *data) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + +#if CRYPTOPP_SHANI_AVAILABLE + if (HasSHA()) + { + SHA256_HashMultipleBlocks_SHANI(state, data, SHA256::BLOCKSIZE, LITTLE_ENDIAN_ORDER); + return; + } +#endif +#if CRYPTOGAMS_ARM_SHA256 && 0 + if (HasNEON()) + { +# if defined(CRYPTOPP_LITTLE_ENDIAN) + word32 dataBuf[16]; + ByteReverse(dataBuf, data, SHA256::BLOCKSIZE); + cryptogams_sha256_block_data_order_neon(state, data, 1); +# else + cryptogams_sha256_block_data_order_neon(state, data, 1); +# endif + return; + } + if (HasARMv7()) + { +# if defined(CRYPTOPP_LITTLE_ENDIAN) + word32 dataBuf[16]; + ByteReverse(dataBuf, data, SHA256::BLOCKSIZE); + cryptogams_sha256_block_data_order(state, data, 1); +# else + cryptogams_sha256_block_data_order(state, data, 1); +# endif + return; + } +#endif +#if CRYPTOPP_ARM_SHA2_AVAILABLE + if (HasSHA2()) + { + SHA256_HashMultipleBlocks_ARMV8(state, data, SHA256::BLOCKSIZE, LITTLE_ENDIAN_ORDER); + return; + } +#endif +#if CRYPTOPP_POWER8_SHA_AVAILABLE + if (HasSHA256()) + { + SHA256_HashMultipleBlocks_POWER8(state, data, SHA256::BLOCKSIZE, LITTLE_ENDIAN_ORDER); + return; + } +#endif + + SHA256_HashBlock_CXX(state, data); +} + +size_t SHA256::HashMultipleBlocks(const word32 *input, size_t length) +{ + CRYPTOPP_ASSERT(input); + CRYPTOPP_ASSERT(length >= SHA256::BLOCKSIZE); + +#if CRYPTOPP_SHANI_AVAILABLE + if (HasSHA()) + { + SHA256_HashMultipleBlocks_SHANI(m_state, input, length, BIG_ENDIAN_ORDER); + return length & (SHA256::BLOCKSIZE - 1); + } +#endif +#if CRYPTOPP_SSE2_ASM_AVAILABLE || CRYPTOPP_X64_MASM_AVAILABLE + if (HasSSE2()) + { + const size_t res = length & (SHA256::BLOCKSIZE - 1); + SHA256_HashMultipleBlocks_SSE2(m_state, input, length-res); + return res; + } +#endif +#if CRYPTOGAMS_ARM_SHA256 + if (HasNEON()) + { + cryptogams_sha256_block_data_order_neon(m_state, input, length / SHA256::BLOCKSIZE); + return length & (SHA256::BLOCKSIZE - 1); + } + if (HasARMv7()) + { + cryptogams_sha256_block_data_order(m_state, input, length / SHA256::BLOCKSIZE); + return length & (SHA256::BLOCKSIZE - 1); + } +#endif +#if CRYPTOPP_ARM_SHA2_AVAILABLE + if (HasSHA2()) + { + SHA256_HashMultipleBlocks_ARMV8(m_state, input, length, BIG_ENDIAN_ORDER); + return length & (SHA256::BLOCKSIZE - 1); + } +#endif +#if CRYPTOPP_POWER8_SHA_AVAILABLE + if (HasSHA256()) + { + SHA256_HashMultipleBlocks_POWER8(m_state, input, length, BIG_ENDIAN_ORDER); + return length & (SHA256::BLOCKSIZE - 1); + } +#endif + + const bool noReverse = NativeByteOrderIs(this->GetByteOrder()); + word32 *dataBuf = this->DataBuf(); + do + { + if (noReverse) + { + SHA256_HashBlock_CXX(m_state, input); + } + else + { + ByteReverse(dataBuf, input, SHA256::BLOCKSIZE); + SHA256_HashBlock_CXX(m_state, dataBuf); + } + + input += SHA256::BLOCKSIZE/sizeof(word32); + length -= SHA256::BLOCKSIZE; + } + while (length >= SHA256::BLOCKSIZE); + return length; +} + +size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length) +{ + CRYPTOPP_ASSERT(input); + CRYPTOPP_ASSERT(length >= SHA256::BLOCKSIZE); + +#if CRYPTOPP_SHANI_AVAILABLE + if (HasSHA()) + { + SHA256_HashMultipleBlocks_SHANI(m_state, input, length, BIG_ENDIAN_ORDER); + return length & (SHA256::BLOCKSIZE - 1); + } +#endif +#if CRYPTOPP_SSE2_ASM_AVAILABLE || CRYPTOPP_X64_MASM_AVAILABLE + if (HasSSE2()) + { + const size_t res = length & (SHA256::BLOCKSIZE - 1); + SHA256_HashMultipleBlocks_SSE2(m_state, input, length-res); + return res; + } +#endif +#if CRYPTOGAMS_ARM_SHA256 + if (HasNEON()) + { + cryptogams_sha256_block_data_order_neon(m_state, input, length / SHA256::BLOCKSIZE); + return length & (SHA256::BLOCKSIZE - 1); + } + if (HasARMv7()) + { + cryptogams_sha256_block_data_order(m_state, input, length / SHA256::BLOCKSIZE); + return length & (SHA256::BLOCKSIZE - 1); + } +#endif +#if CRYPTOPP_ARM_SHA2_AVAILABLE + if (HasSHA2()) + { + SHA256_HashMultipleBlocks_ARMV8(m_state, input, length, BIG_ENDIAN_ORDER); + return length & (SHA256::BLOCKSIZE - 1); + } +#endif +#if CRYPTOPP_POWER8_SHA_AVAILABLE + if (HasSHA256()) + { + SHA256_HashMultipleBlocks_POWER8(m_state, input, length, BIG_ENDIAN_ORDER); + return length & (SHA256::BLOCKSIZE - 1); + } +#endif + + const bool noReverse = NativeByteOrderIs(this->GetByteOrder()); + word32 *dataBuf = this->DataBuf(); + do + { + if (noReverse) + { + SHA256_HashBlock_CXX(m_state, input); + } + else + { + ByteReverse(dataBuf, input, SHA256::BLOCKSIZE); + SHA256_HashBlock_CXX(m_state, dataBuf); + } + + input += SHA256::BLOCKSIZE/sizeof(word32); + length -= SHA256::BLOCKSIZE; + } + while (length >= SHA256::BLOCKSIZE); + return length; +} + +// ************************************************************* + +std::string SHA512_AlgorithmProvider() +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return "SSE2"; +#endif +#if CRYPTOGAMS_ARM_SHA512 + if (HasNEON()) + return "NEON"; + if (HasARMv7()) + return "ARMv7"; +#endif +#if (CRYPTOPP_POWER8_SHA_AVAILABLE) + if (HasSHA512()) + return "Power8"; +#endif + return "C++"; +} + +std::string SHA384::AlgorithmProvider() const +{ + return SHA512_AlgorithmProvider(); +} + +std::string SHA512::AlgorithmProvider() const +{ + return SHA512_AlgorithmProvider(); +} + +void SHA384::InitState(HashWordType *state) +{ + const word64 s[8] = { + W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507), + W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939), + W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511), + W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)}; + memcpy(state, s, sizeof(s)); +} + +void SHA512::InitState(HashWordType *state) +{ + const word64 s[8] = { + W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b), + W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1), + W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f), + W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)}; + memcpy(state, s, sizeof(s)); +} + +#if CRYPTOPP_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86) + +ANONYMOUS_NAMESPACE_BEGIN + +// No inlining due to https://github.com/weidai11/cryptopp/issues/684 +// g++ -DNDEBUG -g2 -O3 -pthread -pipe -c sha.cpp +// sha.cpp: Assembler messages: +// sha.cpp:1155: Error: symbol `SHA512_Round' is already defined +// sha.cpp:1155: Error: symbol `SHA512_Round' is already defined + +CRYPTOPP_NOINLINE CRYPTOPP_NAKED +void CRYPTOPP_FASTCALL SHA512_HashBlock_SSE2(word64 *state, const word64 *data) +{ +#ifdef __GNUC__ + __asm__ __volatile__ + ( + INTEL_NOPREFIX + AS_PUSH_IF86( bx) + AS2( mov ebx, eax) +#else + AS1( push ebx) + AS1( push esi) + AS1( push edi) + AS2( lea ebx, SHA512_K) +#endif + + AS2( mov eax, esp) + AS2( and esp, 0xfffffff0) + AS2( sub esp, 27*16) // 17*16 for expanded data, 20*8 for state + AS_PUSH_IF86( ax) + AS2( xor eax, eax) + + AS2( lea edi, [esp+4+8*8]) // start at middle of state buffer. will decrement pointer each round to avoid copying + AS2( lea esi, [esp+4+20*8+8]) // 16-byte alignment, then add 8 + + AS2( movdqu xmm0, [ecx+0*16]) + AS2( movdq2q mm4, xmm0) + AS2( movdqu [edi+0*16], xmm0) + AS2( movdqu xmm0, [ecx+1*16]) + AS2( movdqu [edi+1*16], xmm0) + AS2( movdqu xmm0, [ecx+2*16]) + AS2( movdq2q mm5, xmm0) + AS2( movdqu [edi+2*16], xmm0) + AS2( movdqu xmm0, [ecx+3*16]) + AS2( movdqu [edi+3*16], xmm0) + ASJ( jmp, 0, f) + +#define SSE2_S0_S1(r, a, b, c) \ + AS2( movq mm6, r)\ + AS2( psrlq r, a)\ + AS2( movq mm7, r)\ + AS2( psllq mm6, 64-c)\ + AS2( pxor mm7, mm6)\ + AS2( psrlq r, b-a)\ + AS2( pxor mm7, r)\ + AS2( psllq mm6, c-b)\ + AS2( pxor mm7, mm6)\ + AS2( psrlq r, c-b)\ + AS2( pxor r, mm7)\ + AS2( psllq mm6, b-a)\ + AS2( pxor r, mm6) + +#define SSE2_s0(r, a, b, c) \ + AS2( movdqu xmm6, r)\ + AS2( psrlq r, a)\ + AS2( movdqu xmm7, r)\ + AS2( psllq xmm6, 64-c)\ + AS2( pxor xmm7, xmm6)\ + AS2( psrlq r, b-a)\ + AS2( pxor xmm7, r)\ + AS2( psrlq r, c-b)\ + AS2( pxor r, xmm7)\ + AS2( psllq xmm6, c-a)\ + AS2( pxor r, xmm6) + +#define SSE2_s1(r, a, b, c) \ + AS2( movdqu xmm6, r)\ + AS2( psrlq r, a)\ + AS2( movdqu xmm7, r)\ + AS2( psllq xmm6, 64-c)\ + AS2( pxor xmm7, xmm6)\ + AS2( psrlq r, b-a)\ + AS2( pxor xmm7, r)\ + AS2( psllq xmm6, c-b)\ + AS2( pxor xmm7, xmm6)\ + AS2( psrlq r, c-b)\ + AS2( pxor r, xmm7) + ASL(SHA512_Round) + + // k + w is in mm0, a is in mm4, e is in mm5 + AS2( paddq mm0, [edi+7*8]) // h + AS2( movq mm2, [edi+5*8]) // f + AS2( movq mm3, [edi+6*8]) // g + AS2( pxor mm2, mm3) + AS2( pand mm2, mm5) + SSE2_S0_S1(mm5,14,18,41) + AS2( pxor mm2, mm3) + AS2( paddq mm0, mm2) // h += Ch(e,f,g) + AS2( paddq mm5, mm0) // h += S1(e) + AS2( movq mm2, [edi+1*8]) // b + AS2( movq mm1, mm2) + AS2( por mm2, mm4) + AS2( pand mm2, [edi+2*8]) // c + AS2( pand mm1, mm4) + AS2( por mm1, mm2) + AS2( paddq mm1, mm5) // temp = h + Maj(a,b,c) + AS2( paddq mm5, [edi+3*8]) // e = d + h + AS2( movq [edi+3*8], mm5) + AS2( movq [edi+11*8], mm5) + SSE2_S0_S1(mm4,28,34,39) // S0(a) + AS2( paddq mm4, mm1) // a = temp + S0(a) + AS2( movq [edi-8], mm4) + AS2( movq [edi+7*8], mm4) + AS1( ret) + + // first 16 rounds + ASL(0) + AS2( movq mm0, [edx+eax*8]) + AS2( movq [esi+eax*8], mm0) + AS2( movq [esi+eax*8+16*8], mm0) + AS2( paddq mm0, [ebx+eax*8]) + ASC( call, SHA512_Round) + + AS1( inc eax) + AS2( sub edi, 8) + AS2( test eax, 7) + ASJ( jnz, 0, b) + AS2( add edi, 8*8) + AS2( cmp eax, 16) + ASJ( jne, 0, b) + + // rest of the rounds + AS2( movdqu xmm0, [esi+(16-2)*8]) + ASL(1) + // data expansion, W[i-2] already in xmm0 + AS2( movdqu xmm3, [esi]) + AS2( paddq xmm3, [esi+(16-7)*8]) + AS2( movdqu xmm2, [esi+(16-15)*8]) + SSE2_s1(xmm0, 6, 19, 61) + AS2( paddq xmm0, xmm3) + SSE2_s0(xmm2, 1, 7, 8) + AS2( paddq xmm0, xmm2) + AS2( movdq2q mm0, xmm0) + AS2( movhlps xmm1, xmm0) + AS2( paddq mm0, [ebx+eax*8]) + AS2( movlps [esi], xmm0) + AS2( movlps [esi+8], xmm1) + AS2( movlps [esi+8*16], xmm0) + AS2( movlps [esi+8*17], xmm1) + // 2 rounds + ASC( call, SHA512_Round) + AS2( sub edi, 8) + AS2( movdq2q mm0, xmm1) + AS2( paddq mm0, [ebx+eax*8+8]) + ASC( call, SHA512_Round) + // update indices and loop + AS2( add esi, 16) + AS2( add eax, 2) + AS2( sub edi, 8) + AS2( test eax, 7) + ASJ( jnz, 1, b) + // do housekeeping every 8 rounds + AS2( mov esi, 0xf) + AS2( and esi, eax) + AS2( lea esi, [esp+4+20*8+8+esi*8]) + AS2( add edi, 8*8) + AS2( cmp eax, 80) + ASJ( jne, 1, b) + +#define SSE2_CombineState(i) \ + AS2( movdqu xmm0, [edi+i*16])\ + AS2( paddq xmm0, [ecx+i*16])\ + AS2( movdqu [ecx+i*16], xmm0) + + SSE2_CombineState(0) + SSE2_CombineState(1) + SSE2_CombineState(2) + SSE2_CombineState(3) + + AS_POP_IF86( sp) + AS1( emms) + +#if defined(__GNUC__) + AS_POP_IF86( bx) + ATT_PREFIX + : + : "a" (SHA512_K), "c" (state), "d" (data) + : "%esi", "%edi", "memory", "cc" + ); +#else + AS1( pop edi) + AS1( pop esi) + AS1( pop ebx) + AS1( ret) +#endif +} + +ANONYMOUS_NAMESPACE_END + +#endif // CRYPTOPP_SSE2_ASM_AVAILABLE + +ANONYMOUS_NAMESPACE_BEGIN + +#define a(i) T[(0-i)&7] +#define b(i) T[(1-i)&7] +#define c(i) T[(2-i)&7] +#define d(i) T[(3-i)&7] +#define e(i) T[(4-i)&7] +#define f(i) T[(5-i)&7] +#define g(i) T[(6-i)&7] +#define h(i) T[(7-i)&7] + +#define blk0(i) (W[i]=data[i]) +#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) (y^((x^y)&(y^z))) + +#define s0(x) (rotrConstant<1>(x)^rotrConstant<8>(x)^(x>>7)) +#define s1(x) (rotrConstant<19>(x)^rotrConstant<61>(x)^(x>>6)) +#define S0(x) (rotrConstant<28>(x)^rotrConstant<34>(x)^rotrConstant<39>(x)) +#define S1(x) (rotrConstant<14>(x)^rotrConstant<18>(x)^rotrConstant<41>(x)) + +#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+\ + (j?blk2(i):blk0(i));d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)); + +void SHA512_HashBlock_CXX(word64 *state, const word64 *data) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + + word64 W[16]={0}, T[8]; + + /* Copy context->state[] to working vars */ + std::memcpy(T, state, sizeof(T)); + + /* 80 operations, partially loop unrolled */ + for (unsigned int j=0; j<80; j+=16) + { + R( 0); R( 1); R( 2); R( 3); + R( 4); R( 5); R( 6); R( 7); + R( 8); R( 9); R(10); R(11); + R(12); R(13); R(14); R(15); + } + + state[0] += a(0); + state[1] += b(0); + state[2] += c(0); + state[3] += d(0); + state[4] += e(0); + state[5] += f(0); + state[6] += g(0); + state[7] += h(0); +} + +ANONYMOUS_NAMESPACE_END + +void SHA512::Transform(word64 *state, const word64 *data) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + +#if CRYPTOPP_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86) + if (HasSSE2()) + { + SHA512_HashBlock_SSE2(state, data); + return; + } +#endif +#if CRYPTOGAMS_ARM_SHA512 + if (HasNEON()) + { +# if (CRYPTOPP_LITTLE_ENDIAN) + word64 dataBuf[16]; + ByteReverse(dataBuf, data, SHA512::BLOCKSIZE); + cryptogams_sha512_block_data_order_neon(state, dataBuf, 1); +# else + cryptogams_sha512_block_data_order_neon(state, data, 1); +# endif + return; + } + if (HasARMv7()) + { +# if (CRYPTOPP_LITTLE_ENDIAN) + word64 dataBuf[16]; + ByteReverse(dataBuf, data, SHA512::BLOCKSIZE); + cryptogams_sha512_block_data_order(state, dataBuf, 1); +# else + cryptogams_sha512_block_data_order(state, data, 1); +# endif + return; + } +#endif +#if CRYPTOPP_POWER8_SHA_AVAILABLE + if (HasSHA512()) + { + SHA512_HashMultipleBlocks_POWER8(state, data, SHA512::BLOCKSIZE, BIG_ENDIAN_ORDER); + return; + } +#endif + + SHA512_HashBlock_CXX(state, data); +} + +#undef Ch +#undef Maj + +#undef s0 +#undef s1 +#undef S0 +#undef S1 + +#undef blk0 +#undef blk1 +#undef blk2 + +#undef R + +#undef a +#undef b +#undef c +#undef d +#undef e +#undef f +#undef g +#undef h + +NAMESPACE_END + +#endif // Not CRYPTOPP_GENERATE_X64_MASM +#endif // Not CRYPTOPP_IMPORTS diff --git a/external/ours/library/crypto/src/shared/original/sha.h b/external/ours/library/crypto/src/shared/original/sha.h new file mode 100755 index 000000000..a819bd92b --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/sha1_armv4.h b/external/ours/library/crypto/src/shared/original/sha1_armv4.h new file mode 100755 index 000000000..7cdb6dab3 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/sha256_armv4.h b/external/ours/library/crypto/src/shared/original/sha256_armv4.h new file mode 100755 index 000000000..a577b5b09 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/sha3.cpp b/external/ours/library/crypto/src/shared/original/sha3.cpp new file mode 100755 index 000000000..35de1b135 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/sha3.cpp @@ -0,0 +1,71 @@ +// sha3.cpp - modified by Wei Dai from Ronny Van Keer's public domain +// Keccak-simple.c. All modifications here are placed in the +// public domain by Wei Dai. +// Keccack core function moved to keccakc.cpp in AUG 2018 +// by Jeffrey Walton. Separating the core file allows both +// SHA3 and Keccack to share the core implementation. + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michael Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by Ronny Van Keer, hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include "pch.h" +#include "sha3.h" + +NAMESPACE_BEGIN(CryptoPP) + +// The Keccak core function +extern void KeccakF1600(word64 *state); + +NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void SHA3::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT(!(input == NULLPTR && length != 0)); + if (length == 0) { return; } + + size_t spaceLeft; + while (length >= (spaceLeft = r() - m_counter)) + { + if (spaceLeft) + xorbuf(m_state.BytePtr() + m_counter, input, spaceLeft); + KeccakF1600(m_state); + input += spaceLeft; + length -= spaceLeft; + m_counter = 0; + } + + if (length) + xorbuf(m_state.BytePtr() + m_counter, input, length); + m_counter += (unsigned int)length; +} + +void SHA3::Restart() +{ + memset(m_state, 0, m_state.SizeInBytes()); + m_counter = 0; +} + +void SHA3::TruncatedFinal(byte *hash, size_t size) +{ + CRYPTOPP_ASSERT(hash != NULLPTR); + ThrowIfInvalidTruncatedSize(size); + + m_state.BytePtr()[m_counter] ^= 0x06; + m_state.BytePtr()[r()-1] ^= 0x80; + KeccakF1600(m_state); + std::memcpy(hash, m_state, size); + Restart(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/sha3.h b/external/ours/library/crypto/src/shared/original/sha3.h new file mode 100755 index 000000000..f02b7d44b --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/sha512_armv4.h b/external/ours/library/crypto/src/shared/original/sha512_armv4.h new file mode 100755 index 000000000..b914577f0 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/sha_simd.cpp b/external/ours/library/crypto/src/shared/original/sha_simd.cpp new file mode 100755 index 000000000..18bdf1923 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/sha_simd.cpp @@ -0,0 +1,1506 @@ +// sha_simd.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// +// This source file uses intrinsics to gain access to SHA-NI and +// ARMv8a SHA instructions. A separate source file is needed +// because additional CXXFLAGS are required to enable the +// appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" +#include "sha.h" +#include "misc.h" + +#if defined(CRYPTOPP_DISABLE_SHA_ASM) +# undef CRYPTOPP_X86_ASM_AVAILABLE +# undef CRYPTOPP_X32_ASM_AVAILABLE +# undef CRYPTOPP_X64_ASM_AVAILABLE +# undef CRYPTOPP_SSE2_ASM_AVAILABLE +#endif + +#if (CRYPTOPP_SHANI_AVAILABLE) +# include +# include +#endif + +// Android makes available with ARMv7-a +#if (CRYPTOPP_BOOL_ARMV8) +# if (CRYPTOPP_ARM_NEON_HEADER) +# include +# endif +# if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +# endif +#endif + +#if CRYPTOPP_POWER8_SHA_AVAILABLE +# include "ppc_simd.h" +#endif + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#ifndef EXCEPTION_EXECUTE_HANDLER +# define EXCEPTION_EXECUTE_HANDLER 1 +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char SHA_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +// ***************** SHA key tables ******************** + +extern const word32 SHA256_K[64]; +extern const word64 SHA512_K[80]; + +// ***************** SIGILL probes ******************** + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); + + static jmp_buf s_jmpSIGILL; + static void SigIllHandler(int) + { + longjmp(s_jmpSIGILL, 1); + } +} +#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY + +#if (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8) +bool CPU_ProbeSHA1() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (CRYPTOPP_ARM_SHA1_AVAILABLE) +# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) + volatile bool result = true; + __try + { + unsigned int w[] = {1,2,3,4, 5,6,7,8, 9,10,11,12}; + uint32x4_t data1 = vld1q_u32(w+0); + uint32x4_t data2 = vld1q_u32(w+4); + uint32x4_t data3 = vld1q_u32(w+8); + + uint32x4_t r1 = vsha1cq_u32 (data1, 0, data2); + uint32x4_t r2 = vsha1mq_u32 (data1, 0, data2); + uint32x4_t r3 = vsha1pq_u32 (data1, 0, data2); + uint32x4_t r4 = vsha1su0q_u32 (data1, data2, data3); + uint32x4_t r5 = vsha1su1q_u32 (data1, data2); + + result = !!(vgetq_lane_u32(r1,0) | vgetq_lane_u32(r2,1) | vgetq_lane_u32(r3,2) | vgetq_lane_u32(r4,3) | vgetq_lane_u32(r5,0)); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + return result; +# else + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + unsigned int w[] = {1,2,3,4, 5,6,7,8, 9,10,11,12}; + uint32x4_t data1 = vld1q_u32(w+0); + uint32x4_t data2 = vld1q_u32(w+4); + uint32x4_t data3 = vld1q_u32(w+8); + + uint32x4_t r1 = vsha1cq_u32 (data1, 0, data2); + uint32x4_t r2 = vsha1mq_u32 (data1, 0, data2); + uint32x4_t r3 = vsha1pq_u32 (data1, 0, data2); + uint32x4_t r4 = vsha1su0q_u32 (data1, data2, data3); + uint32x4_t r5 = vsha1su1q_u32 (data1, data2); + + result = !!(vgetq_lane_u32(r1,0) | vgetq_lane_u32(r2,1) | vgetq_lane_u32(r3,2) | vgetq_lane_u32(r4,3) | vgetq_lane_u32(r5,0)); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_ARM_SHA1_AVAILABLE +} + +bool CPU_ProbeSHA256() +{ +#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif (CRYPTOPP_ARM_SHA2_AVAILABLE) +# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) + volatile bool result = true; + __try + { + unsigned int w[] = {1,2,3,4, 5,6,7,8, 9,10,11,12}; + uint32x4_t data1 = vld1q_u32(w+0); + uint32x4_t data2 = vld1q_u32(w+4); + uint32x4_t data3 = vld1q_u32(w+8); + + uint32x4_t r1 = vsha256hq_u32 (data1, data2, data3); + uint32x4_t r2 = vsha256h2q_u32 (data1, data2, data3); + uint32x4_t r3 = vsha256su0q_u32 (data1, data2); + uint32x4_t r4 = vsha256su1q_u32 (data1, data2, data3); + + result = !!(vgetq_lane_u32(r1,0) | vgetq_lane_u32(r2,1) | vgetq_lane_u32(r3,2) | vgetq_lane_u32(r4,3)); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + return result; +#else + + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } + + if (setjmp(s_jmpSIGILL)) + result = false; + else + { + unsigned int w[] = {1,2,3,4, 5,6,7,8, 9,10,11,12}; + uint32x4_t data1 = vld1q_u32(w+0); + uint32x4_t data2 = vld1q_u32(w+4); + uint32x4_t data3 = vld1q_u32(w+8); + + uint32x4_t r1 = vsha256hq_u32 (data1, data2, data3); + uint32x4_t r2 = vsha256h2q_u32 (data1, data2, data3); + uint32x4_t r3 = vsha256su0q_u32 (data1, data2); + uint32x4_t r4 = vsha256su1q_u32 (data1, data2, data3); + + result = !!(vgetq_lane_u32(r1,0) | vgetq_lane_u32(r2,1) | vgetq_lane_u32(r3,2) | vgetq_lane_u32(r4,3)); + } + + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); + signal(SIGILL, oldHandler); + return result; +# endif +#else + return false; +#endif // CRYPTOPP_ARM_SHA2_AVAILABLE +} +#endif // ARM32 or ARM64 + +// ***************** Intel x86 SHA ******************** + +///////////////////////////////////// +// start of Walton and Gulley code // +///////////////////////////////////// + +#if CRYPTOPP_SHANI_AVAILABLE +// Based on http://software.intel.com/en-us/articles/intel-sha-extensions and code by Sean Gulley. +void SHA1_HashMultipleBlocks_SHANI(word32 *state, const word32 *data, size_t length, ByteOrder order) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + CRYPTOPP_ASSERT(length >= SHA1::BLOCKSIZE); + + __m128i ABCD, ABCD_SAVE, E0, E0_SAVE, E1; + __m128i MASK, MSG0, MSG1, MSG2, MSG3; + + // Load initial values + ABCD = _mm_loadu_si128(CONST_M128_CAST(state)); + E0 = _mm_set_epi32(state[4], 0, 0, 0); + ABCD = _mm_shuffle_epi32(ABCD, 0x1B); + + // IA-32 SHA is little endian, SHA::Transform is big endian, + // and SHA::HashMultipleBlocks can be either. ByteOrder + // allows us to avoid extra endian reversals. It saves 1.0 cpb. + MASK = order == BIG_ENDIAN_ORDER ? // Data arrangement + _mm_set_epi8(0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15) : + _mm_set_epi8(3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12) ; + + while (length >= SHA1::BLOCKSIZE) + { + // Save current hash + ABCD_SAVE = ABCD; + E0_SAVE = E0; + + // Rounds 0-3 + MSG0 = _mm_loadu_si128(CONST_M128_CAST(data+0)); + MSG0 = _mm_shuffle_epi8(MSG0, MASK); + E0 = _mm_add_epi32(E0, MSG0); + E1 = ABCD; + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 0); + + // Rounds 4-7 + MSG1 = _mm_loadu_si128(CONST_M128_CAST(data+4)); + MSG1 = _mm_shuffle_epi8(MSG1, MASK); + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 0); + MSG0 = _mm_sha1msg1_epu32(MSG0, MSG1); + + // Rounds 8-11 + MSG2 = _mm_loadu_si128(CONST_M128_CAST(data+8)); + MSG2 = _mm_shuffle_epi8(MSG2, MASK); + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 0); + MSG1 = _mm_sha1msg1_epu32(MSG1, MSG2); + MSG0 = _mm_xor_si128(MSG0, MSG2); + + // Rounds 12-15 + MSG3 = _mm_loadu_si128(CONST_M128_CAST(data+12)); + MSG3 = _mm_shuffle_epi8(MSG3, MASK); + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + MSG0 = _mm_sha1msg2_epu32(MSG0, MSG3); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 0); + MSG2 = _mm_sha1msg1_epu32(MSG2, MSG3); + MSG1 = _mm_xor_si128(MSG1, MSG3); + + // Rounds 16-19 + E0 = _mm_sha1nexte_epu32(E0, MSG0); + E1 = ABCD; + MSG1 = _mm_sha1msg2_epu32(MSG1, MSG0); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 0); + MSG3 = _mm_sha1msg1_epu32(MSG3, MSG0); + MSG2 = _mm_xor_si128(MSG2, MSG0); + + // Rounds 20-23 + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + MSG2 = _mm_sha1msg2_epu32(MSG2, MSG1); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 1); + MSG0 = _mm_sha1msg1_epu32(MSG0, MSG1); + MSG3 = _mm_xor_si128(MSG3, MSG1); + + // Rounds 24-27 + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + MSG3 = _mm_sha1msg2_epu32(MSG3, MSG2); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 1); + MSG1 = _mm_sha1msg1_epu32(MSG1, MSG2); + MSG0 = _mm_xor_si128(MSG0, MSG2); + + // Rounds 28-31 + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + MSG0 = _mm_sha1msg2_epu32(MSG0, MSG3); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 1); + MSG2 = _mm_sha1msg1_epu32(MSG2, MSG3); + MSG1 = _mm_xor_si128(MSG1, MSG3); + + // Rounds 32-35 + E0 = _mm_sha1nexte_epu32(E0, MSG0); + E1 = ABCD; + MSG1 = _mm_sha1msg2_epu32(MSG1, MSG0); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 1); + MSG3 = _mm_sha1msg1_epu32(MSG3, MSG0); + MSG2 = _mm_xor_si128(MSG2, MSG0); + + // Rounds 36-39 + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + MSG2 = _mm_sha1msg2_epu32(MSG2, MSG1); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 1); + MSG0 = _mm_sha1msg1_epu32(MSG0, MSG1); + MSG3 = _mm_xor_si128(MSG3, MSG1); + + // Rounds 40-43 + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + MSG3 = _mm_sha1msg2_epu32(MSG3, MSG2); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 2); + MSG1 = _mm_sha1msg1_epu32(MSG1, MSG2); + MSG0 = _mm_xor_si128(MSG0, MSG2); + + // Rounds 44-47 + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + MSG0 = _mm_sha1msg2_epu32(MSG0, MSG3); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 2); + MSG2 = _mm_sha1msg1_epu32(MSG2, MSG3); + MSG1 = _mm_xor_si128(MSG1, MSG3); + + // Rounds 48-51 + E0 = _mm_sha1nexte_epu32(E0, MSG0); + E1 = ABCD; + MSG1 = _mm_sha1msg2_epu32(MSG1, MSG0); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 2); + MSG3 = _mm_sha1msg1_epu32(MSG3, MSG0); + MSG2 = _mm_xor_si128(MSG2, MSG0); + + // Rounds 52-55 + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + MSG2 = _mm_sha1msg2_epu32(MSG2, MSG1); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 2); + MSG0 = _mm_sha1msg1_epu32(MSG0, MSG1); + MSG3 = _mm_xor_si128(MSG3, MSG1); + + // Rounds 56-59 + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + MSG3 = _mm_sha1msg2_epu32(MSG3, MSG2); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 2); + MSG1 = _mm_sha1msg1_epu32(MSG1, MSG2); + MSG0 = _mm_xor_si128(MSG0, MSG2); + + // Rounds 60-63 + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + MSG0 = _mm_sha1msg2_epu32(MSG0, MSG3); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 3); + MSG2 = _mm_sha1msg1_epu32(MSG2, MSG3); + MSG1 = _mm_xor_si128(MSG1, MSG3); + + // Rounds 64-67 + E0 = _mm_sha1nexte_epu32(E0, MSG0); + E1 = ABCD; + MSG1 = _mm_sha1msg2_epu32(MSG1, MSG0); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 3); + MSG3 = _mm_sha1msg1_epu32(MSG3, MSG0); + MSG2 = _mm_xor_si128(MSG2, MSG0); + + // Rounds 68-71 + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + MSG2 = _mm_sha1msg2_epu32(MSG2, MSG1); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 3); + MSG3 = _mm_xor_si128(MSG3, MSG1); + + // Rounds 72-75 + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + MSG3 = _mm_sha1msg2_epu32(MSG3, MSG2); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 3); + + // Rounds 76-79 + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 3); + + // Add values back to state + E0 = _mm_sha1nexte_epu32(E0, E0_SAVE); + ABCD = _mm_add_epi32(ABCD, ABCD_SAVE); + + data += SHA1::BLOCKSIZE/sizeof(word32); + length -= SHA1::BLOCKSIZE; + } + + // Save state + ABCD = _mm_shuffle_epi32(ABCD, 0x1B); + _mm_storeu_si128(M128_CAST(state), ABCD); + state[4] = _mm_extract_epi32(E0, 3); +} + +// Based on http://software.intel.com/en-us/articles/intel-sha-extensions and code by Sean Gulley. +void SHA256_HashMultipleBlocks_SHANI(word32 *state, const word32 *data, size_t length, ByteOrder order) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + CRYPTOPP_ASSERT(length >= SHA256::BLOCKSIZE); + + __m128i STATE0, STATE1; + __m128i MSG, TMP, MASK; + __m128i TMSG0, TMSG1, TMSG2, TMSG3; + __m128i ABEF_SAVE, CDGH_SAVE; + + // Load initial values + TMP = _mm_loadu_si128(M128_CAST(&state[0])); + STATE1 = _mm_loadu_si128(M128_CAST(&state[4])); + + // IA-32 SHA is little endian, SHA::Transform is big endian, + // and SHA::HashMultipleBlocks can be either. ByteOrder + // allows us to avoid extra endian reversals. It saves 1.0 cpb. + MASK = order == BIG_ENDIAN_ORDER ? // Data arrangement + _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3) : + _mm_set_epi8(15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0) ; + + TMP = _mm_shuffle_epi32(TMP, 0xB1); // CDAB + STATE1 = _mm_shuffle_epi32(STATE1, 0x1B); // EFGH + STATE0 = _mm_alignr_epi8(TMP, STATE1, 8); // ABEF + STATE1 = _mm_blend_epi16(STATE1, TMP, 0xF0); // CDGH + + while (length >= SHA256::BLOCKSIZE) + { + // Save current hash + ABEF_SAVE = STATE0; + CDGH_SAVE = STATE1; + + // Rounds 0-3 + MSG = _mm_loadu_si128(CONST_M128_CAST(data+0)); + TMSG0 = _mm_shuffle_epi8(MSG, MASK); + MSG = _mm_add_epi32(TMSG0, _mm_set_epi64x(W64LIT(0xE9B5DBA5B5C0FBCF), W64LIT(0x71374491428A2F98))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + // Rounds 4-7 + TMSG1 = _mm_loadu_si128(CONST_M128_CAST(data+4)); + TMSG1 = _mm_shuffle_epi8(TMSG1, MASK); + MSG = _mm_add_epi32(TMSG1, _mm_set_epi64x(W64LIT(0xAB1C5ED5923F82A4), W64LIT(0x59F111F13956C25B))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG0 = _mm_sha256msg1_epu32(TMSG0, TMSG1); + + // Rounds 8-11 + TMSG2 = _mm_loadu_si128(CONST_M128_CAST(data+8)); + TMSG2 = _mm_shuffle_epi8(TMSG2, MASK); + MSG = _mm_add_epi32(TMSG2, _mm_set_epi64x(W64LIT(0x550C7DC3243185BE), W64LIT(0x12835B01D807AA98))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG1 = _mm_sha256msg1_epu32(TMSG1, TMSG2); + + // Rounds 12-15 + TMSG3 = _mm_loadu_si128(CONST_M128_CAST(data+12)); + TMSG3 = _mm_shuffle_epi8(TMSG3, MASK); + MSG = _mm_add_epi32(TMSG3, _mm_set_epi64x(W64LIT(0xC19BF1749BDC06A7), W64LIT(0x80DEB1FE72BE5D74))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG3, TMSG2, 4); + TMSG0 = _mm_add_epi32(TMSG0, TMP); + TMSG0 = _mm_sha256msg2_epu32(TMSG0, TMSG3); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG2 = _mm_sha256msg1_epu32(TMSG2, TMSG3); + + // Rounds 16-19 + MSG = _mm_add_epi32(TMSG0, _mm_set_epi64x(W64LIT(0x240CA1CC0FC19DC6), W64LIT(0xEFBE4786E49B69C1))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG0, TMSG3, 4); + TMSG1 = _mm_add_epi32(TMSG1, TMP); + TMSG1 = _mm_sha256msg2_epu32(TMSG1, TMSG0); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG3 = _mm_sha256msg1_epu32(TMSG3, TMSG0); + + // Rounds 20-23 + MSG = _mm_add_epi32(TMSG1, _mm_set_epi64x(W64LIT(0x76F988DA5CB0A9DC), W64LIT(0x4A7484AA2DE92C6F))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG1, TMSG0, 4); + TMSG2 = _mm_add_epi32(TMSG2, TMP); + TMSG2 = _mm_sha256msg2_epu32(TMSG2, TMSG1); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG0 = _mm_sha256msg1_epu32(TMSG0, TMSG1); + + // Rounds 24-27 + MSG = _mm_add_epi32(TMSG2, _mm_set_epi64x(W64LIT(0xBF597FC7B00327C8), W64LIT(0xA831C66D983E5152))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG2, TMSG1, 4); + TMSG3 = _mm_add_epi32(TMSG3, TMP); + TMSG3 = _mm_sha256msg2_epu32(TMSG3, TMSG2); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG1 = _mm_sha256msg1_epu32(TMSG1, TMSG2); + + // Rounds 28-31 + MSG = _mm_add_epi32(TMSG3, _mm_set_epi64x(W64LIT(0x1429296706CA6351), W64LIT(0xD5A79147C6E00BF3))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG3, TMSG2, 4); + TMSG0 = _mm_add_epi32(TMSG0, TMP); + TMSG0 = _mm_sha256msg2_epu32(TMSG0, TMSG3); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG2 = _mm_sha256msg1_epu32(TMSG2, TMSG3); + + // Rounds 32-35 + MSG = _mm_add_epi32(TMSG0, _mm_set_epi64x(W64LIT(0x53380D134D2C6DFC), W64LIT(0x2E1B213827B70A85))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG0, TMSG3, 4); + TMSG1 = _mm_add_epi32(TMSG1, TMP); + TMSG1 = _mm_sha256msg2_epu32(TMSG1, TMSG0); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG3 = _mm_sha256msg1_epu32(TMSG3, TMSG0); + + // Rounds 36-39 + MSG = _mm_add_epi32(TMSG1, _mm_set_epi64x(W64LIT(0x92722C8581C2C92E), W64LIT(0x766A0ABB650A7354))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG1, TMSG0, 4); + TMSG2 = _mm_add_epi32(TMSG2, TMP); + TMSG2 = _mm_sha256msg2_epu32(TMSG2, TMSG1); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG0 = _mm_sha256msg1_epu32(TMSG0, TMSG1); + + // Rounds 40-43 + MSG = _mm_add_epi32(TMSG2, _mm_set_epi64x(W64LIT(0xC76C51A3C24B8B70), W64LIT(0xA81A664BA2BFE8A1))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG2, TMSG1, 4); + TMSG3 = _mm_add_epi32(TMSG3, TMP); + TMSG3 = _mm_sha256msg2_epu32(TMSG3, TMSG2); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG1 = _mm_sha256msg1_epu32(TMSG1, TMSG2); + + // Rounds 44-47 + MSG = _mm_add_epi32(TMSG3, _mm_set_epi64x(W64LIT(0x106AA070F40E3585), W64LIT(0xD6990624D192E819))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG3, TMSG2, 4); + TMSG0 = _mm_add_epi32(TMSG0, TMP); + TMSG0 = _mm_sha256msg2_epu32(TMSG0, TMSG3); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG2 = _mm_sha256msg1_epu32(TMSG2, TMSG3); + + // Rounds 48-51 + MSG = _mm_add_epi32(TMSG0, _mm_set_epi64x(W64LIT(0x34B0BCB52748774C), W64LIT(0x1E376C0819A4C116))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG0, TMSG3, 4); + TMSG1 = _mm_add_epi32(TMSG1, TMP); + TMSG1 = _mm_sha256msg2_epu32(TMSG1, TMSG0); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + TMSG3 = _mm_sha256msg1_epu32(TMSG3, TMSG0); + + // Rounds 52-55 + MSG = _mm_add_epi32(TMSG1, _mm_set_epi64x(W64LIT(0x682E6FF35B9CCA4F), W64LIT(0x4ED8AA4A391C0CB3))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG1, TMSG0, 4); + TMSG2 = _mm_add_epi32(TMSG2, TMP); + TMSG2 = _mm_sha256msg2_epu32(TMSG2, TMSG1); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + // Rounds 56-59 + MSG = _mm_add_epi32(TMSG2, _mm_set_epi64x(W64LIT(0x8CC7020884C87814), W64LIT(0x78A5636F748F82EE))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(TMSG2, TMSG1, 4); + TMSG3 = _mm_add_epi32(TMSG3, TMP); + TMSG3 = _mm_sha256msg2_epu32(TMSG3, TMSG2); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + // Rounds 60-63 + MSG = _mm_add_epi32(TMSG3, _mm_set_epi64x(W64LIT(0xC67178F2BEF9A3F7), W64LIT(0xA4506CEB90BEFFFA))); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + // Add values back to state + STATE0 = _mm_add_epi32(STATE0, ABEF_SAVE); + STATE1 = _mm_add_epi32(STATE1, CDGH_SAVE); + + data += SHA256::BLOCKSIZE/sizeof(word32); + length -= SHA256::BLOCKSIZE; + } + + TMP = _mm_shuffle_epi32(STATE0, 0x1B); // FEBA + STATE1 = _mm_shuffle_epi32(STATE1, 0xB1); // DCHG + STATE0 = _mm_blend_epi16(TMP, STATE1, 0xF0); // DCBA + STATE1 = _mm_alignr_epi8(STATE1, TMP, 8); // ABEF + + // Save state + _mm_storeu_si128(M128_CAST(&state[0]), STATE0); + _mm_storeu_si128(M128_CAST(&state[4]), STATE1); +} +#endif // CRYPTOPP_SHANI_AVAILABLE + +/////////////////////////////////// +// end of Walton and Gulley code // +/////////////////////////////////// + +// ***************** ARMV8 SHA ******************** + +///////////////////////////////////////////////////////////// +// start of Walton, Schneiders, O'Rourke and Hovsmith code // +///////////////////////////////////////////////////////////// + +#if CRYPTOPP_ARM_SHA1_AVAILABLE +void SHA1_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + CRYPTOPP_ASSERT(length >= SHA1::BLOCKSIZE); + + uint32x4_t C0, C1, C2, C3; + uint32x4_t ABCD, ABCD_SAVED; + uint32x4_t MSG0, MSG1, MSG2, MSG3; + uint32x4_t TMP0, TMP1; + uint32_t E0, E0_SAVED, E1; + + // Load initial values + C0 = vdupq_n_u32(0x5A827999); + C1 = vdupq_n_u32(0x6ED9EBA1); + C2 = vdupq_n_u32(0x8F1BBCDC); + C3 = vdupq_n_u32(0xCA62C1D6); + + ABCD = vld1q_u32(&state[0]); + E0 = state[4]; + + while (length >= SHA1::BLOCKSIZE) + { + // Save current hash + ABCD_SAVED = ABCD; + E0_SAVED = E0; + + MSG0 = vld1q_u32(data + 0); + MSG1 = vld1q_u32(data + 4); + MSG2 = vld1q_u32(data + 8); + MSG3 = vld1q_u32(data + 12); + + if (order == BIG_ENDIAN_ORDER) // Data arrangement + { + MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG0))); + MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG1))); + MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG2))); + MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG3))); + } + + TMP0 = vaddq_u32(MSG0, C0); + TMP1 = vaddq_u32(MSG1, C0); + + // Rounds 0-3 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, C0); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + // Rounds 4-7 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, C0); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3); + + // Rounds 8-11 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG0, C0); + MSG1 = vsha1su1q_u32(MSG1, MSG0); + MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0); + + // Rounds 12-15 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG1, C1); + MSG2 = vsha1su1q_u32(MSG2, MSG1); + MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1); + + // Rounds 16-19 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, C1); + MSG3 = vsha1su1q_u32(MSG3, MSG2); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + // Rounds 20-23 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, C1); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3); + + // Rounds 24-27 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG0, C1); + MSG1 = vsha1su1q_u32(MSG1, MSG0); + MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0); + + // Rounds 28-31 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG1, C1); + MSG2 = vsha1su1q_u32(MSG2, MSG1); + MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1); + + // Rounds 32-35 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, C2); + MSG3 = vsha1su1q_u32(MSG3, MSG2); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + // Rounds 36-39 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, C2); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3); + + // Rounds 40-43 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG0, C2); + MSG1 = vsha1su1q_u32(MSG1, MSG0); + MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0); + + // Rounds 44-47 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG1, C2); + MSG2 = vsha1su1q_u32(MSG2, MSG1); + MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1); + + // Rounds 48-51 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, C2); + MSG3 = vsha1su1q_u32(MSG3, MSG2); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + // Rounds 52-55 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, C3); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3); + + // Rounds 56-59 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG0, C3); + MSG1 = vsha1su1q_u32(MSG1, MSG0); + MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0); + + // Rounds 60-63 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG1, C3); + MSG2 = vsha1su1q_u32(MSG2, MSG1); + MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1); + + // Rounds 64-67 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, C3); + MSG3 = vsha1su1q_u32(MSG3, MSG2); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + // Rounds 68-71 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, C3); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + + // Rounds 72-75 + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E0, TMP0); + + // Rounds 76-79 + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + + E0 += E0_SAVED; + ABCD = vaddq_u32(ABCD_SAVED, ABCD); + + data += SHA1::BLOCKSIZE/sizeof(word32); + length -= SHA1::BLOCKSIZE; + } + + // Save state + vst1q_u32(&state[0], ABCD); + state[4] = E0; +} +#endif // CRYPTOPP_ARM_SHA1_AVAILABLE + +#if CRYPTOPP_ARM_SHA2_AVAILABLE +void SHA256_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + CRYPTOPP_ASSERT(length >= SHA256::BLOCKSIZE); + + uint32x4_t STATE0, STATE1, ABEF_SAVE, CDGH_SAVE; + uint32x4_t MSG0, MSG1, MSG2, MSG3; + uint32x4_t TMP0, TMP1, TMP2; + + // Load initial values + STATE0 = vld1q_u32(&state[0]); + STATE1 = vld1q_u32(&state[4]); + + while (length >= SHA256::BLOCKSIZE) + { + // Save current hash + ABEF_SAVE = STATE0; + CDGH_SAVE = STATE1; + + // Load message + MSG0 = vld1q_u32(data + 0); + MSG1 = vld1q_u32(data + 4); + MSG2 = vld1q_u32(data + 8); + MSG3 = vld1q_u32(data + 12); + + if (order == BIG_ENDIAN_ORDER) // Data arrangement + { + MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG0))); + MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG1))); + MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG2))); + MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG3))); + } + + TMP0 = vaddq_u32(MSG0, vld1q_u32(&SHA256_K[0x00])); + + // Rounds 0-3 + MSG0 = vsha256su0q_u32(MSG0, MSG1); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG1, vld1q_u32(&SHA256_K[0x04])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); + + // Rounds 4-7 + MSG1 = vsha256su0q_u32(MSG1, MSG2); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG2, vld1q_u32(&SHA256_K[0x08])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); + + // Rounds 8-11 + MSG2 = vsha256su0q_u32(MSG2, MSG3); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG3, vld1q_u32(&SHA256_K[0x0c])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); + + // Rounds 12-15 + MSG3 = vsha256su0q_u32(MSG3, MSG0); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG0, vld1q_u32(&SHA256_K[0x10])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); + + // Rounds 16-19 + MSG0 = vsha256su0q_u32(MSG0, MSG1); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG1, vld1q_u32(&SHA256_K[0x14])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); + + // Rounds 20-23 + MSG1 = vsha256su0q_u32(MSG1, MSG2); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG2, vld1q_u32(&SHA256_K[0x18])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); + + // Rounds 24-27 + MSG2 = vsha256su0q_u32(MSG2, MSG3); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG3, vld1q_u32(&SHA256_K[0x1c])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); + + // Rounds 28-31 + MSG3 = vsha256su0q_u32(MSG3, MSG0); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG0, vld1q_u32(&SHA256_K[0x20])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); + + // Rounds 32-35 + MSG0 = vsha256su0q_u32(MSG0, MSG1); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG1, vld1q_u32(&SHA256_K[0x24])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); + + // Rounds 36-39 + MSG1 = vsha256su0q_u32(MSG1, MSG2); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG2, vld1q_u32(&SHA256_K[0x28])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); + + // Rounds 40-43 + MSG2 = vsha256su0q_u32(MSG2, MSG3); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG3, vld1q_u32(&SHA256_K[0x2c])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); + + // Rounds 44-47 + MSG3 = vsha256su0q_u32(MSG3, MSG0); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG0, vld1q_u32(&SHA256_K[0x30])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); + + // Rounds 48-51 + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG1, vld1q_u32(&SHA256_K[0x34])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + + // Rounds 52-55 + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG2, vld1q_u32(&SHA256_K[0x38])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + + // Rounds 56-59 + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG3, vld1q_u32(&SHA256_K[0x3c])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + + // Rounds 60-63 + TMP2 = STATE0; + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + + // Add back to state + STATE0 = vaddq_u32(STATE0, ABEF_SAVE); + STATE1 = vaddq_u32(STATE1, CDGH_SAVE); + + data += SHA256::BLOCKSIZE/sizeof(word32); + length -= SHA256::BLOCKSIZE; + } + + // Save state + vst1q_u32(&state[0], STATE0); + vst1q_u32(&state[4], STATE1); +} +#endif // CRYPTOPP_ARM_SHA2_AVAILABLE + +/////////////////////////////////////////////////////////// +// end of Walton, Schneiders, O'Rourke and Hovsmith code // +/////////////////////////////////////////////////////////// + +// ***************** Power8 SHA ******************** + +////////////////////////////////////////////////// +// start Gustavo, Serra, Scalet and Walton code // +////////////////////////////////////////////////// + +#if CRYPTOPP_POWER8_SHA_AVAILABLE + +// Indexes into the S[] array +enum {A=0, B=1, C, D, E, F, G, H}; + +inline +uint32x4_p VecLoad32(const word32* data, int offset) +{ +#if (CRYPTOPP_LITTLE_ENDIAN) + const uint8x16_p mask = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12}; + const uint32x4_p val = VecLoad(offset, data); + return (uint32x4_p)VecPermute(val, val, mask); +#else + return VecLoad(offset, data); +#endif +} + +template inline +void VecStore32(const T data, word32 dest[4]) +{ + VecStore(data, dest); +} + +inline +uint32x4_p VectorCh(const uint32x4_p x, const uint32x4_p y, const uint32x4_p z) +{ + // The trick below is due to Andy Polyakov and Jack Lloyd + return vec_sel(z,y,x); +} + +inline +uint32x4_p VectorMaj(const uint32x4_p x, const uint32x4_p y, const uint32x4_p z) +{ + // The trick below is due to Andy Polyakov and Jack Lloyd + return vec_sel(y, z, VecXor(x, y)); +} + +inline +uint32x4_p Vector_sigma0(const uint32x4_p val) +{ + return VecSHA256<0,0>(val); +} + +inline +uint32x4_p Vector_sigma1(const uint32x4_p val) +{ + return VecSHA256<0,0xf>(val); +} + +inline +uint32x4_p VectorSigma0(const uint32x4_p val) +{ + return VecSHA256<1,0>(val); +} + +inline +uint32x4_p VectorSigma1(const uint32x4_p val) +{ + return VecSHA256<1,0xf>(val); +} + +inline +uint32x4_p VectorPack(const uint32x4_p a, const uint32x4_p b, + const uint32x4_p c, const uint32x4_p d) +{ + const uint8x16_p m1 = {0,1,2,3, 16,17,18,19, 0,0,0,0, 0,0,0,0}; + const uint8x16_p m2 = {0,1,2,3, 4,5,6,7, 16,17,18,19, 20,21,22,23}; + return VecPermute(VecPermute(a,b,m1), VecPermute(c,d,m1), m2); +} + +template inline +void SHA256_ROUND1(uint32x4_p W[16], uint32x4_p S[8], const uint32x4_p K, const uint32x4_p M) +{ + uint32x4_p T1, T2; + + W[R] = M; + T1 = S[H] + VectorSigma1(S[E]) + VectorCh(S[E],S[F],S[G]) + K + M; + T2 = VectorSigma0(S[A]) + VectorMaj(S[A],S[B],S[C]); + + S[H] = S[G]; S[G] = S[F]; S[F] = S[E]; + S[E] = S[D] + T1; + S[D] = S[C]; S[C] = S[B]; S[B] = S[A]; + S[A] = T1 + T2; +} + +template inline +void SHA256_ROUND2(uint32x4_p W[16], uint32x4_p S[8], const uint32x4_p K) +{ + // Indexes into the W[] array + enum {IDX0=(R+0)&0xf, IDX1=(R+1)&0xf, IDX9=(R+9)&0xf, IDX14=(R+14)&0xf}; + + const uint32x4_p s0 = Vector_sigma0(W[IDX1]); + const uint32x4_p s1 = Vector_sigma1(W[IDX14]); + + uint32x4_p T1 = (W[IDX0] += s0 + s1 + W[IDX9]); + T1 += S[H] + VectorSigma1(S[E]) + VectorCh(S[E],S[F],S[G]) + K; + uint32x4_p T2 = VectorSigma0(S[A]) + VectorMaj(S[A],S[B],S[C]); + + S[H] = S[G]; S[G] = S[F]; S[F] = S[E]; + S[E] = S[D] + T1; + S[D] = S[C]; S[C] = S[B]; S[B] = S[A]; + S[A] = T1 + T2; +} + +void SHA256_HashMultipleBlocks_POWER8(word32 *state, const word32 *data, size_t length, ByteOrder order) +{ + CRYPTOPP_ASSERT(state); CRYPTOPP_ASSERT(data); + CRYPTOPP_ASSERT(length >= SHA256::BLOCKSIZE); + CRYPTOPP_UNUSED(order); + + const uint32_t* k = reinterpret_cast(SHA256_K); + const uint32_t* m = reinterpret_cast(data); + + uint32x4_p abcd = VecLoad(state+0); + uint32x4_p efgh = VecLoad(state+4); + uint32x4_p W[16], S[8], vm, vk; + + size_t blocks = length / SHA256::BLOCKSIZE; + while (blocks--) + { + unsigned int offset=0; + + S[A] = abcd; S[E] = efgh; + S[B] = VecShiftLeftOctet<4>(S[A]); + S[F] = VecShiftLeftOctet<4>(S[E]); + S[C] = VecShiftLeftOctet<4>(S[B]); + S[G] = VecShiftLeftOctet<4>(S[F]); + S[D] = VecShiftLeftOctet<4>(S[C]); + S[H] = VecShiftLeftOctet<4>(S[G]); + + // Rounds 0-16 + vk = VecLoad(offset, k); + vm = VecLoad32(m, offset); + SHA256_ROUND1<0>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<1>(W,S, vk,vm); + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<2>(W,S, vk,vm); + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<3>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad32(m, offset); + SHA256_ROUND1<4>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<5>(W,S, vk,vm); + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<6>(W,S, vk,vm); + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<7>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad32(m, offset); + SHA256_ROUND1<8>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<9>(W,S, vk,vm); + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<10>(W,S, vk,vm); + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<11>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad32(m, offset); + SHA256_ROUND1<12>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<13>(W,S, vk,vm); + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<14>(W,S, vk,vm); + + vk = VecShiftLeftOctet<4>(vk); + vm = VecShiftLeftOctet<4>(vm); + SHA256_ROUND1<15>(W,S, vk,vm); + + m += 16; // 32-bit words, not bytes + + // Rounds 16-64 + for (unsigned int i=16; i<64; i+=16) + { + vk = VecLoad(offset, k); + SHA256_ROUND2<0>(W,S, vk); + SHA256_ROUND2<1>(W,S, VecShiftLeftOctet<4>(vk)); + SHA256_ROUND2<2>(W,S, VecShiftLeftOctet<8>(vk)); + SHA256_ROUND2<3>(W,S, VecShiftLeftOctet<12>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA256_ROUND2<4>(W,S, vk); + SHA256_ROUND2<5>(W,S, VecShiftLeftOctet<4>(vk)); + SHA256_ROUND2<6>(W,S, VecShiftLeftOctet<8>(vk)); + SHA256_ROUND2<7>(W,S, VecShiftLeftOctet<12>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA256_ROUND2<8>(W,S, vk); + SHA256_ROUND2<9>(W,S, VecShiftLeftOctet<4>(vk)); + SHA256_ROUND2<10>(W,S, VecShiftLeftOctet<8>(vk)); + SHA256_ROUND2<11>(W,S, VecShiftLeftOctet<12>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA256_ROUND2<12>(W,S, vk); + SHA256_ROUND2<13>(W,S, VecShiftLeftOctet<4>(vk)); + SHA256_ROUND2<14>(W,S, VecShiftLeftOctet<8>(vk)); + SHA256_ROUND2<15>(W,S, VecShiftLeftOctet<12>(vk)); + offset+=16; + } + + abcd += VectorPack(S[A],S[B],S[C],S[D]); + efgh += VectorPack(S[E],S[F],S[G],S[H]); + } + + VecStore32(abcd, state+0); + VecStore32(efgh, state+4); +} + +inline +void VecStore64(const uint64x2_p val, word64* data) +{ + VecStore(val, data); +} + +inline +uint64x2_p VecLoad64(const word64* data, int offset) +{ +#if (CRYPTOPP_LITTLE_ENDIAN) + const uint8x16_p mask = {0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15}; + return VecPermute(VecLoad(offset, data), mask); +#else + return VecLoad(offset, data); +#endif +} + +inline +uint64x2_p VectorCh(const uint64x2_p x, const uint64x2_p y, const uint64x2_p z) +{ + // The trick below is due to Andy Polyakov and Jack Lloyd + return vec_sel(z,y,x); +} + +inline +uint64x2_p VectorMaj(const uint64x2_p x, const uint64x2_p y, const uint64x2_p z) +{ + // The trick below is due to Andy Polyakov and Jack Lloyd + return vec_sel(y, z, VecXor(x, y)); +} + +inline +uint64x2_p Vector_sigma0(const uint64x2_p val) +{ + return VecSHA512<0,0>(val); +} + +inline +uint64x2_p Vector_sigma1(const uint64x2_p val) +{ + return VecSHA512<0,0xf>(val); +} + +inline +uint64x2_p VectorSigma0(const uint64x2_p val) +{ + return VecSHA512<1,0>(val); +} + +inline +uint64x2_p VectorSigma1(const uint64x2_p val) +{ + return VecSHA512<1,0xf>(val); +} + +inline +uint64x2_p VectorPack(const uint64x2_p x, const uint64x2_p y) +{ + const uint8x16_p m = {0,1,2,3, 4,5,6,7, 16,17,18,19, 20,21,22,23}; + return VecPermute(x,y,m); +} + +template inline +void SHA512_ROUND1(uint64x2_p W[16], uint64x2_p S[8], const uint64x2_p K, const uint64x2_p M) +{ + uint64x2_p T1, T2; + + W[R] = M; + T1 = S[H] + VectorSigma1(S[E]) + VectorCh(S[E],S[F],S[G]) + K + M; + T2 = VectorSigma0(S[A]) + VectorMaj(S[A],S[B],S[C]); + + S[H] = S[G]; S[G] = S[F]; S[F] = S[E]; + S[E] = S[D] + T1; + S[D] = S[C]; S[C] = S[B]; S[B] = S[A]; + S[A] = T1 + T2; +} + +template inline +void SHA512_ROUND2(uint64x2_p W[16], uint64x2_p S[8], const uint64x2_p K) +{ + // Indexes into the W[] array + enum {IDX0=(R+0)&0xf, IDX1=(R+1)&0xf, IDX9=(R+9)&0xf, IDX14=(R+14)&0xf}; + + const uint64x2_p s0 = Vector_sigma0(W[IDX1]); + const uint64x2_p s1 = Vector_sigma1(W[IDX14]); + + uint64x2_p T1 = (W[IDX0] += s0 + s1 + W[IDX9]); + T1 += S[H] + VectorSigma1(S[E]) + VectorCh(S[E],S[F],S[G]) + K; + uint64x2_p T2 = VectorSigma0(S[A]) + VectorMaj(S[A],S[B],S[C]); + + S[H] = S[G]; S[G] = S[F]; S[F] = S[E]; + S[E] = S[D] + T1; + S[D] = S[C]; S[C] = S[B]; S[B] = S[A]; + S[A] = T1 + T2; +} + +void SHA512_HashMultipleBlocks_POWER8(word64 *state, const word64 *data, size_t length, ByteOrder order) +{ + CRYPTOPP_ASSERT(state); CRYPTOPP_ASSERT(data); + CRYPTOPP_ASSERT(length >= SHA512::BLOCKSIZE); + CRYPTOPP_UNUSED(order); + + const uint64_t* k = reinterpret_cast(SHA512_K); + const uint64_t* m = reinterpret_cast(data); + + uint64x2_p ab = VecLoad(state+0); + uint64x2_p cd = VecLoad(state+2); + uint64x2_p ef = VecLoad(state+4); + uint64x2_p gh = VecLoad(state+6); + uint64x2_p W[16], S[8], vm, vk; + + size_t blocks = length / SHA512::BLOCKSIZE; + while (blocks--) + { + unsigned int offset=0; + + S[A] = ab; S[C] = cd; + S[E] = ef; S[G] = gh; + S[B] = VecShiftLeftOctet<8>(S[A]); + S[D] = VecShiftLeftOctet<8>(S[C]); + S[F] = VecShiftLeftOctet<8>(S[E]); + S[H] = VecShiftLeftOctet<8>(S[G]); + + // Rounds 0-16 + vk = VecLoad(offset, k); + vm = VecLoad64(m, offset); + SHA512_ROUND1<0>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<8>(vk); + vm = VecShiftLeftOctet<8>(vm); + SHA512_ROUND1<1>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad64(m, offset); + SHA512_ROUND1<2>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<8>(vk); + vm = VecShiftLeftOctet<8>(vm); + SHA512_ROUND1<3>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad64(m, offset); + SHA512_ROUND1<4>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<8>(vk); + vm = VecShiftLeftOctet<8>(vm); + SHA512_ROUND1<5>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad64(m, offset); + SHA512_ROUND1<6>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<8>(vk); + vm = VecShiftLeftOctet<8>(vm); + SHA512_ROUND1<7>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad64(m, offset); + SHA512_ROUND1<8>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<8>(vk); + vm = VecShiftLeftOctet<8>(vm); + SHA512_ROUND1<9>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad64(m, offset); + SHA512_ROUND1<10>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<8>(vk); + vm = VecShiftLeftOctet<8>(vm); + SHA512_ROUND1<11>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad64(m, offset); + SHA512_ROUND1<12>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<8>(vk); + vm = VecShiftLeftOctet<8>(vm); + SHA512_ROUND1<13>(W,S, vk,vm); + + vk = VecLoad(offset, k); + vm = VecLoad64(m, offset); + SHA512_ROUND1<14>(W,S, vk,vm); + offset+=16; + + vk = VecShiftLeftOctet<8>(vk); + vm = VecShiftLeftOctet<8>(vm); + SHA512_ROUND1<15>(W,S, vk,vm); + + m += 16; // 64-bit words, not bytes + + // Rounds 16-80 + for (unsigned int i=16; i<80; i+=16) + { + vk = VecLoad(offset, k); + SHA512_ROUND2<0>(W,S, vk); + SHA512_ROUND2<1>(W,S, VecShiftLeftOctet<8>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA512_ROUND2<2>(W,S, vk); + SHA512_ROUND2<3>(W,S, VecShiftLeftOctet<8>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA512_ROUND2<4>(W,S, vk); + SHA512_ROUND2<5>(W,S, VecShiftLeftOctet<8>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA512_ROUND2<6>(W,S, vk); + SHA512_ROUND2<7>(W,S, VecShiftLeftOctet<8>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA512_ROUND2<8>(W,S, vk); + SHA512_ROUND2<9>(W,S, VecShiftLeftOctet<8>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA512_ROUND2<10>(W,S, vk); + SHA512_ROUND2<11>(W,S, VecShiftLeftOctet<8>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA512_ROUND2<12>(W,S, vk); + SHA512_ROUND2<13>(W,S, VecShiftLeftOctet<8>(vk)); + offset+=16; + + vk = VecLoad(offset, k); + SHA512_ROUND2<14>(W,S, vk); + SHA512_ROUND2<15>(W,S, VecShiftLeftOctet<8>(vk)); + offset+=16; + } + + ab += VectorPack(S[A],S[B]); + cd += VectorPack(S[C],S[D]); + ef += VectorPack(S[E],S[F]); + gh += VectorPack(S[G],S[H]); + } + + VecStore64(ab, state+0); + VecStore64(cd, state+2); + VecStore64(ef, state+4); + VecStore64(gh, state+6); +} + +#endif // CRYPTOPP_POWER8_SHA_AVAILABLE + +//////////////////////////////////////////////// +// end Gustavo, Serra, Scalet and Walton code // +//////////////////////////////////////////////// + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/shacal2.cpp b/external/ours/library/crypto/src/shared/original/shacal2.cpp new file mode 100755 index 000000000..37ba9899f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/shacal2.cpp @@ -0,0 +1,172 @@ +// shacal2.cpp - written by Kevin Springle, 2003 +// +// Portions of this code were derived from +// Wei Dai's implementation of SHA-2 +// +// Jack Lloyd and the Botan team allowed Crypto++ to use parts of +// Botan's implementation under the same license as Crypto++ +// is released. The code for SHACAL2_Enc_ProcessAndXorBlock_SHANI +// below is Botan's x86_encrypt_blocks with minor tweaks. Many thanks +// to the Botan team. Also see http://github.com/randombit/botan/. +// +// The original code and all modifications are in the public domain. + +#include "pch.h" +#include "config.h" +#include "shacal2.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +// SHACAL-2 function and round definitions + +#define S0(x) (rotrConstant<2>(x)^rotrConstant<13>(x)^rotrConstant<22>(x)) +#define S1(x) (rotrConstant<6>(x)^rotrConstant<11>(x)^rotrConstant<25>(x)) +#define s0(x) (rotrConstant<7>(x)^rotrConstant<18>(x)^(x>>3)) +#define s1(x) (rotrConstant<17>(x)^rotrConstant<19>(x)^(x>>10)) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + +/* R is the SHA-256 round function. */ +/* This macro increments the k argument as a side effect. */ +#define R(a,b,c,d,e,f,g,h,k) \ + h+=S1(e)+Ch(e,f,g)+*k++;d+=h;h+=S0(a)+Maj(a,b,c); + +/* P is the inverse of the SHA-256 round function. */ +/* This macro decrements the k argument as a side effect. */ +#define P(a,b,c,d,e,f,g,h,k) \ + h-=S0(a)+Maj(a,b,c);d-=h;h-=S1(e)+Ch(e,f,g)+*--k; + +#if CRYPTOPP_SHANI_AVAILABLE +extern void SHACAL2_Enc_ProcessAndXorBlock_SHANI(const word32* subKeys, + const byte *inBlock, const byte *xorBlock, byte *outBlock); +#endif + +std::string SHACAL2::Base::AlgorithmProvider() const +{ +#if CRYPTOPP_SHANI_AVAILABLE + if (HasSHA()) + return "SHANI"; +#endif + return "C++"; +} + +void SHACAL2::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &) +{ + AssertValidKeyLength(keylen); + + word32 *rk = m_key; + unsigned int i; + + // 32-bit GCC 5.4 hack... m_key.size() returns 0. Note: this surfaced after changing + // m_key to FixedSizeAlignedSecBlock at commit 1ab1e08ac5b5a0d63374de0c. + GetUserKey(BIG_ENDIAN_ORDER, rk, 64, userKey, keylen); + for (i = 0; i < 48; i++, rk++) + { + rk[16] = rk[0] + s0(rk[1]) + rk[9] + s1(rk[14]); + rk[0] += K[i]; + } + for (i = 48; i < 64; i++, rk++) + { + rk[0] += K[i]; + } +} + +typedef BlockGetAndPut Block; + +void SHACAL2::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ +#if CRYPTOPP_SHANI_AVAILABLE + if (HasSHA()) + { + SHACAL2_Enc_ProcessAndXorBlock_SHANI(m_key, inBlock, xorBlock, outBlock); + return; + } +#endif + + word32 a, b, c, d, e, f, g, h; + const word32 *rk = m_key; + + /* + * map byte array block to cipher state: + */ + Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h); + + // Perform SHA-256 transformation. + + /* 64 operations, partially loop unrolled */ + for (unsigned int j=0; j<64; j+=8) + { + R(a,b,c,d,e,f,g,h,rk); + R(h,a,b,c,d,e,f,g,rk); + R(g,h,a,b,c,d,e,f,rk); + R(f,g,h,a,b,c,d,e,rk); + R(e,f,g,h,a,b,c,d,rk); + R(d,e,f,g,h,a,b,c,rk); + R(c,d,e,f,g,h,a,b,rk); + R(b,c,d,e,f,g,h,a,rk); + } + + /* + * map cipher state to byte array block: + */ + + Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h); +} + +void SHACAL2::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 a, b, c, d, e, f, g, h; + const word32 *rk = m_key + 64; + + /* + * map byte array block to cipher state: + */ + Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h); + + // Perform inverse SHA-256 transformation. + + /* 64 operations, partially loop unrolled */ + for (unsigned int j=0; j<64; j+=8) + { + P(b,c,d,e,f,g,h,a,rk); + P(c,d,e,f,g,h,a,b,rk); + P(d,e,f,g,h,a,b,c,rk); + P(e,f,g,h,a,b,c,d,rk); + P(f,g,h,a,b,c,d,e,rk); + P(g,h,a,b,c,d,e,f,rk); + P(h,a,b,c,d,e,f,g,rk); + P(a,b,c,d,e,f,g,h,rk); + } + + /* + * map cipher state to byte array block: + */ + + Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h); +} + +// The SHACAL-2 round constants are identical to the SHA-256 round constants. +const word32 SHACAL2::Base::K[64] = +{ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/shacal2.h b/external/ours/library/crypto/src/shared/original/shacal2.h new file mode 100755 index 000000000..ca0c482ce --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/shacal2_simd.cpp b/external/ours/library/crypto/src/shared/original/shacal2_simd.cpp new file mode 100755 index 000000000..5114601b7 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/shacal2_simd.cpp @@ -0,0 +1,94 @@ +// shacla2_simd.cpp - written and placed in the public domain by +// Jeffrey Walton and Jack Lloyd +// +// Jack Lloyd and the Botan team allowed Crypto++ to use parts of +// Botan's implementation under the same license as Crypto++ +// is released. The code for SHACAL2_Enc_ProcessAndXorBlock_SHANI +// below is Botan's x86_encrypt_blocks with minor tweaks. Many thanks +// to the Botan team. Also see http://github.com/randombit/botan/. +// +// This source file uses intrinsics to gain access to SHA-NI and +// ARMv8a SHA instructions. A separate source file is needed because +// additional CXXFLAGS are required to enable the appropriate instruction +// sets in some build configurations. + +#include "pch.h" +#include "config.h" +#include "sha.h" +#include "misc.h" + +#if (CRYPTOPP_SHANI_AVAILABLE) +# include +# include +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char SHACAL2_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +#if CRYPTOPP_SHANI_AVAILABLE +void SHACAL2_Enc_ProcessAndXorBlock_SHANI(const word32* subKeys, const byte *inBlock, const byte *xorBlock, byte *outBlock) +{ + CRYPTOPP_ASSERT(subKeys); + CRYPTOPP_ASSERT(inBlock); + CRYPTOPP_ASSERT(outBlock); + + const __m128i MASK1 = _mm_set_epi8(8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7); + const __m128i MASK2 = _mm_set_epi8(0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15); + + __m128i B0 = _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(inBlock + 0)), MASK1); + __m128i B1 = _mm_shuffle_epi8(_mm_loadu_si128(CONST_M128_CAST(inBlock + 16)), MASK2); + + __m128i TMP = _mm_alignr_epi8(B0, B1, 8); + B1 = _mm_blend_epi16(B1, B0, 0xF0); + B0 = TMP; + +#if 0 + // SSE2 + SSSE3, but 0.2 cpb slower on a Celeraon J3455 + const __m128i MASK1 = _mm_set_epi8(8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7); + const __m128i MASK2 = _mm_set_epi8(0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15); + + __m128i B0 = _mm_loadu_si128(CONST_M128_CAST(inBlock + 0)); + __m128i B1 = _mm_loadu_si128(CONST_M128_CAST(inBlock + 16)); + + __m128i TMP = _mm_shuffle_epi8(_mm_unpacklo_epi64(B0, B1), MASK2); + B1 = _mm_shuffle_epi8(_mm_unpackhi_epi64(B0, B1), MASK2); + B0 = TMP; +#endif + + const byte* keys = reinterpret_cast(subKeys); + for (size_t i = 0; i != 8; ++i) + { + const __m128i RK0 = _mm_load_si128(CONST_M128_CAST(keys + 32*i)); + const __m128i RK2 = _mm_load_si128(CONST_M128_CAST(keys + 32*i+16)); + const __m128i RK1 = _mm_srli_si128(RK0, 8); + const __m128i RK3 = _mm_srli_si128(RK2, 8); + + B1 = _mm_sha256rnds2_epu32(B1, B0, RK0); + B0 = _mm_sha256rnds2_epu32(B0, B1, RK1); + B1 = _mm_sha256rnds2_epu32(B1, B0, RK2); + B0 = _mm_sha256rnds2_epu32(B0, B1, RK3); + } + + TMP = _mm_shuffle_epi8(_mm_unpackhi_epi64(B0, B1), MASK1); + B1 = _mm_shuffle_epi8(_mm_unpacklo_epi64(B0, B1), MASK1); + B0 = TMP; + + if (xorBlock) + { + _mm_storeu_si128(M128_CAST(outBlock + 0), + _mm_xor_si128(B0, _mm_loadu_si128(CONST_M128_CAST(xorBlock + 0)))); + + _mm_storeu_si128(M128_CAST(outBlock + 16), + _mm_xor_si128(B1, _mm_loadu_si128(CONST_M128_CAST(xorBlock + 16)))); + } + else + { + _mm_storeu_si128(M128_CAST(outBlock + 0), B0); + _mm_storeu_si128(M128_CAST(outBlock + 16), B1); + } +} +#endif + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/shake.cpp b/external/ours/library/crypto/src/shared/original/shake.cpp new file mode 100755 index 000000000..65e082355 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/shake.cpp @@ -0,0 +1,85 @@ +// shake.cpp - modified by Wei Dai from Ronny Van Keer's public domain +// sha3-simple.c. All modifications here are placed in the +// public domain by Wei Dai. +// Keccack core function moved to keccakc.cpp in AUG 2018 +// by Jeffrey Walton. Separating the core file allows both +// SHA3 and Keccack to share the core implementation. + +/* +The SHAKE sponge function, designed by Guido Bertoni, Joan Daemen, +Michael Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by Ronny Van Keer, hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include "pch.h" +#include "shake.h" + +NAMESPACE_BEGIN(CryptoPP) + +// The Keccak core function +extern void KeccakF1600(word64 *state); + +void SHAKE::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT(!(input == NULLPTR && length != 0)); + if (length == 0) { return; } + + size_t spaceLeft; + while (length >= (spaceLeft = r() - m_counter)) + { + if (spaceLeft) + xorbuf(m_state.BytePtr() + m_counter, input, spaceLeft); + KeccakF1600(m_state); + input += spaceLeft; + length -= spaceLeft; + m_counter = 0; + } + + if (length) + xorbuf(m_state.BytePtr() + m_counter, input, length); + m_counter += (unsigned int)length; +} + +void SHAKE::Restart() +{ + memset(m_state, 0, m_state.SizeInBytes()); + m_counter = 0; +} + +void SHAKE::ThrowIfInvalidTruncatedSize(size_t size) const +{ + if (size > UINT_MAX) + throw InvalidArgument(std::string("HashTransformation: can't truncate a ") + + IntToString(UINT_MAX) + " byte digest to " + IntToString(size) + " bytes"); +} + +void SHAKE::TruncatedFinal(byte *hash, size_t size) +{ + CRYPTOPP_ASSERT(hash != NULLPTR); + ThrowIfInvalidTruncatedSize(size); + + m_state.BytePtr()[m_counter] ^= 0x1F; + m_state.BytePtr()[r()-1] ^= 0x80; + + // FIPS 202, Algorithm 8, pp 18-19. + while (size > 0) + { + KeccakF1600(m_state); + + const size_t segmentLen = STDMIN(size, (size_t)BlockSize()); + std::memcpy(hash, m_state, segmentLen); + + hash += segmentLen; + size -= segmentLen; + } + + Restart(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/shake.h b/external/ours/library/crypto/src/shared/original/shake.h new file mode 100755 index 000000000..0eaab43b2 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 algoirthm 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 algoirthm 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 algoirthm 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 algoirthm 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 algoirthm 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/external/ours/library/crypto/src/shared/original/shark.cpp b/external/ours/library/crypto/src/shared/original/shark.cpp new file mode 100755 index 000000000..6e3b8da3f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/shark.cpp @@ -0,0 +1,163 @@ +// shark.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "shark.h" +#include "misc.h" +#include "modes.h" +#include "gf256.h" + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wmissing-braces" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +static word64 SHARKTransform(word64 a) +{ + static const byte iG[8][8] = { + 0xe7, 0x30, 0x90, 0x85, 0xd0, 0x4b, 0x91, 0x41, + 0x53, 0x95, 0x9b, 0xa5, 0x96, 0xbc, 0xa1, 0x68, + 0x02, 0x45, 0xf7, 0x65, 0x5c, 0x1f, 0xb6, 0x52, + 0xa2, 0xca, 0x22, 0x94, 0x44, 0x63, 0x2a, 0xa2, + 0xfc, 0x67, 0x8e, 0x10, 0x29, 0x75, 0x85, 0x71, + 0x24, 0x45, 0xa2, 0xcf, 0x2f, 0x22, 0xc1, 0x0e, + 0xa1, 0xf1, 0x71, 0x40, 0x91, 0x27, 0x18, 0xa5, + 0x56, 0xf4, 0xaf, 0x32, 0xd2, 0xa4, 0xdc, 0x71, + }; + + word64 result=0; + GF256 gf256(0xf5); + for (unsigned int i=0; i<8; i++) + for(unsigned int j=0; j<8; j++) + result ^= word64(gf256.Multiply(iG[i][j], GF256::Element(a>>(56-8*j)))) << (56-8*i); + return result; +} + +void SHARK::Base::UncheckedSetKey(const byte *key, unsigned int keyLen, const NameValuePairs ¶ms) +{ + AssertValidKeyLength(keyLen); + + m_rounds = GetRoundsAndThrowIfInvalid(params, this); + m_roundKeys.New(m_rounds+1); + + // concatenate key enought times to fill a + for (unsigned int i=0; i<(m_rounds+1)*8; i++) + ((byte *)m_roundKeys.begin())[i] = key[i%keyLen]; + + SHARK::Encryption e; + e.InitForKeySetup(); + byte IV[8] = {0,0,0,0,0,0,0,0}; + CFB_Mode_ExternalCipher::Encryption cfb(e, IV); + + cfb.ProcessString((byte *)m_roundKeys.begin(), (m_rounds+1)*8); + + ConditionalByteReverse(BIG_ENDIAN_ORDER, m_roundKeys.begin(), m_roundKeys.begin(), (m_rounds+1)*8); + + m_roundKeys[m_rounds] = SHARKTransform(m_roundKeys[m_rounds]); + + if (!IsForwardTransformation()) + { + unsigned int i; + + // transform encryption round keys into decryption round keys + for (i=0; i())); + word64 tmp = *(word64 *)(void *)inBlock ^ m_roundKeys[0]; + + ByteOrder order = GetNativeByteOrder(); + tmp = cbox[0][GetByte(order, tmp, 0)] ^ cbox[1][GetByte(order, tmp, 1)] + ^ cbox[2][GetByte(order, tmp, 2)] ^ cbox[3][GetByte(order, tmp, 3)] + ^ cbox[4][GetByte(order, tmp, 4)] ^ cbox[5][GetByte(order, tmp, 5)] + ^ cbox[6][GetByte(order, tmp, 6)] ^ cbox[7][GetByte(order, tmp, 7)] + ^ m_roundKeys[1]; + + for(unsigned int i=2; i(xorBlock, outBlock) + (sbox[GETBYTE(tmp, 7)]) + (sbox[GETBYTE(tmp, 6)]) + (sbox[GETBYTE(tmp, 5)]) + (sbox[GETBYTE(tmp, 4)]) + (sbox[GETBYTE(tmp, 3)]) + (sbox[GETBYTE(tmp, 2)]) + (sbox[GETBYTE(tmp, 1)]) + (sbox[GETBYTE(tmp, 0)]); + + CRYPTOPP_ASSERT(IsAlignedOn(outBlock,GetAlignmentOf())); + *(word64 *)(void *)outBlock ^= m_roundKeys[m_rounds]; +} + +void SHARK::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + CRYPTOPP_ASSERT(IsAlignedOn(inBlock,GetAlignmentOf())); + word64 tmp = *(word64 *)(void *)inBlock ^ m_roundKeys[0]; + + ByteOrder order = GetNativeByteOrder(); + tmp = cbox[0][GetByte(order, tmp, 0)] ^ cbox[1][GetByte(order, tmp, 1)] + ^ cbox[2][GetByte(order, tmp, 2)] ^ cbox[3][GetByte(order, tmp, 3)] + ^ cbox[4][GetByte(order, tmp, 4)] ^ cbox[5][GetByte(order, tmp, 5)] + ^ cbox[6][GetByte(order, tmp, 6)] ^ cbox[7][GetByte(order, tmp, 7)] + ^ m_roundKeys[1]; + + for(unsigned int i=2; i(xorBlock, outBlock) + (sbox[GETBYTE(tmp, 7)]) + (sbox[GETBYTE(tmp, 6)]) + (sbox[GETBYTE(tmp, 5)]) + (sbox[GETBYTE(tmp, 4)]) + (sbox[GETBYTE(tmp, 3)]) + (sbox[GETBYTE(tmp, 2)]) + (sbox[GETBYTE(tmp, 1)]) + (sbox[GETBYTE(tmp, 0)]); + + CRYPTOPP_ASSERT(IsAlignedOn(outBlock,GetAlignmentOf())); + *(word64 *)(void *)outBlock ^= m_roundKeys[m_rounds]; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/shark.h b/external/ours/library/crypto/src/shared/original/shark.h new file mode 100755 index 000000000..09459adc8 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/sharkbox.cpp b/external/ours/library/crypto/src/shared/original/sharkbox.cpp new file mode 100755 index 000000000..1a50c1714 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/sharkbox.cpp @@ -0,0 +1,4166 @@ +#include "pch.h" +#include "shark.h" + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wmissing-braces" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +const byte SHARK::Enc::sbox[256] = { +177, 206, 195, 149, 90, 173, 231, 2, 77, 68, 251, 145, 12, 135, 161, 80, +203, 103, 84, 221, 70, 143, 225, 78, 240, 253, 252, 235, 249, 196, 26, 110, + 94, 245, 204, 141, 28, 86, 67, 254, 7, 97, 248, 117, 89, 255, 3, 34, +138, 209, 19, 238, 136, 0, 14, 52, 21, 128, 148, 227, 237, 181, 83, 35, + 75, 71, 23, 167, 144, 53, 171, 216, 184, 223, 79, 87, 154, 146, 219, 27, + 60, 200, 153, 4, 142, 224, 215, 125, 133, 187, 64, 44, 58, 69, 241, 66, +101, 32, 65, 24, 114, 37, 147, 112, 54, 5, 242, 11, 163, 121, 236, 8, + 39, 49, 50, 182, 124, 176, 10, 115, 91, 123, 183, 129, 210, 13, 106, 38, +158, 88, 156, 131, 116, 179, 172, 48, 122, 105, 119, 15, 174, 33, 222, 208, + 46, 151, 16, 164, 152, 168, 212, 104, 45, 98, 41, 109, 22, 73, 118, 199, +232, 193, 150, 55, 229, 202, 244, 233, 99, 18, 194, 166, 20, 188, 211, 40, +175, 47, 230, 36, 82, 198, 160, 9, 189, 140, 207, 93, 17, 95, 1, 197, +159, 61, 162, 155, 201, 59, 190, 81, 25, 31, 63, 92, 178, 239, 74, 205, +191, 186, 111, 100, 217, 243, 62, 180, 170, 220, 213, 6, 192, 126, 246, 102, +108, 132, 113, 56, 185, 29, 127, 157, 72, 139, 42, 218, 165, 51, 130, 57, +214, 120, 134, 250, 228, 43, 169, 30, 137, 96, 107, 234, 85, 76, 247, 226, +}; + +const byte SHARK::Dec::sbox[256] = { + 53, 190, 7, 46, 83, 105, 219, 40, 111, 183, 118, 107, 12, 125, 54, 139, +146, 188, 169, 50, 172, 56, 156, 66, 99, 200, 30, 79, 36, 229, 247, 201, + 97, 141, 47, 63, 179, 101, 127, 112, 175, 154, 234, 245, 91, 152, 144, 177, +135, 113, 114, 237, 55, 69, 104, 163, 227, 239, 92, 197, 80, 193, 214, 202, + 90, 98, 95, 38, 9, 93, 20, 65, 232, 157, 206, 64, 253, 8, 23, 74, + 15, 199, 180, 62, 18, 252, 37, 75, 129, 44, 4, 120, 203, 187, 32, 189, +249, 41, 153, 168, 211, 96, 223, 17, 151, 137, 126, 250, 224, 155, 31, 210, +103, 226, 100, 119, 132, 43, 158, 138, 241, 109, 136, 121, 116, 87, 221, 230, + 57, 123, 238, 131, 225, 88, 242, 13, 52, 248, 48, 233, 185, 35, 84, 21, + 68, 11, 77, 102, 58, 3, 162, 145, 148, 82, 76, 195, 130, 231, 128, 192, +182, 14, 194, 108, 147, 236, 171, 67, 149, 246, 216, 70, 134, 5, 140, 176, +117, 0, 204, 133, 215, 61, 115, 122, 72, 228, 209, 89, 173, 184, 198, 208, +220, 161, 170, 2, 29, 191, 181, 159, 81, 196, 165, 16, 34, 207, 1, 186, +143, 49, 124, 174, 150, 218, 240, 86, 71, 212, 235, 78, 217, 19, 142, 73, + 85, 22, 255, 59, 244, 164, 178, 6, 160, 167, 251, 27, 110, 60, 51, 205, + 24, 94, 106, 213, 166, 33, 222, 254, 42, 28, 243, 10, 26, 25, 39, 45, +}; + +const word64 SHARK::Enc::cbox[8][256] = { +/* box 0 */ +W64LIT(0x060d838f16f3a365), +W64LIT(0xa68857ee5cae56f6), +W64LIT(0xebf516353c2c4d89), +W64LIT(0x652174be88e85bdc), +W64LIT(0x0d4e9a8086c17921), +W64LIT(0x27ba7d33cffa58a1), +W64LIT(0x88d9e104a237b530), +W64LIT(0x693b8755a4fbe816), +W64LIT(0xdac9591826b254a0), +W64LIT(0x45c2e369fb336af3), +W64LIT(0xa96e1fb87b3e4ef4), +W64LIT(0xb7578f1435eb7ef0), +W64LIT(0x839af80b32056f74), +W64LIT(0xae37f55cc71f277a), +W64LIT(0xa4208538fdff37d5), +W64LIT(0x35991e74ad3cdb6f), +W64LIT(0xba191594b32a07d1), +W64LIT(0x5344d1772e572b7b), +W64LIT(0xe7efe5de103ffe43), +W64LIT(0xa3796fdc41de5e5b), +W64LIT(0x2cf9643c5fc882e5), +W64LIT(0xffdbf6fd48196d22), +W64LIT(0x33949dfbbbcf780a), +W64LIT(0x7d15679dd0cec8bd), +W64LIT(0x5f5e229c024498b1), +W64LIT(0x1223634762c683ce), +W64LIT(0xdcc4da973041f7c5), +W64LIT(0x0b43190f9032da44), +W64LIT(0xc05598eddfc5a6e2), +W64LIT(0x9e5fd31a7753f4b8), +W64LIT(0x9afa8243c0f136fe), +W64LIT(0xcc4f6b06f3d61528), +W64LIT(0xdf38612a3bc25c0d), +W64LIT(0x43cf60e6edc0c996), +W64LIT(0xcfb3d0bbf855bee0), +W64LIT(0x96e071a8ece28534), +W64LIT(0x21b7febcd909fbc4), +W64LIT(0x8ed4628bb4c41655), +W64LIT(0x30682646b04cd3c2), +W64LIT(0xb5ff5dc294ba1fd3), +W64LIT(0x75aac52f4b7fb931), +W64LIT(0xe809ad8837afe641), +W64LIT(0x0eb2213d8d42d2e9), +W64LIT(0x9852509561a057dd), +W64LIT(0xaa92a40570bde53c), +W64LIT(0x7b18e412c63d6bd8), +W64LIT(0xa7dc3e85f67c9c1d), +W64LIT(0xd8618bce87e33583), +W64LIT(0xe34ab487a79d3c05), +W64LIT(0x20e397d773db312f), +W64LIT(0x05f138321d7008ad), +W64LIT(0x17d25b757fb68b63), +W64LIT(0x8a7133d20366d413), +W64LIT(0x0000000000000000), +W64LIT(0xeaa17f5e96fe8762), +W64LIT(0xc101f18675176c09), +W64LIT(0xbebc44cd0488c597), +W64LIT(0xdb9d30738c609e4b), +W64LIT(0xabc6cd6eda6f2fd7), +W64LIT(0x5aaf1aae1f34901c), +W64LIT(0xb00e65f089ca177e), +W64LIT(0xd47b7825abf08649), +W64LIT(0x924520f15b404772), +W64LIT(0x1686321ed5644188), +W64LIT(0x618425e73f4a999a), +W64LIT(0xe21eddec0d4ff6ee), +W64LIT(0xd787c398a0732d81), +W64LIT(0x1f6df9c7e407faef), +W64LIT(0x79b036c4676c0afb), +W64LIT(0x0fe6485627901802), +W64LIT(0x9cf701ccd602959b), +W64LIT(0xbfe82da6ae5a0f7c), +W64LIT(0x990639fecb729d36), +W64LIT(0xca42e889e525b64d), +W64LIT(0xb3f2de4d8249bcb6), +W64LIT(0x4033db5be643625e), +W64LIT(0x4167b2304c91a8b5), +W64LIT(0x108bb191c397e2ed), +W64LIT(0x1834132358269361), +W64LIT(0x541d3b93927642f5), +W64LIT(0x90edf227fa112651), +W64LIT(0x1dc52b1145569bcc), +W64LIT(0xe6bb8cb5baed34a8), +W64LIT(0xd276fbaabd03252c), +W64LIT(0x313c4f2d1a9e1929), +W64LIT(0xfd73242be9480c01), +W64LIT(0x9baeeb286a23fc15), +W64LIT(0xc9be5334eea61d85), +W64LIT(0xc70c720963e4cf6c), +W64LIT(0x3eda077b3d0e012b), +W64LIT(0x97b418c346304fdf), +W64LIT(0x32c0f490111db2e1), +W64LIT(0x2ba08ed8e3e9eb6b), +W64LIT(0x8b255ab9a9b41ef8), +W64LIT(0x91b99b4c50c3ecba), +W64LIT(0xfe8f9f96e2cba7c9), +W64LIT(0x3a7f56228aacc36d), +W64LIT(0xb15a0c9b2318dd95), +W64LIT(0x5953a11314b73bd4), +W64LIT(0xf3c10516640adee8), +W64LIT(0xedf895ba2adfeeec), +W64LIT(0xadcb4ee1cc9c8cb2), +W64LIT(0xde6c0841911096e6), +W64LIT(0x84c312ef8e2406fa), +W64LIT(0xa83a76d3d1ec841f), +W64LIT(0x1c91427aef845127), +W64LIT(0x3665a5c9a6bf70a7), +W64LIT(0xf6303d24797ad645), +W64LIT(0xcd1b026d5904dfc3), +W64LIT(0x1bc8a89e53a538a9), +W64LIT(0x7ee9dc20db4d6375), +W64LIT(0x51ec03a18f064a58), +W64LIT(0xc4f0c9b4686764a4), +W64LIT(0xdd90b3fc9a933d2e), +W64LIT(0x7a4c8d796cefa133), +W64LIT(0x73a746a05d8c1a54), +W64LIT(0x0759eae4bc21698e), +W64LIT(0xc8ea3a5f4474d76e), +W64LIT(0x38d784f42bfda24e), +W64LIT(0x231f2c6a78589ae7), +W64LIT(0xc3a92350d4460d2a), +W64LIT(0x72f32fcbf75ed0bf), +W64LIT(0xbd40ff700f0b6e5f), +W64LIT(0x157a89a3dee7ea40), +W64LIT(0x873fa95285a7ad32), +W64LIT(0x4d7d41db60821b7f), +W64LIT(0x1e3990ac4ed53004), +W64LIT(0x0a1770643ae010af), +W64LIT(0x9311499af1928d99), +W64LIT(0x64751dd5223a9137), +W64LIT(0xfa2acecf5569658f), +W64LIT(0x7c410ef67a1c0256), +W64LIT(0x56b5e945332723d6), +W64LIT(0x6f3604dab2084b73), +W64LIT(0xe95dc4e39d7d2caa), +W64LIT(0x13770a2cc8144925), +W64LIT(0xbc14961ba5d9a4b4), +W64LIT(0xb9e5ae29b8a9ac19), +W64LIT(0xf169d7c0c55bbfcb), +W64LIT(0x2446c68ec479f369), +W64LIT(0x806643b63986c4bc), +W64LIT(0x7fbdb54b719fa99e), +W64LIT(0x04a55159b7a2c246), +W64LIT(0xee042e07215c4524), +W64LIT(0x5bfb73c5b5e65af7), +W64LIT(0x0c1af3eb2c13b3ca), +W64LIT(0xa22d06b7eb0c94b0), +W64LIT(0xb8b1c742127b66f2), +W64LIT(0x285c3565e86a40a3), +W64LIT(0x3b2b3f49207e0986), +W64LIT(0x3c72d5ad9c5f6008), +W64LIT(0x770217f9ea2ed812), +W64LIT(0xfc274d40439ac6ea), +W64LIT(0x4fd5930dc1d37a5c), +W64LIT(0x2e51b6eafe99e3c6), +W64LIT(0x6b93558305aa8935), +W64LIT(0x19607a48f2f4598a), +W64LIT(0x08bfa2b29bb1718c), +W64LIT(0x3f8e6e1097dccbc0), +W64LIT(0x3983ed9f812f68a5), +W64LIT(0xac9f278a664e4659), +W64LIT(0x82ce916098d7a59f), +W64LIT(0xc2fd4a3b7e94c7c1), +W64LIT(0x66ddcf03836bf014), +W64LIT(0xe1e2665106cc5d26), +W64LIT(0x74feac44e1ad73da), +W64LIT(0x8d28d936bf47bd9d), +W64LIT(0x62789e5a34c93252), +W64LIT(0x81322add93540e57), +W64LIT(0xcb1681e24ff77ca6), +W64LIT(0x2512afe56eab3982), +W64LIT(0xd18a4017b6808ee4), +W64LIT(0x705bfd1d560fb19c), +W64LIT(0x4b70c2547671b81a), +W64LIT(0x49d81082d720d939), +W64LIT(0xe0b60f3aac1e97cd), +W64LIT(0x4e81fa666b01b0b7), +W64LIT(0x951cca15e7612efc), +W64LIT(0x463e58d4f0b0c13b), +W64LIT(0x632cf7319e1bf8b9), +W64LIT(0x5ca2992109c73379), +W64LIT(0xf764544fd3a81cae), +W64LIT(0x6ac73ce8af7843de), +W64LIT(0x9f0bba71dd813e53), +W64LIT(0x85977b8424f6cc11), +W64LIT(0x5807c878be65f13f), +W64LIT(0x686fee3e0e2922fd), +W64LIT(0x78e45fafcdbec010), +W64LIT(0x6ccabf67b98be0bb), +W64LIT(0x11dfd8fa69452806), +W64LIT(0xcee7b9d05287740b), +W64LIT(0x50b86aca25d480b3), +W64LIT(0x5df6f04aa315f992), +W64LIT(0x5e0a4bf7a896525a), +W64LIT(0x03fcbbbd0b83abc8), +W64LIT(0x8f800be01e16dcbe), +W64LIT(0xd32292c117d1efc7), +W64LIT(0xe5473708b16e9f60), +W64LIT(0x224b4501d28a500c), +W64LIT(0xfb7ea7a4ffbbaf64), +W64LIT(0x3d26bcc6368daae3), +W64LIT(0x866bc0392f7567d9), +W64LIT(0x3731cca20c6dba4c), +W64LIT(0xb603e67f9f39b41b), +W64LIT(0xa1d1bd0ae08f3f78), +W64LIT(0xd935e2a52d31ff68), +W64LIT(0xaf639c376dcded91), +W64LIT(0x0154696baad2caeb), +W64LIT(0xecacfcd1800d2407), +W64LIT(0xf03dbeab6f897520), +W64LIT(0x02a8d2d6a1516123), +W64LIT(0xf498eff2d82bb766), +W64LIT(0x710f9476fcdd7b77), +W64LIT(0xf8821c19f43804ac), +W64LIT(0xf9d675725eeace47), +W64LIT(0x1a9cc1f5f977f242), +W64LIT(0x5210b81c8485e190), +W64LIT(0x6d9ed60c13592a50), +W64LIT(0xf2956c7dced81403), +W64LIT(0xbb4d7cff19f8cd3a), +W64LIT(0x4c2928b0ca50d194), +W64LIT(0x6e626db118da8198), +W64LIT(0xe4135e631bbc558b), +W64LIT(0x9da368a77cd05f70), +W64LIT(0xa574ec53572dfd3e), +W64LIT(0x09ebcbd93163bb67), +W64LIT(0x4a24ab3fdca372f1), +W64LIT(0x429b098d4712037d), +W64LIT(0x57e1802e99f5e93d), +W64LIT(0xef50476c8b8e8fcf), +W64LIT(0xa085d4614a5df593), +W64LIT(0x34cd771f07ee1184), +W64LIT(0xc6581b62c9360587), +W64LIT(0x2dad0d57f51a480e), +W64LIT(0x898d886f08e57fdb), +W64LIT(0xd6d3aaf30aa1e76a), +W64LIT(0x76567e9240fc12f9), +W64LIT(0xb4ab34a93e68d538), +W64LIT(0xb2a6b726289b765d), +W64LIT(0x8c7cb05d15957776), +W64LIT(0x554952f838a4881e), +W64LIT(0xd52f114e01224ca2), +W64LIT(0x60d04c8c95985371), +W64LIT(0x6789a66829b93aff), +W64LIT(0x2f05df81544b292d), +W64LIT(0x476a31bf5a620bd0), +W64LIT(0xf5cc869972f97d8d), +W64LIT(0x488c79e97df213d2), +W64LIT(0x44968a0251e1a018), +W64LIT(0x26ee14586528924a), +W64LIT(0xd0de297c1c52440f), +W64LIT(0xc5a4a0dfc2b5ae4f), +W64LIT(0x29085c0e42b88a48), +W64LIT(0x142ee0c8743520ab), +W64LIT(0x2af4e7b3493b2180), +W64LIT(0x9448a37e4db3e417), +/* box 1 */ +W64LIT(0xe2795ba105ba30ce), +W64LIT(0x65b5d634f5e0fbdd), +W64LIT(0x2d7d7f1464dd8c55), +W64LIT(0xeefbf778add1c20b), +W64LIT(0x1eb0fbd1f11968e7), +W64LIT(0xe6073f45ce30cd8d), +W64LIT(0x21ffd3cdccb67e90), +W64LIT(0xdf0941cfa750a262), +W64LIT(0xc61df5b1b75ef18a), +W64LIT(0xc5c7defa9dc337c6), +W64LIT(0x2581b729073c83d3), +W64LIT(0xa5e97513167173cf), +W64LIT(0xdd3673bd381526b9), +W64LIT(0xe8baa1eef91ebb93), +W64LIT(0x3b314cf8f625eb34), +W64LIT(0x579d4bc8d5fc5df8), +W64LIT(0xbb598ec2e7681b28), +W64LIT(0xc8a06b1a80708794), +W64LIT(0x1c8fc9a36e5cec3c), +W64LIT(0xf60a5a3f0807d374), +W64LIT(0x1ace9f353a9395a4), +W64LIT(0x7e9e50387aab2cee), +W64LIT(0xb5e41069d0466d36), +W64LIT(0x8cea6ee3b92602d9), +W64LIT(0xf952ddad8af1e7fd), +W64LIT(0xb19a748d1bcc9075), +W64LIT(0x2464ae10b2e4c144), +W64LIT(0xfcc9a070f4a35829), +W64LIT(0xfa88f6e6a06c21b1), +W64LIT(0x2c98662dd105cec2), +W64LIT(0x9065a740d77aeee5), +W64LIT(0xcb7a4051aaed41d8), +W64LIT(0x55a279ba4ab9d923), +W64LIT(0x27be855b98790708), +W64LIT(0xbabc97fb52b059bf), +W64LIT(0xa19711f7ddfb8e8c), +W64LIT(0x047e64e4cb8afd43), +W64LIT(0xc386886cc90c4e5e), +W64LIT(0xc422c7c3281b7551), +W64LIT(0xfb6defdf15b46326), +W64LIT(0x01e51939b5d84297), +W64LIT(0x5cbba8be9c809432), +W64LIT(0x6f762c7b09447080), +W64LIT(0xcee13d8cd4bffe0c), +W64LIT(0x54476083ff619bb4), +W64LIT(0x6e933542bc9c3217), +W64LIT(0x4af79b520e78f353), +W64LIT(0x98996f7db49be163), +W64LIT(0xa07208ce6823cc1b), +W64LIT(0x2b3c29823012f5cd), +W64LIT(0x93bf8c0bfde728a9), +W64LIT(0x2225f886e62bb8dc), +W64LIT(0x7f7b4901cf736e79), +W64LIT(0x0000000000000000), +W64LIT(0x023f32729f4584db), +W64LIT(0xd5cabb805bf4293f), +W64LIT(0x07a44fafe1173b0f), +W64LIT(0xe95fb8d74cc6f904), +W64LIT(0x7b052de504f9933a), +W64LIT(0x6aed51a67716cf54), +W64LIT(0x68d263d4e8534b8f), +W64LIT(0xa96bd9cabe1a810a), +W64LIT(0x1d6ad09adb84aeab), +W64LIT(0x0d67b5e01db3b052), +W64LIT(0x52063615abaee22c), +W64LIT(0x8f3045a893bbc495), +W64LIT(0xd8ad0e604647996d), +W64LIT(0xaf2a8f5cead5f892), +W64LIT(0x3017af8ebf5922fe), +W64LIT(0x4034611df2dc780e), +W64LIT(0x721cfce1d2c0de2b), +W64LIT(0x28e602c91a8f3381), +W64LIT(0xe1a370ea2f27f682), +W64LIT(0x29031bf0af577116), +W64LIT(0x1914b47e100e53e8), +W64LIT(0x567852f160241f6f), +W64LIT(0x793a1f979bbc17e1), +W64LIT(0xef1eee411809809c), +W64LIT(0x6211999b14f7c0d2), +W64LIT(0x059b7ddd7e52bfd4), +W64LIT(0x43ee4a56d841be42), +W64LIT(0xf1ae1590e910e87b), +W64LIT(0x33cd84c595c4e4b2), +W64LIT(0x4b12826bbba0b1c4), +W64LIT(0xeb608aa5d3837ddf), +W64LIT(0x201acaf4796e3c07), +W64LIT(0xbf27ea262ce2e66b), +W64LIT(0x58c5cc5a570a6971), +W64LIT(0x37b3e0215e4e19f1), +W64LIT(0xab54ebb8215f05d1), +W64LIT(0x8ed55c9126638602), +W64LIT(0x9aa65d0f2bde65b8), +W64LIT(0xd7f589f2c4b1ade4), +W64LIT(0x5039046734eb66f7), +W64LIT(0x6cac073023d9b6cc), +W64LIT(0x51dc1d5e81332460), +W64LIT(0x17a92ad5272025f6), +W64LIT(0x47902eb213cb4301), +W64LIT(0x1b2b860c8f4bd733), +W64LIT(0x4f6ce68f702a4c87), +W64LIT(0xcf0424b56167bc9b), +W64LIT(0x997c76440143a3f4), +W64LIT(0x7ae034dcb121d1ad), +W64LIT(0x100d657ac6371ef9), +W64LIT(0x0ac3fa4ffca48b5d), +W64LIT(0xdeec58f61288e0f5), +W64LIT(0x265b9c622da1459f), +W64LIT(0xdcd36a848dcd642e), +W64LIT(0xe4380d3751754956), +W64LIT(0x13d74e31ecaad8b5), +W64LIT(0xfd2cb949417b1abe), +W64LIT(0x9624f1d683b5977d), +W64LIT(0x4675378ba6130196), +W64LIT(0x0b26e376497cc9ca), +W64LIT(0x41d1782447043a99), +W64LIT(0xe39c4298b0627259), +W64LIT(0xcd3b16c7fe223840), +W64LIT(0x7787813cac9261ff), +W64LIT(0x492db01924e5351f), +W64LIT(0x5afafe28c84fedaa), +W64LIT(0x8b4e214c583139d6), +W64LIT(0xccde0ffe4bfa7ad7), +W64LIT(0x76629805194a2368), +W64LIT(0x7ca1624ae5eea835), +W64LIT(0x61cbb2d03e6a069e), +W64LIT(0x48c8a920913d7788), +W64LIT(0x8068c23a114df01c), +W64LIT(0xd38bed160f3b50a7), +W64LIT(0x32289dfc201ca625), +W64LIT(0xc1b9ba1e5649ca85), +W64LIT(0xed21dc33874c0447), +W64LIT(0xa3a8238542be0a57), +W64LIT(0x5b1fe7117d97af3d), +W64LIT(0x3d701a6ea2ea92ac), +W64LIT(0x73f9e5d867189cbc), +W64LIT(0x9ed839ebe05498fb), +W64LIT(0x5920d563e2d22be6), +W64LIT(0xca9f59681f35034f), +W64LIT(0x11e87c4373ef5c6e), +W64LIT(0x97c1e8ef366dd5ea), +W64LIT(0xacf0a417c0483ede), +W64LIT(0xd26ef42fbae31230), +W64LIT(0xbcfdc16d067f2027), +W64LIT(0xbec2f31f993aa4fc), +W64LIT(0x45af1cc08c8ec7da), +W64LIT(0x31f2b6b70a816069), +W64LIT(0xd9481759f39fdbfa), +W64LIT(0xe5dd140ee4ad0bc1), +W64LIT(0xa6335e583cecb583), +W64LIT(0x38eb67b3dcb82d78), +W64LIT(0xf5d07174229a1538), +W64LIT(0x5f6183f5b61d527e), +W64LIT(0x0f58879282f63489), +W64LIT(0x164c33ec92f86761), +W64LIT(0x444a05f93956854d), +W64LIT(0x818ddb03a495b28b), +W64LIT(0x4d53d4fdef6fc85c), +W64LIT(0x8d0f77da0cfe404e), +W64LIT(0x8416a6dedac70d5f), +W64LIT(0x666ffd7fdf7d3d91), +W64LIT(0xb63e3b22fadbab7a), +W64LIT(0xf2743edbc38d2e37), +W64LIT(0xa40c6c2aa3a93158), +W64LIT(0x9f3d20d2558cda6c), +W64LIT(0xfef692026be6dcf2), +W64LIT(0x2ea7545f4e404a19), +W64LIT(0xb2405fc631515639), +W64LIT(0x23c0e1bf53f3fa4b), +W64LIT(0x83b2e9713bd03650), +W64LIT(0x0641569654cf7998), +W64LIT(0xb883a589cdf5dd64), +W64LIT(0x3ad455c143fda9a3), +W64LIT(0x925a9532483f6a3e), +W64LIT(0xaab1f28194874746), +W64LIT(0xf435684d974257af), +W64LIT(0xd1b4df64907ed47c), +W64LIT(0x390e7e8a69606fef), +W64LIT(0xd051c65d25a696eb), +W64LIT(0xb4010950659e2fa1), +W64LIT(0x0c82acd9a86bf2c5), +W64LIT(0x88940a0772acff9a), +W64LIT(0xf39127e276556ca0), +W64LIT(0xaecf96655f0dba05), +W64LIT(0x03da2b4b2a9dc64c), +W64LIT(0x3f4f281c3daf1677), +W64LIT(0x3469cb6a74d3dfbd), +W64LIT(0xf04b0ca95cc8aaec), +W64LIT(0x1f55e2e844c12a70), +W64LIT(0x4cb6cdc45ab78acb), +W64LIT(0xc05ca327e3918812), +W64LIT(0x95feda9da9285131), +W64LIT(0xb966bcb0782d9ff3), +W64LIT(0xa7d647618934f714), +W64LIT(0xd61090cb7169ef73), +W64LIT(0x71c6d7aaf85d1867), +W64LIT(0xecc4c50a329446d0), +W64LIT(0x6450cf0d4038b94a), +W64LIT(0x420b536f6d99fcd5), +W64LIT(0x75b8b34e33d7e524), +W64LIT(0xc26391557cd40cc9), +W64LIT(0xda923c12d9021db6), +W64LIT(0x4e89ffb6c5f20e10), +W64LIT(0x0919d104d6394d11), +W64LIT(0x8aab3875ede97b41), +W64LIT(0xa88ec0f30bc2c39d), +W64LIT(0xb7db221b4f03e9ed), +W64LIT(0xc7f8ec880286b31d), +W64LIT(0x2f424d66fb98088e), +W64LIT(0xe04669d39affb415), +W64LIT(0x3eaa3125887754e0), +W64LIT(0x5e849acc03c510e9), +W64LIT(0x8257f0488e0874c7), +W64LIT(0xbd18d854b3a762b0), +W64LIT(0xb3a546ff848914ae), +W64LIT(0x9ce70b997f111c20), +W64LIT(0x3c9503571732d03b), +W64LIT(0xe7e2267c7be88f1a), +W64LIT(0x63f480a2a12f8245), +W64LIT(0x602eabe98bb24409), +W64LIT(0x941bc3a41cf013a6), +W64LIT(0x678ae4466aa57f06), +W64LIT(0x1232570859729a22), +W64LIT(0x6d491e099601f45b), +W64LIT(0x5d5eb1872958d6a5), +W64LIT(0x1473019e0dbde3ba), +W64LIT(0xa24d3abcf76648c0), +W64LIT(0x85f3bfe76f1f4fc8), +W64LIT(0x08fcc83d63e10f86), +W64LIT(0x745daa77860fa7b3), +W64LIT(0x9180be7962a2ac72), +W64LIT(0x87cc8d95f05acb13), +W64LIT(0x78df06ae2e645576), +W64LIT(0x18f1ad47a5d6117f), +W64LIT(0x358cd253c10b9d2a), +W64LIT(0x0ebd9eab372e761e), +W64LIT(0xf7ef4306bddf91e3), +W64LIT(0x7023ce934d855af0), +W64LIT(0xd42fa2b9ee2c6ba8), +W64LIT(0x3656f918eb965b66), +W64LIT(0x9d0212a0cac95eb7), +W64LIT(0x2ad930bb85cab75a), +W64LIT(0x862994ac45828984), +W64LIT(0x7d447b735036eaa2), +W64LIT(0xb07f6db4ae14d2e2), +W64LIT(0x6b08489fc2ce8dc3), +W64LIT(0x9b4344369e06272f), +W64LIT(0xad15bd2e75907c49), +W64LIT(0xdb77252b6cda5f21), +W64LIT(0xea85939c665b3f48), +W64LIT(0xc945722335a8c503), +W64LIT(0x159618a7b865a12d), +W64LIT(0x69377aed5d8b0918), +W64LIT(0x8971133ec774bd0d), +W64LIT(0x53e32f2c1e76a0bb), +W64LIT(0xf8b7c4943f29a56a), +W64LIT(0xff138b3bde3e9e65), +/* box 2 */ +W64LIT(0x7c6a2eb5fdabecc6), +W64LIT(0x401cda0a752bbea0), +W64LIT(0x1925217156dc57c4), +W64LIT(0x56dec6d301d70787), +W64LIT(0x41c751ff73c6ac58), +W64LIT(0xc9067697a92cb5f9), +W64LIT(0x3391c917aaa0bc85), +W64LIT(0xae0a9a4c0e742afe), +W64LIT(0xaa8ca972162a62f4), +W64LIT(0x5aa193912935df99), +W64LIT(0x86fd9135fe27e5ba), +W64LIT(0xffca074b1d3f538e), +W64LIT(0x0e3cb65d24cdfc1b), +W64LIT(0x4384b2e07fe9885d), +W64LIT(0xc73ac0ca8de149e2), +W64LIT(0x48e5bc7645972eb4), +W64LIT(0xbe0d56b46ef9ffd6), +W64LIT(0x200e6d05c0ef5f50), +W64LIT(0xe1f17dee597f7abd), +W64LIT(0x0243e31f0c2f2405), +W64LIT(0xf4ab09dd2741f567), +W64LIT(0xe4acc52547cc204f), +W64LIT(0x348f92c3b83cc272), +W64LIT(0x53837e181f645d75), +W64LIT(0xd8da319acf4c7229), +W64LIT(0x81e3cae1ecbb9b4d), +W64LIT(0xd6e687c7eb818e32), +W64LIT(0x3dad7f4a8e6d409e), +W64LIT(0x28f70b79f053cf44), +W64LIT(0x493e3783437a3c4c), +W64LIT(0xb27203f6461b27c8), +W64LIT(0xd02357e6fff0e23d), +W64LIT(0xe8d390676f2ef851), +W64LIT(0x26cbbd24d49e335f), +W64LIT(0xee1640467b5f945e), +W64LIT(0x4aa65f6949b80ab1), +W64LIT(0xb56c58225487593f), +W64LIT(0x4ffbe7a2570b5043), +W64LIT(0x0aba85633c93b411), +W64LIT(0x78ec1d8be5f5a4cc), +W64LIT(0x501b16f215a66b88), +W64LIT(0x271036d1d27321a7), +W64LIT(0x7ff2465ff769da3b), +W64LIT(0x35541936bed1d08a), +W64LIT(0xb8c886957a8893d9), +W64LIT(0x2fe950ade2cfb1b3), +W64LIT(0xf90fd76a094e3f81), +W64LIT(0x2daab3b2eee095b6), +W64LIT(0x1abd499b5c1e6139), +W64LIT(0x0c7f554228e2d81e), +W64LIT(0x425f391579049aa5), +W64LIT(0xc3bcf3f495bf01e8), +W64LIT(0xb4b7d3d7526a4bc7), +W64LIT(0x0000000000000000), +W64LIT(0xa0362c112ab9d6e5), +W64LIT(0x91e406198c364e65), +W64LIT(0x454162c16b98e452), +W64LIT(0x139fa4126a4fe3d5), +W64LIT(0x01db8bf506ed12f8), +W64LIT(0x9a85088fb648e88c), +W64LIT(0x3ab3249e9cf13e69), +W64LIT(0xd57eef2de143b8cf), +W64LIT(0xb1ea6b1c4cd91135), +W64LIT(0x7aaffe94e9da80c9), +W64LIT(0xad92f2a604b61c03), +W64LIT(0xa3ae44fb207be018), +W64LIT(0xeb4bf88d65ecceac), +W64LIT(0xc0249b1e9f7d3715), +W64LIT(0xa8cf4a6d1a0546f1), +W64LIT(0xc6e14b3f8b0c5b1a), +W64LIT(0xce182d43bbb0cb0e), +W64LIT(0xfc526fa117fd6573), +W64LIT(0x8c471456c2b451ab), +W64LIT(0xac497953025b0efb), +W64LIT(0x0486333e185e480a), +W64LIT(0x18feaa845031453c), +W64LIT(0xa1eda7e42c54c41d), +W64LIT(0x06c5d02114716c0f), +W64LIT(0x055db8cb1eb35af2), +W64LIT(0xe5774ed0412132b7), +W64LIT(0x36cc71dcb413e677), +W64LIT(0x470281de67b7c057), +W64LIT(0x58e2708e251afb9c), +W64LIT(0xa914c1981ce85409), +W64LIT(0xb3a9880340f63530), +W64LIT(0x638adfe5bf06d70d), +W64LIT(0x0b610e963a7ea6e9), +W64LIT(0x927c6ef386f47898), +W64LIT(0xed8e28ac719da2a3), +W64LIT(0x7548c33ccbfa6e2a), +W64LIT(0xf3b5520935dd8b90), +W64LIT(0x8d9c9fa3c4594353), +W64LIT(0x31d22a08a68f9880), +W64LIT(0x0da4deb72e0fcae6), +W64LIT(0x8fdf7cbcc8766756), +W64LIT(0x5dbfc8453ba9a16e), +W64LIT(0x8e04f749ce9b75ae), +W64LIT(0x83a029fee094bf48), +W64LIT(0xa4b01f2f32e79eef), +W64LIT(0x1c7899ba486f0d36), +W64LIT(0x654f0fc4ab77bb02), +W64LIT(0x7db1a540fb46fe3e), +W64LIT(0x51c09d07134b7970), +W64LIT(0xcb459588a50391fc), +W64LIT(0x3fee9c558242649b), +W64LIT(0xfe118cbe1bd24176), +W64LIT(0x76d0abd6c13858d7), +W64LIT(0x5e27a0af316b9793), +W64LIT(0x69305a868395631c), +W64LIT(0x3b68af6b9a1c2c91), +W64LIT(0x6db669b89bcb2b16), +W64LIT(0xa72877c53825a812), +W64LIT(0xd3bb3f0cf532d4c0), +W64LIT(0x6ff58aa797e40f13), +W64LIT(0x96fa5dcd9eaa3092), +W64LIT(0x2c713847e80d874e), +W64LIT(0xc57923d581ce6de7), +W64LIT(0x2b6f6393fa91f9b9), +W64LIT(0x0922ed89365182ec), +W64LIT(0x324a42e2ac4dae7d), +W64LIT(0x16c21cd974fcb927), +W64LIT(0x956235279468066f), +W64LIT(0x7b747561ef379231), +W64LIT(0x449ae9346d75f6aa), +W64LIT(0xf570822821ace79f), +W64LIT(0x5939fb7b23f7e964), +W64LIT(0x7937967ee318b634), +W64LIT(0x84be722af208c1bf), +W64LIT(0x08f9667c30bc9014), +W64LIT(0xefcdcbb37db286a6), +W64LIT(0xa6f3fc303ec8baea), +W64LIT(0xea9073786301dc54), +W64LIT(0x62515410b9ebc5f5), +W64LIT(0xd260b4f9f3dfc638), +W64LIT(0x9e033bb1ae16a086), +W64LIT(0x38f0c78190de1a6c), +W64LIT(0xc267780193521310), +W64LIT(0x80384114ea5689b5), +W64LIT(0x9b5e837ab0a5fa74), +W64LIT(0xf73361372d83c39a), +W64LIT(0x3009a1fda0628a78), +W64LIT(0xd4a564d8e7aeaa37), +W64LIT(0xfb4c347505611b84), +W64LIT(0x5b7a18642fd8cd61), +W64LIT(0x239605efca2d69ad), +W64LIT(0xf8d45c9f0fa32d79), +W64LIT(0xbb50ee7f704aa524), +W64LIT(0x392b4c7496330894), +W64LIT(0x0fe73da82220eee3), +W64LIT(0x3717fa29b2fef48f), +W64LIT(0xf26ed9fc33309968), +W64LIT(0xd73d0c32ed6c9cca), +W64LIT(0xda99d285c363562c), +W64LIT(0xde1fe1bbdb3d1e26), +W64LIT(0x738d131ddf8b0225), +W64LIT(0x292c808cf6beddbc), +W64LIT(0xbc4eb5ab62d6dbd3), +W64LIT(0x039868ea0ac236fd), +W64LIT(0xcc5bce5cb79fef0b), +W64LIT(0xb031e0e94a3403cd), +W64LIT(0xc4a2a82087237f1f), +W64LIT(0xb72fbb3d58a87d3a), +W64LIT(0xafd111b908993806), +W64LIT(0x68ebd173857871e4), +W64LIT(0x9d9b535ba4d4967b), +W64LIT(0xe9081b9269c3eaa9), +W64LIT(0x71cef002d3a42620), +W64LIT(0x93a7e50680196a60), +W64LIT(0x891aac9ddc070b59), +W64LIT(0x155a74337e3e8fda), +W64LIT(0x4e206c5751e642bb), +W64LIT(0x9721d6389847226a), +W64LIT(0x12442fe76ca2f12d), +W64LIT(0x2553d5cede5c05a2), +W64LIT(0xa275cf0e2696f2e0), +W64LIT(0x24885e3bd8b1175a), +W64LIT(0x670cecdba7589f07), +W64LIT(0x749348c9cd177cd2), +W64LIT(0x64948431ad9aa9fa), +W64LIT(0x2ab4e866fc7ceb41), +W64LIT(0xe6ef263a4be3044a), +W64LIT(0xe734adcf4d0e16b2), +W64LIT(0x903f8dec8adb5c9d), +W64LIT(0xf02d3ae33f1fbd6d), +W64LIT(0x725698e8d96610dd), +W64LIT(0x1da3124f4e821fce), +W64LIT(0x1719972c7211abdf), +W64LIT(0x11dc470d6660c7d0), +W64LIT(0xec55a3597770b05b), +W64LIT(0xbfd6dd416814ed2e), +W64LIT(0x57054d26073a157f), +W64LIT(0x1e3b7aa544402933), +W64LIT(0x5ffc2b5a3786856b), +W64LIT(0x61c93cfab329f308), +W64LIT(0x3e3517a084af7663), +W64LIT(0xf6e8eac22b6ed162), +W64LIT(0x1007ccf8608dd528), +W64LIT(0x66d7672ea1b58dff), +W64LIT(0x8b594f82d0282f5c), +W64LIT(0x1fe0f15042ad3bcb), +W64LIT(0x4b7dd49c4f551849), +W64LIT(0x4c638f485dc966be), +W64LIT(0xcfc3a6b6bd5dd9f6), +W64LIT(0x46d90a2b615ad2af), +W64LIT(0x8565f9dff4e5d347), +W64LIT(0x94b9bed292851497), +W64LIT(0xfa97bf80038c097c), +W64LIT(0xb9130d607c658121), +W64LIT(0xdc5c02a4d7123a23), +W64LIT(0x224d8e1accc07b55), +W64LIT(0x87261ac0f8caf742), +W64LIT(0xd901ba6fc9a160d1), +W64LIT(0xab57228710c7700c), +W64LIT(0x21d5e6f0c6024da8), +W64LIT(0x98c6eb90ba67cc89), +W64LIT(0x827ba20be679adb0), +W64LIT(0x991d6065bc8ade71), +W64LIT(0x5546ae390b15317a), +W64LIT(0xa56b94da340a8c17), +W64LIT(0x071e5bd4129c7ef7), +W64LIT(0xe02af61b5f926845), +W64LIT(0x6b73b9998fba4719), +W64LIT(0xdfc46a4eddd00cde), +W64LIT(0x770b2023c7d54a2f), +W64LIT(0x7e29cdaaf184c8c3), +W64LIT(0xba8b658a76a7b7dc), +W64LIT(0x9c40d8aea2398483), +W64LIT(0x9fd8b044a8fbb27e), +W64LIT(0xdb425970c58e44d4), +W64LIT(0xe269150453bd4c40), +W64LIT(0x3c76f4bf88805266), +W64LIT(0xf1f6b11639f2af95), +W64LIT(0x549d25cc0df82382), +W64LIT(0x4db804bd5b247446), +W64LIT(0x8a82c477d6c53da4), +W64LIT(0x5258f5ed19894f8d), +W64LIT(0x6e2e015291091deb), +W64LIT(0xc1ff10eb999025ed), +W64LIT(0xbd953e5e643bc92b), +W64LIT(0xc8ddfd62afc1a701), +W64LIT(0x5c6443b03d44b396), +W64LIT(0x6c6de24d9d2639ee), +W64LIT(0x1481ffc678d39d22), +W64LIT(0xd1f8dc13f91df0c5), +W64LIT(0xca9e1e7da3ee8304), +W64LIT(0xdd878951d1ff28db), +W64LIT(0x6012b70fb5c4e1f0), +W64LIT(0x1b66c26e5af373c1), +W64LIT(0xe3b29ef155505eb8), +W64LIT(0x70157bf7d54934d8), +W64LIT(0x2e32db58e422a34b), +W64LIT(0x6aa8326c895755e1), +W64LIT(0xb6f430c85e456fc2), +W64LIT(0xfd89e4541110778b), +W64LIT(0x88c12768daea19a1), +W64LIT(0xcd8045a9b172fdf3), +/* box 3 */ +W64LIT(0x99183e616655b742), +W64LIT(0xb2872032a50d6860), +W64LIT(0x0946f63b060528ef), +W64LIT(0x36612b9a141ef07d), +W64LIT(0x0634da84dd49579b), +W64LIT(0xfc9c9e9b486c8a57), +W64LIT(0xa63fe3c0744e6fd0), +W64LIT(0xf1515758d8b46bf9), +W64LIT(0x3e82559fcd5197ff), +W64LIT(0x92e12d262bc40177), +W64LIT(0xc3bb433a5a7752c5), +W64LIT(0x21c3852a5183267a), +W64LIT(0x39130725cf528f09), +W64LIT(0x9ba7db1d2dc12998), +W64LIT(0xc58f99be873e055e), +W64LIT(0xd9d424498f32656c), +W64LIT(0x27f75fae8cca71e1), +W64LIT(0x59b91019a8fc3430), +W64LIT(0xce768af9caafb36b), +W64LIT(0x9d930199f0887e03), +W64LIT(0x63b07a7ef3706a8e), +W64LIT(0xb5167288a70e7096), +W64LIT(0x40cc1a28e967d22e), +W64LIT(0x4d01d3eb79bf3380), +W64LIT(0x9e896cdb6456afb4), +W64LIT(0x2548bad2c75eef3b), +W64LIT(0xa79a6bfeab0420bd), +W64LIT(0x9f2ce4e5bb1ce0d9), +W64LIT(0x32ea146282c3393c), +W64LIT(0x6d67defff7765a97), +W64LIT(0x83775912b31080eb), +W64LIT(0xf5da68a04e69a2b8), +W64LIT(0x1196743498d4819c), +W64LIT(0x0bf913474d91b635), +W64LIT(0x43d6776a7db90399), +W64LIT(0x444725d07fba1b6f), +W64LIT(0x6584a0fa2e393d15), +W64LIT(0x3f27dda1121bd892), +W64LIT(0xf6c005e2dab7730f), +W64LIT(0x56cb3ca673b04b44), +W64LIT(0x642128c4f1737278), +W64LIT(0xbf4ae9f135d589ce), +W64LIT(0xb038c54eee99f6ba), +W64LIT(0xf47fe09e9123edd5), +W64LIT(0x75b75cf069a7f3e4), +W64LIT(0xd419ed8a1fea84c2), +W64LIT(0x73838674b4eea47f), +W64LIT(0x498aec13ef62fac1), +W64LIT(0x20660d148ec96917), +W64LIT(0xa48006bc3fdaf10a), +W64LIT(0x2f1421ab55851663), +W64LIT(0x0a5c9b7992dbf958), +W64LIT(0xd1375a4c567d02ee), +W64LIT(0x0000000000000000), +W64LIT(0xc842507d17e6e4f0), +W64LIT(0xf3eeb2249320f523), +W64LIT(0xc9e7d843c8acab9d), +W64LIT(0xff86f3d9dcb25be0), +W64LIT(0xb4b3fab678443ffb), +W64LIT(0xb19d4d7031d3b9d7), +W64LIT(0x79df1d0d26355d27), +W64LIT(0x8eba90d123c86145), +W64LIT(0xaa57a23d3bdcc113), +W64LIT(0xcb583d3f83383547), +W64LIT(0xd871ac7750782a01), +W64LIT(0xe162ab529f2aa508), +W64LIT(0x38b68f1b1018c064), +W64LIT(0x237c60561a17b8a0), +W64LIT(0xa31154063dd9e9fc), +W64LIT(0x713c6308ff7a3aa5), +W64LIT(0x1a6f6773d54537a9), +W64LIT(0x08e37e05d94f6782), +W64LIT(0x357b46d880c021ca), +W64LIT(0x6cc256c1283c15fa), +W64LIT(0xcfd302c715e5fc06), +W64LIT(0xbdf50c8d7e411714), +W64LIT(0x7cf1aacb6fa2db0b), +W64LIT(0x5240035ee56d8205), +W64LIT(0x7b60f8716da1c3fd), +W64LIT(0x01a5883edf4a4f6d), +W64LIT(0xdd5f1bb119efac2d), +W64LIT(0x5474d9da3824d59e), +W64LIT(0x0f722cbfdb4c7f74), +W64LIT(0x17a2aeb0459dd607), +W64LIT(0x37c4a3a4cb54bf10), +W64LIT(0xc21ecb04853d1da8), +W64LIT(0x4273ff54a2f34cf4), +W64LIT(0xdace490b1becb4db), +W64LIT(0x6af68c45f5754261), +W64LIT(0x46f8c0ac342e85b5), +W64LIT(0x854383966e59d770), +W64LIT(0x81c8bc6ef8841e31), +W64LIT(0x3bace25984c611d3), +W64LIT(0x1033fc0a479ecef1), +W64LIT(0x1c5bbdf7080c6032), +W64LIT(0x7412d4ceb6edbc89), +W64LIT(0xa8e8474170485fc9), +W64LIT(0xb8dbbb4b37d69138), +W64LIT(0x079152ba020318f6), +W64LIT(0x72260e4a6ba4eb12), +W64LIT(0x905ec85a60509fad), +W64LIT(0x2dabc4d71e1188b9), +W64LIT(0xd092d27289374d83), +W64LIT(0x610f9f02b8e4f454), +W64LIT(0x02bfe57c4b949eda), +W64LIT(0x95707f9c29c71981), +W64LIT(0x6fd83b83bce2c44d), +W64LIT(0x5d322fe13e21fd71), +W64LIT(0x34decee65f8a6ea7), +W64LIT(0xcd6ce7bb5e7162dc), +W64LIT(0xfb0dcc214a6f92a1), +W64LIT(0x2eb1a9958acf590e), +W64LIT(0xdcfa938fc6a5e340), +W64LIT(0x669ecdb8bae7eca2), +W64LIT(0x151d4bcc0e0948dd), +W64LIT(0xfd3916a59726c53a), +W64LIT(0x581c982777b67b5d), +W64LIT(0x1bcaef4d0a0f78c4), +W64LIT(0xdfe0fecd527b32f7), +W64LIT(0x128c19760c0a502b), +W64LIT(0x84e60ba8b113981d), +W64LIT(0x3c3db0e386c50925), +W64LIT(0x7febc789fb7c0abc), +W64LIT(0x7d5422f5b0e89466), +W64LIT(0xd70380c88b345575), +W64LIT(0xbbc1d609a308408f), +W64LIT(0xe278c6100bf474bf), +W64LIT(0x5e2842a3aaff2cc6), +W64LIT(0x6b53047b2a3f0d0c), +W64LIT(0xf7658ddc05fd3c62), +W64LIT(0x9a025323f28b66f5), +W64LIT(0x8c0575ad685cff9f), +W64LIT(0x76ad31b2fd792253), +W64LIT(0x68496939bee1dcbb), +W64LIT(0x7e4e4fb7243645d1), +W64LIT(0xe44c1c94d6bd2324), +W64LIT(0xbeef61cfea9fc6a3), +W64LIT(0x91fb4064bf1ad0c0), +W64LIT(0x052eb7c64997862c), +W64LIT(0x4a9081517bbc2b76), +W64LIT(0x8f1f18effc822e28), +W64LIT(0x3a096a675b8c5ebe), +W64LIT(0xee1087ed4466da7c), +W64LIT(0x2652d79053803e8c), +W64LIT(0x7099eb36203075c8), +W64LIT(0xc7307cc2ccaa9b84), +W64LIT(0x5c97a7dfe16bb21c), +W64LIT(0x50ffe622aef91cdf), +W64LIT(0x8da0fd93b716b0f2), +W64LIT(0x69ece10761ab93d6), +W64LIT(0x31f07920161de88b), +W64LIT(0x13299148d3401f46), +W64LIT(0x031a6d4294ded1b7), +W64LIT(0xccc96f85813b2db1), +W64LIT(0x14b8c3f2d14307b0), +W64LIT(0x8659eed4fa8706c7), +W64LIT(0xba645e377c420fe2), +W64LIT(0x2920fb2f88cc41f8), +W64LIT(0x87fc66ea25cd49aa), +W64LIT(0x1ee4588b4398fee8), +W64LIT(0xecaf62910ff244a6), +W64LIT(0xf817a163deb14316), +W64LIT(0x45e2adeea0f05402), +W64LIT(0x806d345027ce515c), +W64LIT(0x576eb498acfa0429), +W64LIT(0xa5258e82e090be67), +W64LIT(0x892bc26b21cb79b3), +W64LIT(0x6e7db3bd63a88b20), +W64LIT(0x4e1bbea9ed61e237), +W64LIT(0xadc6f08739dfd9e5), +W64LIT(0x8b9427176a5fe769), +W64LIT(0xa1aeb17a764d7726), +W64LIT(0x4b35096fa4f6641b), +W64LIT(0x22d9e868c55df7cd), +W64LIT(0x55d151e4e76e9af3), +W64LIT(0x966a12debd19c836), +W64LIT(0x0dcdc9c390d8e1ae), +W64LIT(0xf24b3a1a4c6aba4e), +W64LIT(0x24ed32ec1814a056), +W64LIT(0xaf7915fb724b473f), +W64LIT(0x2885731157860e95), +W64LIT(0x9c3689a72fc2316e), +W64LIT(0x475d4892eb64cad8), +W64LIT(0xac6378b9e6959688), +W64LIT(0xa00b3944a907384b), +W64LIT(0xc695f4fc13e0d4e9), +W64LIT(0x3055f11ec957a7e6), +W64LIT(0x6215f2402c3a25e3), +W64LIT(0xde4576f38d317d9a), +W64LIT(0x9344a518f48e4e1a), +W64LIT(0x82d2d12c6c5acf86), +W64LIT(0xefb50fd39b2c9511), +W64LIT(0xe981d5574665c28a), +W64LIT(0x5f8dca9d75b563ab), +W64LIT(0xb60c1fca33d0a121), +W64LIT(0xfe237be703f8148d), +W64LIT(0xd6a608f6547e1a18), +W64LIT(0xb97e3375e89cde55), +W64LIT(0xd388bf301de99c34), +W64LIT(0x5b06f565e368aaea), +W64LIT(0xf0f4df6607fe2494), +W64LIT(0x1607268e9ad7996a), +W64LIT(0xaedc9dc5ad010852), +W64LIT(0xe0c7236c4060ea65), +W64LIT(0xea9bb815d2bb133d), +W64LIT(0x888e4a55fe8136de), +W64LIT(0x5aa37d5b3c22e587), +W64LIT(0xc104a64611e3cc1f), +W64LIT(0x515a6e1c71b353b2), +W64LIT(0xc42a118058744a33), +W64LIT(0x7708b98c22336d3e), +W64LIT(0x2a3a966d1c12904f), +W64LIT(0x8a31af29b515a804), +W64LIT(0xed0aeaafd0b80bcb), +W64LIT(0x2c0e4ce9c15bc7d4), +W64LIT(0x0c6841fd4f92aec3), +W64LIT(0x98bdb65fb91ff82f), +W64LIT(0x1f41d0b59cd2b185), +W64LIT(0xb322a80c7a47270d), +W64LIT(0xe6f3f9e89d29bdfe), +W64LIT(0x7ac5704fb2eb8c90), +W64LIT(0xa94dcf7faf0210a4), +W64LIT(0x787a9533f97f124a), +W64LIT(0xdb6bc135c4a6fbb6), +W64LIT(0x048b3ff896ddc941), +W64LIT(0xe8245d69992f8de7), +W64LIT(0xe3dd4e2ed4be3bd2), +W64LIT(0xcafdb5015c727a2a), +W64LIT(0xb7a997f4ec9aee4c), +W64LIT(0xe75671d64263f293), +W64LIT(0x2b9f1e53c358df22), +W64LIT(0x18d0820f9ed1a973), +W64LIT(0xabf22a03e4968e7e), +W64LIT(0xa2b4dc38e293a691), +W64LIT(0x673b458665ada3cf), +W64LIT(0xf9b2295d01fb0c7b), +W64LIT(0xd22d370ec2a3d359), +W64LIT(0x97cf9ae06253875b), +W64LIT(0x0ed7a48104063019), +W64LIT(0x482f642d3028b5ac), +W64LIT(0xc0a12e78cea98372), +W64LIT(0x4fbe3697322bad5a), +W64LIT(0x19750a31419be61e), +W64LIT(0x41699216362d9d43), +W64LIT(0xd5bc65b4c0a0cbaf), +W64LIT(0xe5e994aa09f76c49), +W64LIT(0xeb3e302b0df15c50), +W64LIT(0x94d5f7a2f68d56ec), +W64LIT(0x53e58b603a27cd68), +W64LIT(0x3d9838dd598f4648), +W64LIT(0x60aa173c67aebb39), +W64LIT(0x1dfe35c9d7462f5f), +W64LIT(0x4ca45bd5a6f57ced), +W64LIT(0xbc5084b3a10b5879), +W64LIT(0xfaa8441f9525ddcc), +W64LIT(0x334f9c5c5d897651), +/* box 4 */ +W64LIT(0xda1687a883adf27e), +W64LIT(0xe35c9378578d9f22), +W64LIT(0x303ca4531637fa40), +W64LIT(0xa088321f74b20375), +W64LIT(0xc9863f3a9acb95e9), +W64LIT(0x5fcf47c57d0b0ed4), +W64LIT(0x4aa211e4e1280b4b), +W64LIT(0xe1a4c9ba871d1289), +W64LIT(0x4926664759f03a4f), +W64LIT(0xadfb36ede3707bca), +W64LIT(0xcf7bd1891f8ef7e1), +W64LIT(0x9735559e8f882792), +W64LIT(0x5932a976f84e6cdc), +W64LIT(0x9dc792bef547818a), +W64LIT(0x06fdeeb385456208), +W64LIT(0x46ad38771ea2cf5b), +W64LIT(0x5eb36aa41543b27b), +W64LIT(0x8b2eb33cd1bcb511), +W64LIT(0x71105ff6e598ebbc), +W64LIT(0x5441ad846f8c1463), +W64LIT(0x4c5fff57646d6943), +W64LIT(0xf3485c49f633c9b1), +W64LIT(0x9cbbbfdf9d0f3d25), +W64LIT(0x22d031a067192178), +W64LIT(0xca0248992213a4ed), +W64LIT(0x19627fb263a9c18f), +W64LIT(0x9330e1efda5dc831), +W64LIT(0x1390b89219666797), +W64LIT(0x2edf18339893e568), +W64LIT(0x6c779435d3e4c590), +W64LIT(0x53c06e568281cac4), +W64LIT(0x6ff3e3966b3cf494), +W64LIT(0xfe3b58bb61f1b10e), +W64LIT(0x77edb14560dd89b4), +W64LIT(0x02f85ac2d0908dab), +W64LIT(0x12ec95f3712edb38), +W64LIT(0x85d9c06dfea6fcaa), +W64LIT(0x90b4964c6285f935), +W64LIT(0xf1b0068b26a3441a), +W64LIT(0x729428555d40dab8), +W64LIT(0x5c4b3066c5d33fd0), +W64LIT(0x5d371d07ad9b837f), +W64LIT(0xa48d866e2167ecd6), +W64LIT(0xb661139d504937ee), +W64LIT(0xa27068dda4228ede), +W64LIT(0xf8c6b608e4b4d306), +W64LIT(0x6bf657e73ee91b37), +W64LIT(0xac871b8c8b38c765), +W64LIT(0x4ea7a595b4fde4e8), +W64LIT(0x0d7304f297c278bf), +W64LIT(0xb71d3efc38018b41), +W64LIT(0xae7f414e5ba84ace), +W64LIT(0xaf036c2f33e0f661), +W64LIT(0x0000000000000000), +W64LIT(0xb89660cc7f537e55), +W64LIT(0xa675dcacf1f7617d), +W64LIT(0x610490c74426bd2f), +W64LIT(0xc18ca2d83094be5a), +W64LIT(0x2adaac42cd460acb), +W64LIT(0x7d1f76651a122fac), +W64LIT(0xc58916a9654151f9), +W64LIT(0xedabe0297897d699), +W64LIT(0x2d5b6f90204bd46c), +W64LIT(0x26d585d132cccedb), +W64LIT(0x9f3fc87c25d70c21), +W64LIT(0xc60d610add9960fd), +W64LIT(0x80a0597dc33bafa6), +W64LIT(0xd0e44088f9625466), +W64LIT(0x1d67cbc3367c2e2c), +W64LIT(0x2c2742f1480368c3), +W64LIT(0x89d6e9fe012c38ba), +W64LIT(0xe9ae54582d42393a), +W64LIT(0x3ecbd702392db3fb), +W64LIT(0xb5e5643ee89106ea), +W64LIT(0xa882affddeed28c6), +W64LIT(0x1ae60811db71f08b), +W64LIT(0x924ccc8eb215749e), +W64LIT(0xfcc30279b1613ca5), +W64LIT(0x825803bf13ab220d), +W64LIT(0xd992f00b3b75c37a), +W64LIT(0xc8fa125bf2832946), +W64LIT(0x35453d432baaa94c), +W64LIT(0xf9ba9b698cfc6fa9), +W64LIT(0x37bd6781fb3a24e7), +W64LIT(0x791ac2144fc7c00f), +W64LIT(0x16e9218224fb349b), +W64LIT(0xdb6aaac9ebe54ed1), +W64LIT(0xd8eedd6a533d7fd5), +W64LIT(0x7c635b04725a9303), +W64LIT(0x553d80e507c4a8cc), +W64LIT(0x9a46516c184a5f2d), +W64LIT(0x14117b40f46bb930), +W64LIT(0x1ee3bc608ea41f28), +W64LIT(0x27a9a8b05a847274), +W64LIT(0x4050d6c49be7ad53), +W64LIT(0x7be298d69f574da4), +W64LIT(0x6a8a7a8656a1a798), +W64LIT(0x4d23d2360c25d5ec), +W64LIT(0x1014cf31a1be5693), +W64LIT(0xb264a7ec059cd84d), +W64LIT(0xea2a23fb959a083e), +W64LIT(0xf0cc2bea4eebf8b5), +W64LIT(0x76919c240895351b), +W64LIT(0x0b8eea4112871ab7), +W64LIT(0x47d1151676ea73f4), +W64LIT(0xbdeff9dc42ce2d59), +W64LIT(0x2ba68123a50eb664), +W64LIT(0x057999103d9d530c), +W64LIT(0xe759270902587081), +W64LIT(0xef53baeba8075b32), +W64LIT(0x4fdb88f4dcb55847), +W64LIT(0x6e8fcef70374483b), +W64LIT(0x1168e250c9f6ea3c), +W64LIT(0x1b9a2570b3394c24), +W64LIT(0x706c72978dd05713), +W64LIT(0x865db7ce467ecdae), +W64LIT(0x52bc4337eac9766b), +W64LIT(0x504419f53a59fbc0), +W64LIT(0x8f2b074d84695ab2), +W64LIT(0x6078bda62c6e0180), +W64LIT(0x43d4a167233f9c57), +W64LIT(0x0ef773512f1a49bb), +W64LIT(0x0c0f2993ff8ac410), +W64LIT(0x4bde3c858960b7e4), +W64LIT(0x66855315a92b6388), +W64LIT(0xd360372b41ba6562), +W64LIT(0x584e84179006d073), +W64LIT(0x9b3a7c0d7002e382), +W64LIT(0xa5f1ab0f492f5079), +W64LIT(0x2822f6801dd68760), +W64LIT(0x445562b5ce3242f0), +W64LIT(0xaa7af53f0e7da56d), +W64LIT(0x3c338dc0e9bd3e50), +W64LIT(0x3bb24e1204b0e0f7), +W64LIT(0xd59dd998c4ff076a), +W64LIT(0x91c8bb2d0acd459a), +W64LIT(0x84a5ed0c96ee4005), +W64LIT(0x33b8d3f0aeefcb44), +W64LIT(0x57c5da27d7542567), +W64LIT(0x32c4fe91c6a777eb), +W64LIT(0x3439102243e215e3), +W64LIT(0xc7714c6bb5d1dc52), +W64LIT(0x3fb7fa6351650f54), +W64LIT(0x87219aaf2e367101), +W64LIT(0xf5b5b2fa7376abb9), +W64LIT(0x412cfba5f3af11fc), +W64LIT(0xdceb691b06e89076), +W64LIT(0xbb12176fc78b4f51), +W64LIT(0x73e8053435086617), +W64LIT(0xe220be193fc5238d), +W64LIT(0xb09cfd2ed50c55e6), +W64LIT(0xb9ea4dad171bc2fa), +W64LIT(0x9e43e51d4d9fb08e), +W64LIT(0x36c14ae093729848), +W64LIT(0xa9fe829cb6a59469), +W64LIT(0x0405b47155d5efa3), +W64LIT(0x0af2c7207acfa618), +W64LIT(0x7e9b01c6a2ca1ea8), +W64LIT(0xdd97447a6ea02cd9), +W64LIT(0x0781c3d2ed0ddea7), +W64LIT(0x7866ef75278f7ca0), +W64LIT(0xd1986de9912ae8c9), +W64LIT(0xcb7e65f84a5b1842), +W64LIT(0xcd838b4bcf1e7a4a), +W64LIT(0xab06d85e663519c2), +W64LIT(0xd4e1f4f9acb7bbc5), +W64LIT(0xfdbf2f18d929800a), +W64LIT(0xf23471289e7b751e), +W64LIT(0xbc93d4bd2a8691f6), +W64LIT(0x3d4fa0a181f582ff), +W64LIT(0xba6e3a0eafc3f3fe), +W64LIT(0x5ab6ded540965dd8), +W64LIT(0xeb560e9afdd2b491), +W64LIT(0x0976b083c217971c), +W64LIT(0xecd7cd4810df6a36), +W64LIT(0x23ac1cc10f519dd7), +W64LIT(0xbe6b8e7ffa161c5d), +W64LIT(0x7fe72ca7ca82a207), +W64LIT(0xc0f08fb958dc02f5), +W64LIT(0x7a9eb5b7f71ff10b), +W64LIT(0xa709f1cd99bfddd2), +W64LIT(0x8dd35d8f54f9d719), +W64LIT(0x8caf70ee3cb16bb6), +W64LIT(0xe4dd50aaba804185), +W64LIT(0x83242ede7be39ea2), +W64LIT(0x98be0baec8dad286), +W64LIT(0x690e0d25ee79969c), +W64LIT(0x95cd0f5c5f18aa39), +W64LIT(0x56b9f746bf1c99c8), +W64LIT(0x7469c6e6d805b8b0), +W64LIT(0x8a529e5db9f409be), +W64LIT(0xe6250a686a10cc2e), +W64LIT(0x2fa33552f0db59c7), +W64LIT(0x42a88c064b7720f8), +W64LIT(0x6d0bb954bbac793f), +W64LIT(0x181e52d30be17d20), +W64LIT(0xbf17a31e925ea0f2), +W64LIT(0x94b1223d37501696), +W64LIT(0xe8d27939450a8595), +W64LIT(0xccffa62aa756c6e5), +W64LIT(0x383639b1bc68d1f3), +W64LIT(0xee2f978ac04fe79d), +W64LIT(0xa30c45bccc6a3271), +W64LIT(0x1f9f9101e6eca387), +W64LIT(0xb1e0d04fbd44e949), +W64LIT(0x242ddf13e25c4370), +W64LIT(0x156d56219c23059f), +W64LIT(0x88aac49f69648415), +W64LIT(0x6280e764fcfe8c2b), +W64LIT(0xdf6f1eb8be30a172), +W64LIT(0xe5a17dcbd2c8fd2a), +W64LIT(0xe0d8e4dbef55ae26), +W64LIT(0x63fcca0594b63084), +W64LIT(0xa1f41f7e1cfabfda), +W64LIT(0x295edbe1759e3bcf), +W64LIT(0x67f97e74c163df27), +W64LIT(0x038477a3b8d83104), +W64LIT(0xde1333d9d6781ddd), +W64LIT(0x3ace63736cf85c58), +W64LIT(0xd619ae3b7c27366e), +W64LIT(0x5bcaf3b428dee177), +W64LIT(0xb3188a8d6dd464e2), +W64LIT(0x1c1be6a25e349283), +W64LIT(0x017c2d616848bcaf), +W64LIT(0x8e572a2cec21e61d), +W64LIT(0xf631c559cbae9abd), +W64LIT(0x81dc741cab731309), +W64LIT(0xff4775da09b90da1), +W64LIT(0xb499495f80d9ba45), +W64LIT(0x0f8b5e304752f514), +W64LIT(0x394a14d0d4206d5c), +W64LIT(0xce07fce877c64b4e), +W64LIT(0xf4c99f9b1b3e1716), +W64LIT(0xc4f53bc80d09ed56), +W64LIT(0xc208d57b884c8f5e), +W64LIT(0x080a9de2aa5f2bb3), +W64LIT(0x314089327e7f46ef), +W64LIT(0xfa3eecca34245ead), +W64LIT(0x20286b62b789acd3), +W64LIT(0x7515eb87b04d041f), +W64LIT(0x513834945211476f), +W64LIT(0x650124b611f3528c), +W64LIT(0x17950ce34cb38834), +W64LIT(0x45294fd4a67afe5f), +W64LIT(0x21544603dfc1107c), +W64LIT(0x485a4b2631b886e0), +W64LIT(0x6872204486312a33), +W64LIT(0x647d09d779bbee23), +W64LIT(0x2551f2728a14ffdf), +W64LIT(0xd765835a146f8ac1), +W64LIT(0xd21c1a4a29f2d9cd), +W64LIT(0x99c226cfa0926e29), +W64LIT(0xfb42c1ab5c6ce202), +W64LIT(0xc374f81ae00433f1), +W64LIT(0x964978ffe7c09b3d), +W64LIT(0xf74de838a3e62612), +/* box 5 */ +W64LIT(0x74b87b36b0592c6a), +W64LIT(0x3d82d75dffb4b81c), +W64LIT(0x8884246715267825), +W64LIT(0xdaf2d8a77ed4e5de), +W64LIT(0xfeb118650e53f9c7), +W64LIT(0xbd2d1aea59226b06), +W64LIT(0x26ce87f6dbabb191), +W64LIT(0x32772ecbeb66bd0a), +W64LIT(0xd4bbf82bc5104c8c), +W64LIT(0x055357720c4e03a1), +W64LIT(0xef5be62a32d0f6fd), +W64LIT(0xbe1c84c45d186aca), +W64LIT(0xacc7e4a565a1643c), +W64LIT(0x8dd7731519687b84), +W64LIT(0x11eafe4f3c830f3a), +W64LIT(0x04ef8e68a358afe5), +W64LIT(0x40ad9ca1534b930d), +W64LIT(0xe44191d4855a5c0e), +W64LIT(0x6001d20b809420f1), +W64LIT(0x73666b70173b8243), +W64LIT(0x372479b9e728beab), +W64LIT(0x45fecbd35f0590ac), +W64LIT(0x7057f55e1301838f), +W64LIT(0xff0dc17fa1455583), +W64LIT(0x0cc467b810e804da), +W64LIT(0xb9c29482fa7ac4e3), +W64LIT(0xa003831d754960e6), +W64LIT(0x8a096353be0ad5ad), +W64LIT(0xdd2cc8e1d9b64bf7), +W64LIT(0xc7dc415052bfee3e), +W64LIT(0x9f0c137421d17572), +W64LIT(0x35a93e8d4c041323), +W64LIT(0x9a5f44062d9f76d3), +W64LIT(0x71eb2c44bc172fcb), +W64LIT(0x0ff5f99614d20516), +W64LIT(0x7789e518b4632da6), +W64LIT(0xc99561dce97b476c), +W64LIT(0x5276fcc06bf29dfb), +W64LIT(0x4a0b32454bd795ba), +W64LIT(0x9274add69e2fddec), +W64LIT(0x4f5865374799961b), +W64LIT(0xb2d8e37c4df06e10), +W64LIT(0xc4eddf7e5685eff2), +W64LIT(0xb3643a66e2e6c254), +W64LIT(0xd50721316a06e0c8), +W64LIT(0x8bb5ba49111c79e9), +W64LIT(0x2bb639546455190f), +W64LIT(0xf8d3d1390627fbaa), +W64LIT(0x38d1802ff3fabbbd), +W64LIT(0xdfa18fd5729ae67f), +W64LIT(0x4ee4bc2de88f3a5f), +W64LIT(0xf72628af12f5febc), +W64LIT(0x0aa6aee4189c06b7), +W64LIT(0x0000000000000000), +W64LIT(0x9eb0ca6e8ec7d936), +W64LIT(0xcb1826e84257eae4), +W64LIT(0x187dce8520250841), +W64LIT(0xc28f16225ef1ed9f), +W64LIT(0xc333cf38f1e741db), +W64LIT(0x4220db95f8673e85), +W64LIT(0xdc9011fb76a0e7b3), +W64LIT(0x105627559395a37e), +W64LIT(0x2f59b73cc70db6ea), +W64LIT(0xe112c6a689145faf), +W64LIT(0x82228a830dba7e92), +W64LIT(0x2ee56e26681b1aae), +W64LIT(0x2a0ae04ecb43b54b), +W64LIT(0x47738ce7f4293d24), +W64LIT(0xa7dd935bd22bcecf), +W64LIT(0xd2d93177cd644ee1), +W64LIT(0xebb4684291885918), +W64LIT(0x0e49208cbbc4a952), +W64LIT(0xa550d46f79076347), +W64LIT(0x411145bbfc5d3f49), +W64LIT(0xe6ccd6e02e76f186), +W64LIT(0x4bb7eb5fe4c139fe), +W64LIT(0x5d8305567f2098ed), +W64LIT(0x95aabd90394d73c5), +W64LIT(0x25ff19d8df91b05d), +W64LIT(0x86cd04ebaee2d177), +W64LIT(0x03319e2e043a01cc), +W64LIT(0x6b1ba5f5371e8a02), +W64LIT(0x76353c021b7581e2), +W64LIT(0x64ee5c6323cc8f14), +W64LIT(0x5c3fdc4cd03634a9), +W64LIT(0x6996e2c19c32278a), +W64LIT(0x8938fd7dba30d461), +W64LIT(0x7b4d82a0a48b297c), +W64LIT(0xbfa05ddef20ec68e), +W64LIT(0x8ee6ed3b1d527a48), +W64LIT(0x61bd0b112f828cb5), +W64LIT(0x66631b5788e0229c), +W64LIT(0x55a8ec86cc9033d2), +W64LIT(0x1c9240ed837da7a4), +W64LIT(0x150570279fdba0df), +W64LIT(0x53ca25dac4e431bf), +W64LIT(0xd636bf1f6e3ce104), +W64LIT(0xcaa4fff2ed4146a0), +W64LIT(0x787c1c8ea0b128b0), +W64LIT(0xad7b3dbfcab7c878), +W64LIT(0xfc3c5f51a57f544f), +W64LIT(0xb78bb40e41be6db1), +W64LIT(0x8c6baa0fb67ed7c0), +W64LIT(0xce4b719a4e19e945), +W64LIT(0xf96f0823a93157ee), +W64LIT(0x7d2f4bfcacff2b11), +W64LIT(0x3eb34973fb8eb9d0), +W64LIT(0xe39f81922238f227), +W64LIT(0x239dd084d7e5b230), +W64LIT(0x1fa3dec38747a668), +W64LIT(0xc5510664f99343b6), +W64LIT(0xc829b8c6466deb28), +W64LIT(0x85fc9ac5aad8d0bb), +W64LIT(0xb6376d14eea8c1f5), +W64LIT(0x9d8154408afdd8fa), +W64LIT(0x3be01e01f7c0ba71), +W64LIT(0x628c953f2bb88d79), +W64LIT(0x6d796ca93f6a886f), +W64LIT(0xfa5e960dad0b5622), +W64LIT(0xe5fd48ce2a4cf04a), +W64LIT(0xe7700ffa81605dc2), +W64LIT(0x2dd4f0086c211b62), +W64LIT(0x2221099e78f31e74), +W64LIT(0xdb4e01bdd1c2499a), +W64LIT(0xf417b68116cfff70), +W64LIT(0xb506f33aea92c039), +W64LIT(0x514762ee6fc89c37), +W64LIT(0x9c3d8d5a25eb74be), +W64LIT(0x396d59355cec17f9), +W64LIT(0xccc636aee53544cd), +W64LIT(0x0b1a77feb78aaaf3), +W64LIT(0xe9392f763aa4f490), +W64LIT(0xaaa52df96dd56651), +W64LIT(0x46cf55fd5b3f9160), +W64LIT(0xa4ec0d75d611cf03), +W64LIT(0xaff67a8b619b65f0), +W64LIT(0x3415e797e312bf67), +W64LIT(0x7af15bba0b9d8538), +W64LIT(0x811314ad09807f5e), +W64LIT(0x8771ddf101f47d33), +W64LIT(0x969b23be3d777209), +W64LIT(0xd365e86d6272e2a5), +W64LIT(0x58d05224736e9b4c), +W64LIT(0xc660984afda9427a), +W64LIT(0x5414359c63869f96), +W64LIT(0xe885f66c95b258d4), +W64LIT(0x655285798cda2350), +W64LIT(0x6cc5b5b3907c242b), +W64LIT(0x6ff42b9d944625e7), +W64LIT(0xc0025116f5dd4017), +W64LIT(0xa28ec429de65cd6e), +W64LIT(0x63304c2584ae213d), +W64LIT(0x7fa20cc807d38699), +W64LIT(0x996eda2829a5771f), +W64LIT(0x1b4c50ab241f098d), +W64LIT(0x1e1f07d928510a2c), +W64LIT(0x33cbf7d14470114e), +W64LIT(0xb055a448e6dcc398), +W64LIT(0x98d2033286b3db5b), +W64LIT(0xec6a780436eaf731), +W64LIT(0xa1bf5a07da5fcca2), +W64LIT(0xbaf30aacfe40c52f), +W64LIT(0xf144e1f31a81fcd1), +W64LIT(0xe0ae1fbc2602f3eb), +W64LIT(0x14b9a93d30cd0c9b), +W64LIT(0x596c8b3edc783708), +W64LIT(0x682a3bdb33248bce), +W64LIT(0xb87e4d98556c68a7), +W64LIT(0x80afcdb7a696d31a), +W64LIT(0x5725abb267bc9e5a), +W64LIT(0x914533f89a15dc20), +W64LIT(0x5eb29b787b1a9921), +W64LIT(0x01bcd91aaf16ac44), +W64LIT(0xc1be880c5acbec53), +W64LIT(0xedd6a11e99fc5b75), +W64LIT(0x028d4734ab2cad88), +W64LIT(0x8f5a3421b244d60c), +W64LIT(0x4dd52203ecb53b93), +W64LIT(0x3f0f906954981594), +W64LIT(0xae4aa391ce8dc9b4), +W64LIT(0x3698a0a3483e12ef), +W64LIT(0xf5ab6f9bb9d95334), +W64LIT(0x082be9d0b3b0ab3f), +W64LIT(0xd1e8af59c95e4f2d), +W64LIT(0xd87f9f93d5f84856), +W64LIT(0x6e48f2873b5089a3), +W64LIT(0x2443c0c270871c19), +W64LIT(0xb1e97d5249ca6fdc), +W64LIT(0x7c9392e603e98755), +W64LIT(0x839e5399a2acd2d6), +W64LIT(0x19c1179f8f33a405), +W64LIT(0xde1d56cfdd8c4a3b), +W64LIT(0x20ac4eaad3dfb3fc), +W64LIT(0x1af089b18b09a5c9), +W64LIT(0x3a5cc71b58d61635), +W64LIT(0x444212c9f0133ce8), +W64LIT(0x72dab26ab82d2e07), +W64LIT(0x4c69fb1943a397d7), +W64LIT(0xf3c9a6c7b1ad5159), +W64LIT(0x1d2e99f72c6b0be0), +W64LIT(0xb4ba2a2045846c7d), +W64LIT(0xe22358888d2e5e63), +W64LIT(0x2887a77a606f18c3), +W64LIT(0xa8286acdc6f9cbd9), +W64LIT(0x5f0e4262d40c3565), +W64LIT(0xeee73f309dc65ab9), +W64LIT(0x9be39d1c8289da97), +W64LIT(0x1634ee099be1a113), +W64LIT(0xea08b1583e9ef55c), +W64LIT(0x9727faa49261de4d), +W64LIT(0x2c682912c337b726), +W64LIT(0xcff7a880e10f4501), +W64LIT(0x1788371334f70d57), +W64LIT(0x27725eec74bd1dd5), +W64LIT(0x3146b0e5ef5cbcc6), +W64LIT(0x099730ca1ca6077b), +W64LIT(0xf2757fdd1ebbfd1d), +W64LIT(0x6aa77cef98082646), +W64LIT(0xbb4fd3b65156696b), +W64LIT(0x569972a8c8aa321e), +W64LIT(0xa3321d337173612a), +W64LIT(0x50fbbbf4c0de3073), +W64LIT(0x5a5d1510d84236c4), +W64LIT(0xfd80864b0a69f80b), +W64LIT(0x07de1046a762ae29), +W64LIT(0xa6614a417d3d628b), +W64LIT(0xd78a6605c12a4d40), +W64LIT(0x67dfc24d27f68ed8), +W64LIT(0xbc91c3f0f634c742), +W64LIT(0xd05476436648e369), +W64LIT(0x493aac6b4fed9476), +W64LIT(0x12db606138b90ef6), +W64LIT(0xa994b3d769ef679d), +W64LIT(0x211097b07cc91fb8), +W64LIT(0x30fa69ff404a1082), +W64LIT(0x3c3e0e4750a21458), +W64LIT(0x7504a22c1f4f802e), +W64LIT(0x844043df05ce7cff), +W64LIT(0xf0f838e9b5975095), +W64LIT(0x7e1ed5d2a8c52add), +W64LIT(0x90f9eae235037064), +W64LIT(0x0662c95c0874026d), +W64LIT(0x9416648a965bdf81), +W64LIT(0xf69af1b5bde352f8), +W64LIT(0x0d78bea2bffea89e), +W64LIT(0x293b7e60cf79b487), +W64LIT(0xd9c346897aeee412), +W64LIT(0xfbe24f17021dfa66), +W64LIT(0x1367b97b97afa2b2), +W64LIT(0xab19f4e3c2c3ca15), +W64LIT(0x48867571e0fb3832), +W64LIT(0x93c874cc313971a8), +W64LIT(0x79c0c5940fa784f4), +W64LIT(0xcd7aefb44a23e889), +W64LIT(0x439c028f577192c1), +W64LIT(0x5be1cc0a77549a80), +/* box 6 */ +W64LIT(0x714d28d778656928), +W64LIT(0xc88a7c6b84f64f7c), +W64LIT(0xec43cac5ab89aaca), +W64LIT(0x777fa38110dc16a3), +W64LIT(0x0f7d5c87e4213b5c), +W64LIT(0x73f051e5f3a1ef51), +W64LIT(0xea714193c330d541), +W64LIT(0x95e5f3dae016c4f3), +W64LIT(0x63d3738095a0e173), +W64LIT(0x9825d66f8ff379d6), +W64LIT(0xe8cc38a148f45338), +W64LIT(0xa840b0c025f06bb0), +W64LIT(0x944135c35f748735), +W64LIT(0x74661caa247ad31c), +W64LIT(0xe7b16426acd56864), +W64LIT(0xd1e689df6e6f0589), +W64LIT(0xa73dec47c1d150ec), +W64LIT(0x64453ecf427bdd3e), +W64LIT(0x0ed99a9e5b43789a), +W64LIT(0x7b1b402dc05be840), +W64LIT(0x0dc025b56fe5bd25), +W64LIT(0x3f183a284e22293a), +W64LIT(0xa0aba108160a6ca1), +W64LIT(0x46be033705bd4703), +W64LIT(0x86df6e94b2b10f6e), +W64LIT(0xa216d83a9dceead8), +W64LIT(0x129e5b57edc5885b), +W64LIT(0x7e3074509c445274), +W64LIT(0x7d29cb7ba8e297cb), +W64LIT(0x1611a9330eb871a9), +W64LIT(0x486799a95efe3f99), +W64LIT(0x9fb39b205828459b), +W64LIT(0xd0424fc6d10d464f), +W64LIT(0xe968feb8f79610fe), +W64LIT(0x5d6f8fb164e08b8f), +W64LIT(0xaafdc9f2ae34edc9), +W64LIT(0x02bd79328bc48679), +W64LIT(0x9b3c6944bb55bc69), +W64LIT(0x6277b5992ac2a2b5), +W64LIT(0x877ba88d0dd34ca8), +W64LIT(0xfa5263f6a531db63), +W64LIT(0x2e9fde54974164de), +W64LIT(0xcda14816d8e9f548), +W64LIT(0x675c81e476dd1881), +W64LIT(0x2a102c30743c9d2c), +W64LIT(0x37f32be07dd82e2b), +W64LIT(0x256d70b7901da670), +W64LIT(0x4ce86bcdbd83c66b), +W64LIT(0x50afaa040b0536aa), +W64LIT(0xef5a75ee9f2f6f75), +W64LIT(0xb3913c4644ada73c), +W64LIT(0x1187e47cd9634de4), +W64LIT(0xc54a59deeb13f259), +W64LIT(0x0000000000000000), +W64LIT(0x01a4c619bf6243c6), +W64LIT(0x90cec7a7bc097ec7), +W64LIT(0xf94bdcdd91971edc), +W64LIT(0x8e347f5c814b087f), +W64LIT(0xc7f720ec60d77420), +W64LIT(0x354e52d2f61ca852), +W64LIT(0x34ea94cb497eeb94), +W64LIT(0xae723b964d49143b), +W64LIT(0xf48bf968fe72a3f9), +W64LIT(0xfc60e8a0cd88a4e8), +W64LIT(0x2909931b409a5893), +W64LIT(0xbd48a6d81feedfa6), +W64LIT(0x6cae2f077181da2f), +W64LIT(0xad6b84bd79efd184), +W64LIT(0x18c833ad55fb0933), +W64LIT(0x204644cacc021c44), +W64LIT(0x392ab17e269b56b1), +W64LIT(0x14acd001857cf7d0), +W64LIT(0x8abb8d386236f18d), +W64LIT(0xeefeb3f7204d2cb3), +W64LIT(0xf636805a75b62580), +W64LIT(0x2bb4ea29cb5edeea), +W64LIT(0xc653e6f5dfb537e6), +W64LIT(0x8d2dc077b5edcdc0), +W64LIT(0x31c1a0b6156151a0), +W64LIT(0xf8ef1ac42ef55d1a), +W64LIT(0xdbb0e125d65184e1), +W64LIT(0x82509cf051ccf69c), +W64LIT(0xe33e96424fa89196), +W64LIT(0xdf3f1341352c7d13), +W64LIT(0x8f90b9453e294bb9), +W64LIT(0x1023226566010e22), +W64LIT(0xa58095754a15d695), +W64LIT(0x2c22a7661c85e2a7), +W64LIT(0xe183ef70c46c17ef), +W64LIT(0xafd6fd8ff22b57fd), +W64LIT(0x471ac52ebadf04c5), +W64LIT(0x4d4cadd402e185ad), +W64LIT(0x916a01be036b3d01), +W64LIT(0x28ad5502fff81b55), +W64LIT(0x3657edf9c2ba6ded), +W64LIT(0xd2ff36f45ac9c036), +W64LIT(0xf1a0cd15a26d19cd), +W64LIT(0xd90d98175d950298), +W64LIT(0xf7924643cad46646), +W64LIT(0xdd826a73bee8fb6a), +W64LIT(0x9d0ee212d3ecc3e2), +W64LIT(0xb6ba083b18b21d08), +W64LIT(0x3da5431ac5e6af43), +W64LIT(0x08eb11c833fa0711), +W64LIT(0x052b347d5c1fba34), +W64LIT(0x6fb7902c45271f90), +W64LIT(0x133a9d4e52a7cb9d), +W64LIT(0x6e135635fa455c56), +W64LIT(0x725497fc4cc3ac97), +W64LIT(0xf31db42729a99fb4), +W64LIT(0x846217a639758917), +W64LIT(0x4b7e26826a58fa26), +W64LIT(0x235ffbe1f8a4d9fb), +W64LIT(0xff79578bf92e6157), +W64LIT(0xda14273c6933c727), +W64LIT(0x8b1f4b21dd54b24b), +W64LIT(0x9caa240b6c8e8024), +W64LIT(0xc1c5abba086e0bab), +W64LIT(0xde9bd5588a4e3ed5), +W64LIT(0x2d86617fa3e7a161), +W64LIT(0xbff5dfea942a59df), +W64LIT(0x66f847fdc9bf5b47), +W64LIT(0x3b97c84cad5fd0c8), +W64LIT(0x3ebcfc31f1406afc), +W64LIT(0xca3705590f32c905), +W64LIT(0x24c9b6ae2f7fe5b6), +W64LIT(0x408c88616d043888), +W64LIT(0x93d7788c88afbb78), +W64LIT(0x196cf5b4ea994af5), +W64LIT(0x9a98af5d0437ffaf), +W64LIT(0x8c89066e0a8f8e06), +W64LIT(0xab590feb1156ae0f), +W64LIT(0xd7d4028906d67a02), +W64LIT(0xe4a8db0d9873addb), +W64LIT(0xc378d28883aa8dd2), +W64LIT(0x4ff1d4e6892503d4), +W64LIT(0xd670c490b9b439c4), +W64LIT(0x65e1f8d6fd199ef8), +W64LIT(0xf2b9723e96cbdc72), +W64LIT(0xb12c4574cf692145), +W64LIT(0x569d215263bc4921), +W64LIT(0x69851b7a2d9e601b), +W64LIT(0x5e76309a50464e30), +W64LIT(0x5fd2f683ef240df6), +W64LIT(0xd8a95e0ee2f7415e), +W64LIT(0xe29a505bf0cad250), +W64LIT(0x96fc4cf1d4b0014c), +W64LIT(0x8806f40ae9f277f4), +W64LIT(0x53b6152f3fa3f315), +W64LIT(0x1c47c1c9b686f0c1), +W64LIT(0x80ede5c2da0870e5), +W64LIT(0xd5697bbb8d12fc7b), +W64LIT(0xfdc42eb972eae72e), +W64LIT(0x0bf2aee3075cc2ae), +W64LIT(0x22fb3df847c69a3d), +W64LIT(0xbadeeb97c835e3eb), +W64LIT(0xdc26ac6a018ab8ac), +W64LIT(0xbcec60c1a08c9c60), +W64LIT(0x4231f153e6c0bef1), +W64LIT(0x337cd9849ea5d7d9), +W64LIT(0x5b5d04e70c59f404), +W64LIT(0x79a6391f4b9f6e39), +W64LIT(0x5212d33680c1b0d3), +W64LIT(0xb5a3b7102c14d8b7), +W64LIT(0x7f94b249232611b2), +W64LIT(0x17b56f2ab1da326f), +W64LIT(0x59e07dd5879d727d), +W64LIT(0xebd5878a7c529687), +W64LIT(0xbb7a2d8e7757a02d), +W64LIT(0x0319bf2b34a6c5bf), +W64LIT(0x5ccb49a8db82c849), +W64LIT(0x1de307d009e4b307), +W64LIT(0x49c35fb0e19c7c5f), +W64LIT(0x55849e79571a8c9e), +W64LIT(0x7abf86347f39ab86), +W64LIT(0x9273be9537cdf8be), +W64LIT(0xe615a23f13b72ba2), +W64LIT(0x6821dd6392fc23dd), +W64LIT(0x5af9c2feb33bb7c2), +W64LIT(0x06328b5668b97f8b), +W64LIT(0x44037a058e79c17a), +W64LIT(0x83f45ae9eeaeb55a), +W64LIT(0x5739e74bdcde0ae7), +W64LIT(0xfbf6a5ef1a5398a5), +W64LIT(0xe50c1d142711ee1d), +W64LIT(0x1a754a9fde3f8f4a), +W64LIT(0x7802ff06f4fd2dff), +W64LIT(0xf52f3f714110e03f), +W64LIT(0x2674cf9ca4bb63cf), +W64LIT(0x60caccaba10624cc), +W64LIT(0xb088836d700b6283), +W64LIT(0xa6992a5e7eb3132a), +W64LIT(0xa9e476d99a922876), +W64LIT(0x6b386248a65ae662), +W64LIT(0xc2dc14913cc8ce14), +W64LIT(0x76db6598afbe5565), +W64LIT(0x32d81f9d21c7941f), +W64LIT(0x21e282d373605f82), +W64LIT(0xc0616da3b70c486d), +W64LIT(0x616e0ab21e64670a), +W64LIT(0x6d0ae91ecee399e9), +W64LIT(0x27d009851bd92009), +W64LIT(0xfedd9192464c2291), +W64LIT(0x45a7bc1c311b82bc), +W64LIT(0x54205860e878cf58), +W64LIT(0xa10f6711a9682f67), +W64LIT(0x9981107630913a10), +W64LIT(0xede70cdc14ebe90c), +W64LIT(0x70e9eecec7072aee), +W64LIT(0x1f5e7ee28220357e), +W64LIT(0x2f3b184d28232718), +W64LIT(0x41284e78d2667b4e), +W64LIT(0xa424536cf5779553), +W64LIT(0xa3b21e2322aca91e), +W64LIT(0x4e5512ff36474012), +W64LIT(0x1efab8fb3d4276b8), +W64LIT(0x89a2321356903432), +W64LIT(0xcb93c340b0508ac3), +W64LIT(0x306566afaa031266), +W64LIT(0x4adae09bd53ab9e0), +W64LIT(0xc92eba723b940cba), +W64LIT(0x094fd7d18c9844d7), +W64LIT(0xcc058e0f678bb68e), +W64LIT(0xd4cdbda23270bfbd), +W64LIT(0x0a5668fab83e8168), +W64LIT(0x510b6c1db467756c), +W64LIT(0xb86392a543f16592), +W64LIT(0x048ff264e37df9f2), +W64LIT(0x3a330e55123d930e), +W64LIT(0xb235fa5ffbcfe4fa), +W64LIT(0xb9c754bcfc932654), +W64LIT(0x3c0185037a84ec85), +W64LIT(0x0c64e3acd087fee3), +W64LIT(0xe02729697b0e5429), +W64LIT(0x07964d4fd7db3c4d), +W64LIT(0x814923db656a3323), +W64LIT(0x388e776799f91577), +W64LIT(0x6a9ca4511938a5a4), +W64LIT(0x1bd18c86615dcc8c), +W64LIT(0xb407710993769b71), +W64LIT(0x150816183a1eb416), +W64LIT(0x4395374a59a2fd37), +W64LIT(0xc4ee9fc75471b19f), +W64LIT(0x5844bbcc38ff31bb), +W64LIT(0xcf1c3124532d7331), +W64LIT(0xb71ece22a7d05ece), +W64LIT(0xaccf42a4c68d9242), +W64LIT(0x97588ae86bd2428a), +W64LIT(0x75c2dab39b1890da), +W64LIT(0x9e175d39e74a065d), +W64LIT(0xf0040b0c1d0f5a0b), +W64LIT(0xceb8f73dec4f30f7), +W64LIT(0xbe5119f32b481a19), +W64LIT(0xd35bf0ede5ab83f0), +W64LIT(0x7c8d0d621780d40d), +W64LIT(0x85c6d1bf8617cad1), +/* box 7 */ +W64LIT(0xb1c742127b66f2a4), +W64LIT(0xce916098d7a59fc1), +W64LIT(0xc312ef8e2406fa70), +W64LIT(0x956c7dced81403d5), +W64LIT(0x5a0c9b2318dd9520), +W64LIT(0xad0d57f51a480e8b), +W64LIT(0xe7b9d05287740b01), +W64LIT(0x0217f9ea2ed81268), +W64LIT(0x4d7cff19f8cd3a06), +W64LIT(0x44d1772e572b7b67), +W64LIT(0xfb73c5b5e65af72e), +W64LIT(0x91427aef84512705), +W64LIT(0x0c720963e4cf6c85), +W64LIT(0x87c398a0732d8117), +W64LIT(0xa17f5e96fe87620e), +W64LIT(0x50476c8b8e8fcf1d), +W64LIT(0xcb4ee1cc9c8cb225), +W64LIT(0x67b2304c91a8b59a), +W64LIT(0x54696baad2caebcd), +W64LIT(0xddcf03836bf01437), +W64LIT(0x46c68ec479f3690f), +W64LIT(0x8f9f96e2cba7c942), +W64LIT(0xe1802e99f5e93db9), +W64LIT(0x4e9a8086c179215a), +W64LIT(0xf0c9b4686764a427), +W64LIT(0xfd4a3b7e94c7c196), +W64LIT(0xfcbbbd0b83abc8a2), +W64LIT(0xebcbd93163bb6784), +W64LIT(0xf9643c5fc882e546), +W64LIT(0xc4da973041f7c5fc), +W64LIT(0x1af3eb2c13b3ca97), +W64LIT(0x6e1fb87b3e4ef4fb), +W64LIT(0x5e229c024498b1f0), +W64LIT(0xf516353c2c4d89c3), +W64LIT(0xcc869972f97d8da9), +W64LIT(0x8d886f08e57fdb2a), +W64LIT(0x1cca15e7612efc2f), +W64LIT(0x567e9240fc12f9a5), +W64LIT(0x43190f9032da44eb), +W64LIT(0xfeac44e1ad73daca), +W64LIT(0x07c878be65f13f8c), +W64LIT(0x618bce87e3358322), +W64LIT(0xf895ba2adfeeec72), +W64LIT(0x751dd5223a913758), +W64LIT(0x59eae4bc21698e7c), +W64LIT(0xff5dc294ba1fd3fe), +W64LIT(0x03e67f9f39b41b5c), +W64LIT(0x2292c117d1efc7c9), +W64LIT(0x8a4017b6808ee4a6), +W64LIT(0xd1bd0ae08f3f78b2), +W64LIT(0x135e631bbc558bf6), +W64LIT(0xee14586528924a60), +W64LIT(0x8857ee5cae56f6ce), +W64LIT(0x0000000000000000), +W64LIT(0x0e65f089ca177eed), +W64LIT(0x34132358269361db), +W64LIT(0x15679dd0cec8bd4e), +W64LIT(0x800be01e16dcbe9b), +W64LIT(0x949dfbbbcf780ae1), +W64LIT(0xe397d773db312fd1), +W64LIT(0xedf227fa1126513c), +W64LIT(0xb5e945332723d674), +W64LIT(0x53a11314b73bd441), +W64LIT(0x23634762c683cefd), +W64LIT(0x4b4501d28a500cbe), +W64LIT(0x473708b16e9f603b), +W64LIT(0x1770643ae010af26), +W64LIT(0xa746a05d8c1a54b6), +W64LIT(0x90b3fc9a933d2e31), +W64LIT(0x35e2a52d31ff68ef), +W64LIT(0xab34a93e68d53833), +W64LIT(0xd81082d720d939d3), +W64LIT(0xb86aca25d480b3c5), +W64LIT(0xdfd8fa694528065f), +W64LIT(0x4f6b06f3d615286e), +W64LIT(0x578f1435eb7ef091), +W64LIT(0x9af80b32056f740c), +W64LIT(0x92a40570bde53c59), +W64LIT(0xdbf6fd48196d228f), +W64LIT(0x1b026d5904dfc3a3), +W64LIT(0x3c4f2d1a9e19298e), +W64LIT(0xc8a89e53a538a979), +W64LIT(0x991e74ad3cdb6f50), +W64LIT(0x042e07215c4524d0), +W64LIT(0x8e6e1097dccbc076), +W64LIT(0xe071a8ece285348d), +W64LIT(0xd784f42bfda24e0a), +W64LIT(0x7d41db60821b7f0d), +W64LIT(0x85d4614a5df5937f), +W64LIT(0xbb8cb5baed34a899), +W64LIT(0x40ff700f0b6e5fb7), +W64LIT(0x2cf7319e1bf8b924), +W64LIT(0x3a76d3d1ec841f36), +W64LIT(0x4520f15b40477253), +W64LIT(0xf138321d7008ad13), +W64LIT(0x42e889e525b64ddf), +W64LIT(0x65a5c9a6bf70a7f2), +W64LIT(0x208538fdff37d5a1), +W64LIT(0x410ef67a1c025683), +W64LIT(0x18e412c63d6bd8ff), +W64LIT(0x72d5ad9c5f6008d4), +W64LIT(0x255ab9a9b41ef845), +W64LIT(0x93558305aa89356d), +W64LIT(0x70c2547671b81abc), +W64LIT(0x3604dab2084b73b3), +W64LIT(0x05df81544b292de4), +W64LIT(0xf2de4d8249bcb64f), +W64LIT(0x0bba71dd813e5309), +W64LIT(0xa368a77cd05f7066), +W64LIT(0x796fdc41de5e5bdd), +W64LIT(0xec03a18f064a5808), +W64LIT(0x085c0e42b88a4855), +W64LIT(0x274d40439ac6ea2d), +W64LIT(0x31cca20c6dba4c3f), +W64LIT(0x322add93540e5763), +W64LIT(0xb60f3aac1e97cd28), +W64LIT(0x7cb05d1595777639), +W64LIT(0xb036c4676c0afb90), +W64LIT(0x0a4bf7a896525a3d), +W64LIT(0x73242be9480c01e0), +W64LIT(0x5bfd1d560fb19c14), +W64LIT(0x7b7825abf08649b5), +W64LIT(0xb7febcd909fbc41c), +W64LIT(0x81fa666b01b0b7af), +W64LIT(0xd25b757fb68b63ee), +W64LIT(0x0d838f16f3a365b1), +W64LIT(0x6a31bf5a620bd02b), +W64LIT(0x26bcc6368daae319), +W64LIT(0x9ed60c13592a50dc), +W64LIT(0x581b62c936058748), +W64LIT(0x9cc1f5f977f242b4), +W64LIT(0x83ed9f812f68a5c7), +W64LIT(0x74ec53572dfd3e6c), +W64LIT(0xb3d0bbf855bee0cc), +W64LIT(0xacfcd1800d2407bf), +W64LIT(0x303d24797ad6450b), +W64LIT(0x7a89a3dee7ea4081), +W64LIT(0x69d7c0c55bbfcb77), +W64LIT(0x770a2cc814492530), +W64LIT(0x0f9476fcdd7b77d9), +W64LIT(0xaeeb286a23fc15d7), +W64LIT(0x2174be88e85bdc95), +W64LIT(0xde297c1c52440f6b), +W64LIT(0xd04c8c9598537186), +W64LIT(0x2ee0c8743520ab4c), +W64LIT(0x977b8424f6cc11bd), +W64LIT(0x10b81c8485e190aa), +W64LIT(0xa4a0dfc2b5ae4fea), +W64LIT(0x98eff2d82bb76664), +W64LIT(0xa8d2d6a15161236f), +W64LIT(0xd4628bb4c4165556), +W64LIT(0x682646b04cd3c243), +W64LIT(0x2d06b7eb0c94b010), +W64LIT(0x626db118da81987e), +W64LIT(0x2928b0ca50d194c0), +W64LIT(0x6df9c7e407faefa7), +W64LIT(0x1681e24ff77ca612), +W64LIT(0x4952f838a4881ed6), +W64LIT(0x76fbaabd03252c04), +W64LIT(0xc73ce8af7843dea0), +W64LIT(0xe82da6ae5a0f7cd8), +W64LIT(0xc10516640adee818), +W64LIT(0x968a0251e1a01889), +W64LIT(0x37f55cc71f277a87), +W64LIT(0xe5ae29b8a9ac1969), +W64LIT(0xcabf67b98be0bb11), +W64LIT(0xf4e7b3493b2180f7), +W64LIT(0xe9dc20db4d6375ec), +W64LIT(0x639c376dcded914a), +W64LIT(0x12afe56eab3982c2), +W64LIT(0xc2e369fb336af344), +W64LIT(0xa6b726289b765d82), +W64LIT(0x14961ba5d9a4b47a), +W64LIT(0xbc44cd0488c59715), +W64LIT(0xd3aaf30aa1e76ada), +W64LIT(0x28d936bf47bd9df4), +W64LIT(0xaf1aae1f34901ce3), +W64LIT(0x2f114e01224ca278), +W64LIT(0xe648562790180235), +W64LIT(0x24ab3fdca372f171), +W64LIT(0x52509561a057dd75), +W64LIT(0xc6cd6eda6f2fd794), +W64LIT(0xa08ed8e3e9eb6b3a), +W64LIT(0x09ad8837afe64161), +W64LIT(0xbdb54b719fa99e21), +W64LIT(0x8c79e97df213d21e), +W64LIT(0xcf60e6edc0c996f5), +W64LIT(0x5dc4e39d7d2caaac), +W64LIT(0x11499af1928d999e), +W64LIT(0x5fd31a7753f4b8c4), +W64LIT(0x01f18675176c0934), +W64LIT(0xc52b1145569bccc8), +W64LIT(0x9f278a664e4659e8), +W64LIT(0x3dbeab6f897520ba), +W64LIT(0xa2992109c7337952), +W64LIT(0x9b098d4712037d38), +W64LIT(0xc9591826b254a04d), +W64LIT(0x3b8755a4fbe81602), +W64LIT(0xbe5334eea61d857d), +W64LIT(0x51b6eafe99e3c629), +W64LIT(0x191594b32a07d1cb), +W64LIT(0x1f2c6a78589ae773), +W64LIT(0x3fa95285a7ad32d2), +W64LIT(0x5c3565e86a40a398), +W64LIT(0xb2213d8d42d2e9f8), +W64LIT(0xefe5de103ffe4354), +W64LIT(0x4ab487a79d3c058a), +W64LIT(0xcd771f07ee11849d), +W64LIT(0xbfa2b29bb1718c49), +W64LIT(0xba7d33cffa58a1ad), +W64LIT(0x6fee3e0e2922fdcf), +W64LIT(0x64544fd3a81caec6), +W64LIT(0xd9e104a237b530e7), +W64LIT(0xf32fcbf75ed0bf7b), +W64LIT(0x3e58d4f0b0c13be6), +W64LIT(0xb418c346304fdf40), +W64LIT(0xaac52f4b7fb93107), +W64LIT(0xdc3e85f67c9c1d03), +W64LIT(0xd5930dc1d37a5c62), +W64LIT(0x0639fecb729d36b8), +W64LIT(0xc0f490111db2e12c), +W64LIT(0x7ea7a4ffbbaf6451), +W64LIT(0xf6f04aa315f9929f), +W64LIT(0x6643b63986c4bcae), +W64LIT(0x6c0841911096e693), +W64LIT(0x8425e73f4a999a4b), +W64LIT(0x7133d20366d41388), +W64LIT(0x38612a3bc25c0d5e), +W64LIT(0xb99b4c50c3ecbaf1), +W64LIT(0x1d3b93927642f51b), +W64LIT(0x7f56228aacc36d65), +W64LIT(0x9d30738c609e4b80), +W64LIT(0x48a37e4db3e417e2), +W64LIT(0x8bb191c397e2ed92), +W64LIT(0x2acecf5569658f9c), +W64LIT(0xda077b3d0e012bbb), +W64LIT(0xa55159b7a2c246de), +W64LIT(0x33db5be643625e57), +W64LIT(0x821c19f43804acf3), +W64LIT(0x3990ac4ed530046a), +W64LIT(0xd675725eeace473e), +W64LIT(0x789e5a34c93252e9), +W64LIT(0x86321ed564418823), +W64LIT(0xfa8243c0f136fe1a), +W64LIT(0xe45fafcdbec0105d), +W64LIT(0x2b3f49207e0986a8), +W64LIT(0xa92350d4460d2a5b), +W64LIT(0x1eddec0d4ff6ee47), +W64LIT(0x89a66829b93afffa), +W64LIT(0x607a48f2f4598a16), +W64LIT(0x6bc0392f7567d91f), +W64LIT(0xea3a5f4474d76eb0), +W64LIT(0x5598eddfc5a6e2f9), +W64LIT(0x4c8d796cefa13332), +W64LIT(0xf701ccd602959bab), +W64LIT(0xe2665106cc5d26e5), +}; + +const word64 SHARK::Dec::cbox[8][256] = { +/* box 0 */ +W64LIT(0xe6126af05e55aff3), +W64LIT(0x4b6c893f310b0835), +W64LIT(0xaa4c0e84ebfc8d57), +W64LIT(0xfb9b5c7bf3b3090d), +W64LIT(0x4508a6a9ccba5ce2), +W64LIT(0xe5d1d2064dc6bde9), +W64LIT(0x348343755288edde), +W64LIT(0xb684505de46b250c), +W64LIT(0xa8cede205a1e91e8), +W64LIT(0x40b89b46f9fa6acc), +W64LIT(0x8ee1ec1afab080ba), +W64LIT(0xde77d6b7408e0a45), +W64LIT(0x9a3e184c2e455802), +W64LIT(0xbe93fad23f0955ef), +W64LIT(0x3ae76ce3af39b909), +W64LIT(0xad7ee3cf6f5ea7c6), +W64LIT(0x8b51d1f5cff0b694), +W64LIT(0x70ca8d8e3c43bf99), +W64LIT(0xccdba7f8b2a8f6c9), +W64LIT(0x4c5e6474b5a922a4), +W64LIT(0x5d31adcd541ccc32), +W64LIT(0x9b7f701e8c3456a7), +W64LIT(0x2ac9cd08ecfd593a), +W64LIT(0x8fa0844858c18e1f), +W64LIT(0x32f0c66c745bc9ea), +W64LIT(0xc58d6525cbbb888f), +W64LIT(0x8c633cbe4b529c05), +W64LIT(0xf2cd9ea68aa0774b), +W64LIT(0x2cba4811ca2e7d0e), +W64LIT(0xe2e33f4dc9649778), +W64LIT(0xf4be1bbfac73537f), +W64LIT(0x22de6787379f29d9), +W64LIT(0x0956c2dd79137e46), +W64LIT(0xe061efe978868bc7), +W64LIT(0x1cc85ed90f97a85b), +W64LIT(0x31337e9a67c8dbf0), +W64LIT(0x360193d1e36af161), +W64LIT(0x7fefca4a6383e5eb), +W64LIT(0x8535fe633241e243), +W64LIT(0xc3fee03ced68acbb), +W64LIT(0x81c4abdea570dac8), +W64LIT(0x67d6c12efb25753b), +W64LIT(0xa4282112164dd980), +W64LIT(0xcf181f0ea13be4d3), +W64LIT(0xa98fb672f86f9f4d), +W64LIT(0x5c70c59ff66dc297), +W64LIT(0xb0f7d544c2b80138), +W64LIT(0x0da79760ee2246cd), +W64LIT(0x3740fb83411bffc4), +W64LIT(0x24ade29e114c0ded), +W64LIT(0xf858e48de0201b17), +W64LIT(0x0e642f96fdb154d7), +W64LIT(0xddb46e41531d185f), +W64LIT(0x25ec8accb33d0348), +W64LIT(0x0282d0a4b1e21cbf), +W64LIT(0x1bfab3928b3582ca), +W64LIT(0xaffc336bdebcbb79), +W64LIT(0x35c22b27f0f9e37b), +W64LIT(0x03c3b8f61393121a), +W64LIT(0xb8e07fcb19da71db), +W64LIT(0x99fda0ba3dd64a18), +W64LIT(0xce59775c034aea76), +W64LIT(0x49ee599b80e9148a), +W64LIT(0xfe2b6194c6f33f23), +W64LIT(0x4edcb4d0044b3e1b), +W64LIT(0xd5a3c4ce887f68bc), +W64LIT(0xdf36bee5e2ff04e0), +W64LIT(0x171c4ca0c766caa2), +W64LIT(0x0bd41279c8f162f9), +W64LIT(0xe490ba54efb7b34c), +W64LIT(0x5b4228d472cfe806), +W64LIT(0x5355825ba9ad98e5), +W64LIT(0x9f8e25a31b056e2c), +W64LIT(0xcd9acfaa10d9f86c), +W64LIT(0x88926903dc63a48e), +W64LIT(0xb40680f9558939b3), +W64LIT(0x239f0fd595ee277c), +W64LIT(0xec8710db34d5c3af), +W64LIT(0x87b72ec783a3fefc), +W64LIT(0x632794936c144db0), +W64LIT(0x46cb1e5fdf294ef8), +W64LIT(0x83467b7a1492c677), +W64LIT(0x9c4d9d5508967c36), +W64LIT(0xd6607c389bec7aa6), +W64LIT(0x165d24f26517c407), +W64LIT(0xc4cc0d7769ca862a), +W64LIT(0xcbe94ab3360adc58), +W64LIT(0x847496319030ece6), +W64LIT(0x7a5ff7a556c3d3c5), +W64LIT(0xc03d58cafefbbea1), +W64LIT(0x76b908971a909bad), +W64LIT(0x2f79f0e7d9bd6f14), +W64LIT(0x197863363ad79e75), +W64LIT(0xda86830ad7bf32ce), +W64LIT(0x5a034086d0bee6a3), +W64LIT(0x97998f2cc0671ecf), +W64LIT(0x552607428f7ebcd1), +W64LIT(0x51d752ff184f845a), +W64LIT(0xbb23c73d0a4963c1), +W64LIT(0x2b88a55a4e8c579f), +W64LIT(0xd80453ae665d2e71), +W64LIT(0xee05c07f8537df10), +W64LIT(0x423a4be248187673), +W64LIT(0xcaa822e1947bd2fd), +W64LIT(0x1abbdbc029448c6f), +W64LIT(0x96d8e77e6216106a), +W64LIT(0x6266fcc1ce654315), +W64LIT(0x89d301517e12aa2b), +W64LIT(0x730935782fd0ad83), +W64LIT(0x8085c38c0701d46d), +W64LIT(0x6b303e1cb7763d53), +W64LIT(0x3f57510c9a798f27), +W64LIT(0x4449cefb6ecb5247), +W64LIT(0x48af31c922981a2f), +W64LIT(0x98bcc8e89fa744bd), +W64LIT(0x69b2eeb8069421ec), +W64LIT(0xebb5fd90b077e93e), +W64LIT(0x6a71564e150733f6), +W64LIT(0x116fc9b9e1b5ee96), +W64LIT(0x4a2de16d937a0690), +W64LIT(0xb9a11799bbab7f7e), +W64LIT(0x9368da9157562644), +W64LIT(0x718be5dc9e32b13c), +W64LIT(0xc82af2452599ce42), +W64LIT(0xb547e8abf7f83716), +W64LIT(0x33b1ae3ed62ac74f), +W64LIT(0x799c4f534550c1df), +W64LIT(0x3e16395e38088182), +W64LIT(0x7c2c72bc7010f7f1), +W64LIT(0xf38cf6f428d179ee), +W64LIT(0xd29129850cdd422d), +W64LIT(0x41f9f3145b8b6469), +W64LIT(0x945a37dad3f40cd5), +W64LIT(0x757ab061090389b7), +W64LIT(0x6554118a4ac76984), +W64LIT(0x7d6d1aeed261f954), +W64LIT(0x01416852a2710ea5), +W64LIT(0xb27505e0735a1d87), +W64LIT(0x77f860c5b8e19508), +W64LIT(0x78dd2701e721cf7a), +W64LIT(0xe12087bbdaf78562), +W64LIT(0x86f6469521d2f059), +W64LIT(0xef44a82d2746d1b5), +W64LIT(0xbc112a768eeb4950), +W64LIT(0xc2bf886e4f19a21e), +W64LIT(0x307216c8c5b9d555), +W64LIT(0xc96b9a1787e8c0e7), +W64LIT(0xa31acc5992eff311), +W64LIT(0xa0d974af817ce10b), +W64LIT(0xdcf50613f16c16fa), +W64LIT(0xfca9b1307711239c), +W64LIT(0x57a4d7e63e9ca06e), +W64LIT(0xc64eddd3d8289a95), +W64LIT(0xa25ba40b309efdb4), +W64LIT(0x2e3898b57bcc61b1), +W64LIT(0xf5ff73ed0e025dda), +W64LIT(0xa6aaf1b6a7afc53f), +W64LIT(0xd9453bfcc42c20d4), +W64LIT(0x9d0cf507aae77293), +W64LIT(0x290a75feff6e4b20), +W64LIT(0xa7eb99e405decb9a), +W64LIT(0xa1981cfd230defae), +W64LIT(0x12ac714ff226fc8c), +W64LIT(0x743bd833ab728712), +W64LIT(0x6c02d35733d417c2), +W64LIT(0xe9372d340195f581), +W64LIT(0xf77da349bfe04165), +W64LIT(0x68f386eaa4e52f49), +W64LIT(0x211ddf71240c3bc3), +W64LIT(0x13ed191d5057f229), +W64LIT(0xe8764566a3e4fb24), +W64LIT(0xf9198cdf425115b2), +W64LIT(0xd013f921bd3f5e92), +W64LIT(0x91ea0a35e6b43afb), +W64LIT(0x0732ed4b84a22a91), +W64LIT(0xeaf495c21206e79b), +W64LIT(0x5214ea090bdc9640), +W64LIT(0x0000000000000000), +W64LIT(0xb3346db2d12b1322), +W64LIT(0x0ce6ff324c534868), +W64LIT(0xaebd5b397ccdb5dc), +W64LIT(0x0a957a2b6a806c5c), +W64LIT(0x1f0be62f1c04ba41), +W64LIT(0x14dff456d4f5d8b8), +W64LIT(0x58819022615cfa1c), +W64LIT(0x05b03def3540362e), +W64LIT(0xe3a2571f6b1599dd), +W64LIT(0x9229b2c3f52728e1), +W64LIT(0xba62af6fa8386d64), +W64LIT(0x0673851926d32434), +W64LIT(0x641579d8e8b66721), +W64LIT(0x04f155bd9731388b), +W64LIT(0x9ecf4df1b9746089), +W64LIT(0x205cb723867d3566), +W64LIT(0x102ea1eb43c4e033), +W64LIT(0x3ba604b10d48b7ac), +W64LIT(0x50963aadba3e8aff), +W64LIT(0xac3f8b9dcd2fa963), +W64LIT(0x7b1e9ff7f4b2dd60), +W64LIT(0xf63ccb1b1d914fc0), +W64LIT(0x7eaea218c1f2eb4e), +W64LIT(0x5fb37d69e5fed08d), +W64LIT(0x56e5bfb49cedaecb), +W64LIT(0x2dfb2043685f73ab), +W64LIT(0x61a54437ddf6510f), +W64LIT(0x6fc16ba1204705d8), +W64LIT(0xe75302a2fc24a156), +W64LIT(0x3dd581a82b9b9398), +W64LIT(0xdbc7eb5875ce3c6b), +W64LIT(0x90ab626744c5345e), +W64LIT(0x59c0f870c32df4b9), +W64LIT(0x6697a97c59547b9e), +W64LIT(0xfde8d962d5602d39), +W64LIT(0xd3d041d7aeac4c88), +W64LIT(0x5ef2153b478fde28), +W64LIT(0xd4e2ac9c2a0e6619), +W64LIT(0x1e4a8e7dbe75b4e4), +W64LIT(0x72485d2a8da1a326), +W64LIT(0x437b23b0ea6978d6), +W64LIT(0x159e9c047684d61d), +W64LIT(0x0f2547c45fc05a72), +W64LIT(0xf10e265099336551), +W64LIT(0x3c94e9fa89ea9d3d), +W64LIT(0xbfd292809d785b4a), +W64LIT(0x0817aa8fdb6270e3), +W64LIT(0x60e42c657f875faa), +W64LIT(0x18390b6498a690d0), +W64LIT(0x478a760d7d58405d), +W64LIT(0x284b1dac5d1f4585), +W64LIT(0xb1b6bd1660c90f9d), +W64LIT(0xd15291731f4e5037), +W64LIT(0x4d1f0c2617d82c01), +W64LIT(0xc70fb5817a599430), +W64LIT(0x6d43bb0591a51967), +W64LIT(0x6e8003f382360b7d), +W64LIT(0x1d89368bade6a6fe), +W64LIT(0x4f9ddc82a63a30be), +W64LIT(0xedc6788996a4cd0a), +W64LIT(0xab0d66d6498d83f2), +W64LIT(0x54676f102d0fb274), +W64LIT(0xc17c30985c8ab004), +W64LIT(0x3865bc471edba5b6), +W64LIT(0x3924d415bcaaab13), +W64LIT(0x951b5f8871850270), +W64LIT(0x8a10b9a76d81b831), +W64LIT(0xbd5042242c9a47f5), +W64LIT(0xa5694940b43cd725), +W64LIT(0xff6a09c664823186), +W64LIT(0x8d2254ece92392a0), +W64LIT(0xb7c5380f461a2ba9), +W64LIT(0x82071328b6e3c8d2), +W64LIT(0xd721146a399d7403), +W64LIT(0xfada342951c207a8), +W64LIT(0x262f323aa0ae1152), +W64LIT(0xf04f4e023b426bf4), +W64LIT(0x276e5a6802df1ff7), +/* box 1 */ +W64LIT(0x3b4016dbfd16e203), +W64LIT(0x9a7574c51174530a), +W64LIT(0x90012e69c02ec8d3), +W64LIT(0xf44580e3d780e076), +W64LIT(0xf81dec2b49eca14b), +W64LIT(0x26cae3e8a6e3d7ef), +W64LIT(0x0962419e0c41f6ab), +W64LIT(0x54d1eb4070ebd951), +W64LIT(0x865e884b0188eec8), +W64LIT(0xdf76067ea406fe8a), +W64LIT(0x29849412e594fba0), +W64LIT(0x461569896869c0f2), +W64LIT(0xb5ddd6b3bbd6724e), +W64LIT(0x0c586cc89e6c413d), +W64LIT(0x6b0ad97054d904ea), +W64LIT(0xa135621eec62b109), +W64LIT(0x0eef7e47087ea461), +W64LIT(0xfaaafea4dffe4417), +W64LIT(0xe0ad344e80342331), +W64LIT(0xab4138b23d382ad0), +W64LIT(0x107390468e90fcff), +W64LIT(0xbe0885a2218561b9), +W64LIT(0xdbed22957d22c132), +W64LIT(0x2251c7037fc7e857), +W64LIT(0x33835ef8ba5e9c86), +W64LIT(0xb3f1e0d7f4e0a8aa), +W64LIT(0x3fdb32302432ddbb), +W64LIT(0xa719547aa3546bed), +W64LIT(0xe10c3df3cb3dab1f), +W64LIT(0x17feaf9f8aafae35), +W64LIT(0x9df84b1c154b01c0), +W64LIT(0x8364a51d93a5595e), +W64LIT(0x535cd49974d48b9b), +W64LIT(0x01a109bd4b09882e), +W64LIT(0xc4d0c529b0c51182), +W64LIT(0x2e09abcbe1aba96a), +W64LIT(0x1f3de7bccde7d0b0), +W64LIT(0x9317355b1d35a5a1), +W64LIT(0x6c87e6a950e65620), +W64LIT(0x8910ffb142ffc287), +W64LIT(0x40395fed275f1a16), +W64LIT(0x7b794936da49f815), +W64LIT(0xf269b68798b63a92), +W64LIT(0xfd27c17ddbc116dd), +W64LIT(0x8d8bdb5a9bdbfd3f), +W64LIT(0x1ba6c35714c3ef08), +W64LIT(0x6e30f426c6f4b37c), +W64LIT(0x7fe26ddd036dc7ad), +W64LIT(0x14e8b4ad57b4c347), +W64LIT(0xb985ba7b25ba3373), +W64LIT(0xe9cf75d08c75d59a), +W64LIT(0x626898ee5898f241), +W64LIT(0x5b9f9cba339cf51e), +W64LIT(0xb250e96abfe92084), +W64LIT(0x165fa622c1a6261b), +W64LIT(0xf5e4895e9c896858), +W64LIT(0xb76ac43c2dc49712), +W64LIT(0x02b7128f9612e55c), +W64LIT(0x1d8af5335bf535ec), +W64LIT(0x36b973ae28732b10), +W64LIT(0xa8572380e02347a2), +W64LIT(0xf6f2926c4192052a), +W64LIT(0x8c2ad2e7d0d27511), +W64LIT(0xd32e6ab63a6abfb7), +W64LIT(0xbd1e9e90fc9e0ccb), +W64LIT(0x03161b32dd1b6d72), +W64LIT(0x4dc03a98f23ad305), +W64LIT(0x81d3b79205b7bc02), +W64LIT(0x450372bbb572ad80), +W64LIT(0x2d1fb0f93cb0c418), +W64LIT(0x2a928f20388f96d2), +W64LIT(0x721b08a8d6080ebe), +W64LIT(0x92b63ce6563c2d8f), +W64LIT(0xeb78675f1a6730c6), +W64LIT(0x13658b74538b918d), +W64LIT(0x428e4d62b14dff4a), +W64LIT(0x88b1f60c09f64aa9), +W64LIT(0x75963771d2375c74), +W64LIT(0x7ad8408b9140703b), +W64LIT(0x57c7f072adf0b423), +W64LIT(0xe5971918121994a7), +W64LIT(0x5666f9cfe6f93c0d), +W64LIT(0x8f3cc9d50dc91863), +W64LIT(0x1e9cee0186ee589e), +W64LIT(0x8a06e4839fe4aff5), +W64LIT(0xb824b3c66eb3bb5d), +W64LIT(0xd1997839ac785aeb), +W64LIT(0x6752b5b8cab545d7), +W64LIT(0xb47cdf0ef0dffa60), +W64LIT(0x949a0a82190af76b), +W64LIT(0xc04be1c269e12e3a), +W64LIT(0xfc86c8c090c89ef3), +W64LIT(0xe3bb2f7c5d2f4e43), +W64LIT(0x6aabd0cd1fd08cc4), +W64LIT(0x2147dc31a2dc8525), +W64LIT(0xca3fbb6eb8bbb5e3), +W64LIT(0x48fa17ce60176493), +W64LIT(0x6444ae8a17ae28a5), +W64LIT(0x2b33869d73861efc), +W64LIT(0xd0387184e771d2c5), +W64LIT(0x7cf476efde76aadf), +W64LIT(0x63c9915313917a6f), +W64LIT(0xc929a05c65a0d891), +W64LIT(0xda4c2b28362b491c), +W64LIT(0xfe31da4f06da7baf), +W64LIT(0xc1eae87f22e8a614), +W64LIT(0x5c12a36337a3a7d4), +W64LIT(0x18b0d865c9d8827a), +W64LIT(0xe7200b97840b71fb), +W64LIT(0x4bec0cfcbd0c09e1), +W64LIT(0x0f4e77fa43772c4f), +W64LIT(0x4c613325b9335b2b), +W64LIT(0xf3c8bf3ad3bfb2bc), +W64LIT(0x87ff81f64a8166e6), +W64LIT(0xa38270917a705455), +W64LIT(0x1911d1d882d10a54), +W64LIT(0x44a27b06fe7b25ae), +W64LIT(0x049b24ebd9243fb8), +W64LIT(0xbb32a8f4b3a8d62f), +W64LIT(0x91a027d48b2740fd), +W64LIT(0x3d6c20bfb22038e7), +W64LIT(0xe681022acf02f9d5), +W64LIT(0xf17fadb545ad57e0), +W64LIT(0xcc138d0af78d6f07), +W64LIT(0x495b1e732b1eecbd), +W64LIT(0x38560de9200d8f71), +W64LIT(0xa9f62a3dab2acf8c), +W64LIT(0x47b46034236048dc), +W64LIT(0x8e9dc06846c0904d), +W64LIT(0xaccc076b3907781a), +W64LIT(0x32225745f15714a8), +W64LIT(0xd4a3556f3e55ed7d), +W64LIT(0xd7b54e5de34e800f), +W64LIT(0xddc114f132141bd6), +W64LIT(0x6d26ef141befde0e), +W64LIT(0x85489379dc9383ba), +W64LIT(0x0bd553119a5313f7), +W64LIT(0x786f520407529567), +W64LIT(0xcb9eb2d3f3b23dcd), +W64LIT(0xa223792c3179dc7b), +W64LIT(0x0a745aacd15a9bd9), +W64LIT(0x710d139a0b1363cc), +W64LIT(0x681cc24289c26998), +W64LIT(0x1a07caea5fca6726), +W64LIT(0x82c5aca0d8acd170), +W64LIT(0x25dcf8da7bf8ba9d), +W64LIT(0xc7c6de1b6dde7cf0), +W64LIT(0xc35dfaf0b4fa4348), +W64LIT(0xded70fc3ef0f76a4), +W64LIT(0x504acfaba9cfe6e9), +W64LIT(0xc571cc94fbcc99ac), +W64LIT(0x5ea5b1eca1b14288), +W64LIT(0xae7b15e4af159d46), +W64LIT(0xc888a9e12ea950bf), +W64LIT(0xf7539bd10a9b8d04), +W64LIT(0x962d180d8f181237), +W64LIT(0xe43610a559101c89), +W64LIT(0x772125fe4425b928), +W64LIT(0x84e99ac4979a0b94), +W64LIT(0xc667d7a626d7f4de), +W64LIT(0xefe343b4c3430f7e), +W64LIT(0xd5025cd2755c6553), +W64LIT(0xa6b85dc7e85de3c3), +W64LIT(0xd61447e0a8470821), +W64LIT(0x3e7a3b8d6f3b5595), +W64LIT(0x52fddd243fdd03b5), +W64LIT(0x8072be2f4ebe342c), +W64LIT(0x12c482c9188219a3), +W64LIT(0x9eee502ec8506cb2), +W64LIT(0xad6d0ed6720ef034), +W64LIT(0x59288e35a58e1042), +W64LIT(0xe21a26c11626c66d), +W64LIT(0x247df16730f132b3), +W64LIT(0xf0dea4080ea4dfce), +W64LIT(0x31344c772c4c79da), +W64LIT(0x4f77281764283659), +W64LIT(0x79ce5bb94c5b1d49), +W64LIT(0x0000000000000000), +W64LIT(0x73ba01159d018690), +W64LIT(0x74373ecc993ed45a), +W64LIT(0xbcbf972db79784e5), +W64LIT(0x4ed621aa2f21be77), +W64LIT(0xd95a301aeb30246e), +W64LIT(0x9c5942a15e4289ee), +W64LIT(0x37187a13637aa33e), +W64LIT(0x276bea55edea5fc1), +W64LIT(0x1c2bfc8e10fcbdc2), +W64LIT(0xed54513b5551ea22), +W64LIT(0x20e6d58ce9d50d0b), +W64LIT(0x3ae11f66b61f6a2d), +W64LIT(0x66f3bc0581bccdf9), +W64LIT(0x2cbeb94477b94c36), +W64LIT(0x99636ff7cc6f3e78), +W64LIT(0x953b033f52037f45), +W64LIT(0xb0e7fbe529fbc5d8), +W64LIT(0x60df8a61ce8a171d), +W64LIT(0x6f91fd9b8dfd3b52), +W64LIT(0xaae0310f7631a2fe), +W64LIT(0xbfa98c1f6a8ce997), +W64LIT(0x8ba7ed3ed4ed27db), +W64LIT(0x98c2664a8766b656), +W64LIT(0x062c36644f36dae4), +W64LIT(0x5570e2fd3be2517f), +W64LIT(0xead96ee2516eb8e8), +W64LIT(0x419856506c569238), +W64LIT(0x23f0cebe34ce6079), +W64LIT(0x309545ca6745f1f4), +W64LIT(0x5a3e950778957d30), +W64LIT(0x617e83dc85839f33), +W64LIT(0xfb0bf71994f7cc39), +W64LIT(0x3ccd2902f929b0c9), +W64LIT(0x70ac1a27401aebe2), +W64LIT(0xcea49f85619f8a5b), +W64LIT(0x39f704546b04075f), +W64LIT(0x0df96575d565c913), +W64LIT(0x08c3482347487e85), +W64LIT(0xd28f630b71633799), +W64LIT(0xecf558861e58620c), +W64LIT(0xc2fcf34dfff3cb66), +W64LIT(0x978c11b0c4119a19), +W64LIT(0x69bdcbffc2cbe1b6), +W64LIT(0xba93a149f8a15e01), +W64LIT(0x51ebc616e2c66ec7), +W64LIT(0x078d3fd9043f52ca), +W64LIT(0x58898788ee87986c), +W64LIT(0x4a4d0541f60581cf), +W64LIT(0xe86e7c6dc77c5db4), +W64LIT(0xee424a09884a8750), +W64LIT(0xcdb284b7bc84e729), +W64LIT(0x65e5a7375ca7a08b), +W64LIT(0x2fa8a276aaa22144), +W64LIT(0xa0946ba3a76b3927), +W64LIT(0xa5ae46f535468eb1), +W64LIT(0x35af689cf5684662), +W64LIT(0x28259dafae9d738e), +W64LIT(0xcf0596382a960275), +W64LIT(0xb6cbcd8166cd1f3c), +W64LIT(0x7e43646048644f83), +W64LIT(0x9bd47d785a7ddb24), +W64LIT(0x432f44dffa447764), +W64LIT(0x9f4f59938359e49c), +W64LIT(0x7d557f52957f22f1), +W64LIT(0x76802c430f2c3106), +W64LIT(0xdc601d4c791d93f8), +W64LIT(0x053a2d56922db796), +W64LIT(0x11d299fbc59974d1), +W64LIT(0xf9bce59602e52965), +W64LIT(0xd8fb39a7a039ac40), +W64LIT(0x340e6121be61ce4c), +W64LIT(0x5f04b851eab8caa6), +W64LIT(0x5db3aade7caa2ffa), +W64LIT(0x1549bd101cbd4b69), +W64LIT(0xff90d3f24dd3f381), +W64LIT(0xafda1c59e41c1568), +W64LIT(0xb146f25862f24df6), +W64LIT(0xa40f4f487e4f069f), +/* box 2 */ +W64LIT(0xa1a35cebf8f0f94c), +W64LIT(0x2c203d650f3f095d), +W64LIT(0x1a2bdaee4084a2a7), +W64LIT(0xd32404574d7bcc68), +W64LIT(0xf785bea594a9adc4), +W64LIT(0xf2eb54456206949c), +W64LIT(0x3f5e334d0475ced1), +W64LIT(0x5994299b835d1f60), +W64LIT(0x785b7989ac204794), +W64LIT(0x025da6a2cf461a41), +W64LIT(0xdf1f3a71f01a901b), +W64LIT(0x27284f018bb77637), +W64LIT(0xe1955a6d694c5310), +W64LIT(0x24a1baf2d9d261ac), +W64LIT(0xe4fbb08d9fe36a48), +W64LIT(0x8d83618ef7cff011), +W64LIT(0x2ac72276abf5279e), +W64LIT(0xf9e32621e68eebf6), +W64LIT(0xbf323fb4d3f86f69), +W64LIT(0xbb888605b8745beb), +W64LIT(0x70dafe1e7acd2f65), +W64LIT(0xd0adf1a41f1edbf3), +W64LIT(0x1e91635f2b089625), +W64LIT(0xee2791b8864818f8), +W64LIT(0x99ce23e4c56c1484), +W64LIT(0xf33f0714ff259946), +W64LIT(0xbd6f99161cbe7528), +W64LIT(0x9f293cf761a63a47), +W64LIT(0xb80173f6ea114c70), +W64LIT(0x6543ef25d54dc62a), +W64LIT(0x39b92c5ea0bfe012), +W64LIT(0x63a4f0367187e8e9), +W64LIT(0x4c0d38a02cddf62f), +W64LIT(0x07334c4239e92319), +W64LIT(0x43bff375c3d9bdc7), +W64LIT(0xca862b4a5f9a7954), +W64LIT(0x5d2e902ae8d12be2), +W64LIT(0x137e0e280b4ac78c), +W64LIT(0xf162a1b630638307), +W64LIT(0x55af17bd3e3c4313), +W64LIT(0x358212781ddebc61), +W64LIT(0x94214e93e52e452d), +W64LIT(0xc18e592edb12063e), +W64LIT(0xec7a371a490e02b9), +W64LIT(0x4963d240da72cf77), +W64LIT(0x41e255d70c9fa786), +W64LIT(0xff0439324244c535), +W64LIT(0x88ed8b6e0160c949), +W64LIT(0x6c163be39e83a301), +W64LIT(0xc534e09fb09e32bc), +W64LIT(0x806c0cf9d78da1b8), +W64LIT(0xdba583c09b96a499), +W64LIT(0x746047af11411be7), +W64LIT(0xf40c4b56c6ccba5f), +W64LIT(0x6270a367eca4e533), +W64LIT(0xd41748157492ef71), +W64LIT(0xeff3c2e91b6b1522), +W64LIT(0x0e66988472274632), +W64LIT(0x534808ae9af66dd0), +W64LIT(0x8231aa5b18cbbbf9), +W64LIT(0xb2dd52c3f3ba3ec0), +W64LIT(0xdd429cd33f5c8a5a), +W64LIT(0x4e509e02e39bec6e), +W64LIT(0x26fc1c5016947bed), +W64LIT(0xd9f8256254d0bed8), +W64LIT(0x0955d4c64bce652b), +W64LIT(0x1610e4c8fde5fed4), +W64LIT(0x6dc268b203a0aedb), +W64LIT(0x2e7d9bc7c079131c), +W64LIT(0xc3d3ff8c14541c7f), +W64LIT(0xd64aeeb7bbd4f530), +W64LIT(0xab7f7ddee15b8bfc), +W64LIT(0x144d426a32a3e495), +W64LIT(0x8e0a947da5aae78a), +W64LIT(0x798f2ad831034a4e), +W64LIT(0x3be48afc6ff9fa53), +W64LIT(0x529c5bff07d5600a), +W64LIT(0xbee66ce54edb62b3), +W64LIT(0x931202d1dcc76634), +W64LIT(0x50c1fd5dc8937a4b), +W64LIT(0xa4cdb60b0e5fc014), +W64LIT(0x57f2b11ff17a5952), +W64LIT(0x47054ac4a8558945), +W64LIT(0x5a1ddc68d13808fb), +W64LIT(0x5cfac37b75f22638), +W64LIT(0xc207acdd897711a5), +W64LIT(0x289a84d464b33ddf), +W64LIT(0xc05a0a7f46310be4), +W64LIT(0xe6a6162f50a57009), +W64LIT(0x06e71f13a4ca2ec3), +W64LIT(0x5f733688279731a3), +W64LIT(0xeb497b5870e721a0), +W64LIT(0xb667eb7298360a42), +W64LIT(0xe3c8fccfa60a4951), +W64LIT(0xe772457ecd867dd3), +W64LIT(0x6978d103682c9a59), +W64LIT(0x0def6d77204251a9), +W64LIT(0xc90fdeb90dff6ecf), +W64LIT(0xd179a2f5823dd629), +W64LIT(0x2fa9c8965d5a1ec6), +W64LIT(0x81b85fa84aaeac62), +W64LIT(0xdc96cf82a27f8780), +W64LIT(0x602d05c523e2ff72), +W64LIT(0x19a22f1d12e1b53c), +W64LIT(0xe52fe3dc02c06792), +W64LIT(0x58407aca1e7e12ba), +W64LIT(0x61f95694bec1f2a8), +W64LIT(0x48b781114751c2ad), +W64LIT(0xaaab2e8f7c788626), +W64LIT(0x04bab9b16b8c3482), +W64LIT(0x2df46e34921c0487), +W64LIT(0x1123a88ac40cddcd), +W64LIT(0xc6bd156ce2fb2527), +W64LIT(0x7f6835cb95c9648d), +W64LIT(0x83e5f90a85e8b623), +W64LIT(0x4f84cd537eb8e1b4), +W64LIT(0x294ed785f9903005), +W64LIT(0x1cccc5fde44e8c64), +W64LIT(0xcb52781bc2b9748e), +W64LIT(0x1d1896ac796d81be), +W64LIT(0xb30901926e99331a), +W64LIT(0xad9862cd4591a53f), +W64LIT(0xc8db8de890dc6315), +W64LIT(0x7bd28c7afe45500f), +W64LIT(0x0adc213519ab72b0), +W64LIT(0xa8f6882db33e9c67), +W64LIT(0xb5ee1e81ca531dd9), +W64LIT(0x201b0343b25e552e), +W64LIT(0x4036068691bcaa5c), +W64LIT(0xae11973e17f4b2a4), +W64LIT(0x9efd6fa6fc85379d), +W64LIT(0x33650d6bb91492a2), +W64LIT(0x3a30d9adf2daf789), +W64LIT(0x0c3b3e26bd615c73), +W64LIT(0xf651edf4098aa01e), +W64LIT(0x710ead4fe7ee22bf), +W64LIT(0x3138abc9765288e3), +W64LIT(0x9d749a55aee02006), +W64LIT(0x6e4b9d4151c5b940), +W64LIT(0x84d6b548bc01953a), +W64LIT(0x360be78b4fbbabfa), +W64LIT(0xa22aa918aa95eed7), +W64LIT(0xedae644bd42d0f63), +W64LIT(0x46d119953576849f), +W64LIT(0x6497bc74486ecbf0), +W64LIT(0xfbbe808329c8f1b7), +W64LIT(0x4aea27b38817d8ec), +W64LIT(0x5626e24e6c595488), +W64LIT(0x056eeae0f6af3958), +W64LIT(0x4558ec6667139304), +W64LIT(0x448cbf37fa309ede), +W64LIT(0x6f9fce10cce6b49a), +W64LIT(0xa0770fba65d3f496), +W64LIT(0x671e49871a0bdc6b), +W64LIT(0xda71d09106b5a943), +W64LIT(0x08818797d6ed68f1), +W64LIT(0xa3fefa4937b6e30d), +W64LIT(0xb080f4613cfc2481), +W64LIT(0x763de10dde0701a6), +W64LIT(0x4dd96bf1b1fefbf5), +W64LIT(0x92c6518041e46bee), +W64LIT(0x3456412980fdb1bb), +W64LIT(0x981a70b5584f195e), +W64LIT(0x3d0395efcb33d490), +W64LIT(0xba5cd55425575631), +W64LIT(0x4b3e74e21534d536), +W64LIT(0x6af124f03a498dc2), +W64LIT(0x7ebc669a08ea6957), +W64LIT(0x30ecf898eb718539), +W64LIT(0xa922db7c2e1d91bd), +W64LIT(0x7a06df2b63665dd5), +W64LIT(0xb154a730a1df295b), +W64LIT(0xfc8dccc11021d2ae), +W64LIT(0xcfe8c1aaa935400c), +W64LIT(0x97a8bb60b74b52b6), +W64LIT(0x18767c4c8fc2b8e6), +W64LIT(0x9a47d6179709031f), +W64LIT(0x0000000000000000), +W64LIT(0xac4c319cd8b2a8e5), +W64LIT(0xb9d520a7773241aa), +W64LIT(0xdecb69206d399dc1), +W64LIT(0x1f45300eb62b9bff), +W64LIT(0x10f7fbdb592fd017), +W64LIT(0x3e8a601c9956c30b), +W64LIT(0x8502e619212298e0), +W64LIT(0xf5d818075befb785), +W64LIT(0x547b44eca31f4ec9), +W64LIT(0x9ca0c90433c32ddc), +W64LIT(0xe041093cf46f5eca), +W64LIT(0xa69010a9c119da55), +W64LIT(0xc769463d7fd828fd), +W64LIT(0xc4e0b3ce2dbd3f66), +W64LIT(0x2575e9a344f16c76), +W64LIT(0x01d453519d230dda), +W64LIT(0xfa6ad3d2b4ebfc6d), +W64LIT(0xd5c31b44e9b1e2ab), +W64LIT(0xf83775707bade62c), +W64LIT(0xbcbbca47819d78f2), +W64LIT(0xd79ebde626f7f8ea), +W64LIT(0x5bc98f394c1b0521), +W64LIT(0x2246a5e17d184f6f), +W64LIT(0x12aa5d799669ca56), +W64LIT(0x5ea765d9bab43c79), +W64LIT(0x8939d83f9c43c493), +W64LIT(0x32b15e3a24379f78), +W64LIT(0xe914ddfabfa13be1), +W64LIT(0x909bf7228ea271af), +W64LIT(0x73530bed28a838fe), +W64LIT(0xd2f05706d058c1b2), +W64LIT(0xfed06a63df67c8ef), +W64LIT(0xb43a4dd057701003), +W64LIT(0xa519e55a937ccdce), +W64LIT(0x75b414fe8c62163d), +W64LIT(0xafc5c46f8ad7bf7e), +W64LIT(0x2392f6b0e03b42b5), +W64LIT(0x386d7f0f3d9cedc8), +W64LIT(0x21cf50122f7d58f4), +W64LIT(0x9b9385460a2a0ec5), +W64LIT(0x5115ae0c55b07791), +W64LIT(0x0fb2cbd5ef044be8), +W64LIT(0xea9d2809edc42c7a), +W64LIT(0xcc613459fb505797), +W64LIT(0x426ba0245efab01d), +W64LIT(0x1599113baf80e94f), +W64LIT(0x7d3593695a8f7ecc), +W64LIT(0x0389f5f35265179b), +W64LIT(0x875f40bbee6482a1), +W64LIT(0x95f51dc2780d48f7), +W64LIT(0x7ce1c038c7ac7316), +W64LIT(0xce3c92fb34164dd6), +W64LIT(0xcdb5670866735a4d), +W64LIT(0x8ab02dccce26d308), +W64LIT(0x914fa47313817c75), +W64LIT(0x8b647e9d5305ded2), +W64LIT(0xd82c7633c9f3b302), +W64LIT(0x728758bcb58b3524), +W64LIT(0xe8c08eab2282363b), +W64LIT(0x8fdec72c3889ea50), +W64LIT(0x2b13712736d62a44), +W64LIT(0x3cd7c6be5610d94a), +W64LIT(0x37dfb4dad298a620), +W64LIT(0x868b13ea73478f7b), +W64LIT(0xb7b3b82305150798), +W64LIT(0x0b08726484887f6a), +W64LIT(0x1bff89bfdda7af7d), +W64LIT(0x77e9b25c43240c7c), +W64LIT(0xf0b6f2e7ad408edd), +W64LIT(0x17c4b79960c6f30e), +W64LIT(0x8c5732df6aecfdcb), +W64LIT(0x68ac8252f50f9783), +W64LIT(0x66ca1ad68728d1b1), +W64LIT(0x6b2577a1a76a8018), +W64LIT(0xe21caf9e3b29448b), +W64LIT(0xa74443f85c3ad78f), +W64LIT(0xfd599f908d02df74), +W64LIT(0x967ce8312a685f6c), +/* box 3 */ +W64LIT(0xfa7b9775ba3af751), +W64LIT(0x03ef98cb769c2d13), +W64LIT(0x7191ce067072359e), +W64LIT(0xbab18b6bff7516a8), +W64LIT(0xe6e5ef4efbc1065e), +W64LIT(0x7bec74a3b1d0dbf4), +W64LIT(0x656b4fb907c31c4a), +W64LIT(0x4e8520f99fc86304), +W64LIT(0x8fd8df31d16dae58), +W64LIT(0x90a93fc1e60a7244), +W64LIT(0x30ad09f2b449cfc5), +W64LIT(0x8453be7e91bb5b90), +W64LIT(0x1d68a3d1c08feaad), +W64LIT(0x5c54642504b410f6), +W64LIT(0x8061383c8a9e3707), +W64LIT(0xf9940fbecca6da42), +W64LIT(0x46e1d97da982bbdf), +W64LIT(0xfc50521656f7ad77), +W64LIT(0x5e4d2704f35c2647), +W64LIT(0x8bea5973ca48c2cf), +W64LIT(0xd06323dfa34593bd), +W64LIT(0x62b651306a7a5dce), +W64LIT(0xa436b0714966d116), +W64LIT(0x4f73fb131ebc78a6), +W64LIT(0x92b07ce011e244f5), +W64LIT(0x33429139c2d5e2d6), +W64LIT(0xcee418c515565403), +W64LIT(0xd7be3d56cefcd239), +W64LIT(0x53ed83285f4789a9), +W64LIT(0xf3e9b51b0d043428), +W64LIT(0x20650e0fd8dd8a86), +W64LIT(0xb6e7f4add21aa2e4), +W64LIT(0x6d0fb63d3189c491), +W64LIT(0x0da0a42cac1bafee), +W64LIT(0x3f14eeffefba569a), +W64LIT(0x13279f361a086850), +W64LIT(0x9b225e8ea6dc878c), +W64LIT(0x6684d772715f3159), +W64LIT(0xa3ebaef824df9092), +W64LIT(0xc499a260d4f4ba69), +W64LIT(0xaa798c9693e153eb), +W64LIT(0x50021be329dba4ba), +W64LIT(0x949bb983fd2f1ed3), +W64LIT(0xdfdac4d2f8b60ae2), +W64LIT(0xf0062dd07b98193b), +W64LIT(0xafbdd13e09b024de), +W64LIT(0xb95e13a089e93bbb), +W64LIT(0x649d945386b707e8), +W64LIT(0xe4fcac6f0c2930ef), +W64LIT(0x413cc7f4c43bfa5b), +W64LIT(0x3b2668bdf49f3a0d), +W64LIT(0xe50a77858d5d2b4d), +W64LIT(0x05c45da89a517735), +W64LIT(0x3ee235156ece4d38), +W64LIT(0xfe491137a11f9bc6), +W64LIT(0xb7112f47536eb946), +W64LIT(0x07dd1e896db94184), +W64LIT(0x1ab5bd58ad36ab29), +W64LIT(0x8197e3d60bea2ca5), +W64LIT(0xab8f577c12954849), +W64LIT(0x9cff4007cb65c608), +W64LIT(0xa00436335243bd81), +W64LIT(0xfda689fcd783b6d5), +W64LIT(0xccfd5be4e2be62b2), +W64LIT(0x75a348446b575909), +W64LIT(0x17151974012d04c7), +W64LIT(0xfb8d4c9f3b4eecf3), +W64LIT(0xac5249f57f2c09cd), +W64LIT(0x9346a70a90965f57), +W64LIT(0x043286421b256c97), +W64LIT(0x27b81086b564cb02), +W64LIT(0x3569545a2e18b8f0), +W64LIT(0x6b24735edd449eb7), +W64LIT(0x2193d5e559a99124), +W64LIT(0xc7763aaba268977a), +W64LIT(0xb0cc31ce3ed7f8c2), +W64LIT(0xc939064c78ef1587), +W64LIT(0x16e3c29e80591f65), +W64LIT(0x5da2bfcf85c00b54), +W64LIT(0x5990398d9ee567c3), +W64LIT(0x67720c98f02b2afb), +W64LIT(0x54309da132fec82d), +W64LIT(0xeab39088d6aeb212), +W64LIT(0x9682faa20ac72862), +W64LIT(0xd38cbb14d5d9beae), +W64LIT(0x4c9c63d8682055b5), +W64LIT(0xd648e6bc4f88c99b), +W64LIT(0xdc355c198e2a27f1), +W64LIT(0x10c807fd6c944543), +W64LIT(0x450e41b6df1e96cc), +W64LIT(0x0b8b614f40d6f5c8), +W64LIT(0xd27a60fe54ada50c), +W64LIT(0x49583e70f2712280), +W64LIT(0x8dc19c10268598e9), +W64LIT(0x5866e2671f917c61), +W64LIT(0x79f537824638ed45), +W64LIT(0xc2b267033839e04f), +W64LIT(0xcb20456d8f072336), +W64LIT(0x2a18b4aa197f64ec), +W64LIT(0xdbe84290e3936675), +W64LIT(0x73888d27879a032f), +W64LIT(0xe8aad3a9214684a3), +W64LIT(0x6ee02ef64715e982), +W64LIT(0xa996145de57d7ef8), +W64LIT(0xc8cfdda6f99b0e25), +W64LIT(0x062bc563eccd5a26), +W64LIT(0x264ecb6c3410d0a0), +W64LIT(0xb8a8c84a089d2019), +W64LIT(0x7dc7b1c05d1d81d2), +W64LIT(0xd5a77e773914e488), +W64LIT(0x4b417d5105991431), +W64LIT(0xf62de8b39755431d), +W64LIT(0x993b1daf5134b13d), +W64LIT(0x82787b1d7d7601b6), +W64LIT(0xe321b2e66190716b), +W64LIT(0xb5086c66a4868ff7), +W64LIT(0x9ee603263c8df0b9), +W64LIT(0x349f8fb0af6ca352), +W64LIT(0x5b897aac690d5172), +W64LIT(0x7c316a2adc699a70), +W64LIT(0xd451a59db860ff2a), +W64LIT(0x706715ecf1062e3c), +W64LIT(0x838ea0f7fc021a14), +W64LIT(0x57df056a4462e53e), +W64LIT(0xcf12c32f94224fa1), +W64LIT(0xed6e8e01bb17f396), +W64LIT(0x915fe42b677e69e6), +W64LIT(0x89f31a523da0f47e), +W64LIT(0xe71334a47ab51dfc), +W64LIT(0xa860cfb76409655a), +W64LIT(0x9f10d8ccbdf9eb1b), +W64LIT(0xef77cd204cffc527), +W64LIT(0xf862d4544dd2c1e0), +W64LIT(0x8a1c82994b3cd96d), +W64LIT(0xae4b0ad488c43f7c), +W64LIT(0x98cdc645d040aa9f), +W64LIT(0x7fdef2e1aaf5b763), +W64LIT(0x4717029728f6a07d), +W64LIT(0x745593aeea2342ab), +W64LIT(0xee8116cacd8bde85), +W64LIT(0x727e56cd06ee188d), +W64LIT(0x227c4d2e2f35bc37), +W64LIT(0x977421488bb333c0), +W64LIT(0xa21d7512a5ab8b30), +W64LIT(0xbb4750817e010d0a), +W64LIT(0x6cf96dd7b0fddf33), +W64LIT(0x2801f78bee97525d), +W64LIT(0x1c9e783b41fbf10f), +W64LIT(0x9d099bed4a11ddaa), +W64LIT(0x7a1aaf4930a4c056), +W64LIT(0x32b44ad343a1f974), +W64LIT(0x3cfb763499267b89), +W64LIT(0xb2d572efc93fce73), +W64LIT(0x63408adaeb0e466c), +W64LIT(0xada4921ffe58126f), +W64LIT(0x5fbbfcee72283de5), +W64LIT(0x6ad2a8b45c308515), +W64LIT(0x0c567fc62d6fb44c), +W64LIT(0x956d62697c5b0571), +W64LIT(0x25a153a7428cfdb3), +W64LIT(0x150c5a55f6c53276), +W64LIT(0xe2d7690ce0e46ac9), +W64LIT(0xda1e997a62e77dd7), +W64LIT(0xf5c27078e1c96e0e), +W64LIT(0xc344bce9b94dfbed), +W64LIT(0x60af12119d926b7f), +W64LIT(0xa1f2edd9d337a623), +W64LIT(0xcad69e870e733894), +W64LIT(0x3770177bd9f08e41), +W64LIT(0xa5c06b9bc812cab4), +W64LIT(0x1f71e0f03767dc1c), +W64LIT(0x44f89a5c5e6a8d6e), +W64LIT(0x6159c9fb1ce670dd), +W64LIT(0x8e2e04db5019b5fa), +W64LIT(0x8805c1b8bcd4efdc), +W64LIT(0xe138f1c7967847da), +W64LIT(0x4ab7a6bb84ed0f93), +W64LIT(0x0000000000000000), +W64LIT(0x38c9f0768203171e), +W64LIT(0x1b4366b22c42b08b), +W64LIT(0x7803ec68c74cf6e7), +W64LIT(0xec9855eb3a63e834), +W64LIT(0xbe830d29e4507a3f), +W64LIT(0x2dc5aa2374c62568), +W64LIT(0xa62ff350be8ee7a7), +W64LIT(0x764cd08f1dcb741a), +W64LIT(0x8c3747faa7f1834b), +W64LIT(0x0fb9e70d5bf3995f), +W64LIT(0x55c6464bb38ad38f), +W64LIT(0xf7db3359162158bf), +W64LIT(0xd195f8352231881f), +W64LIT(0x0992226eb73ec379), +W64LIT(0x14fa81bf77b129d4), +W64LIT(0x48aee59a73053922), +W64LIT(0x2457884dc3f8e611), +W64LIT(0xffbfcadd206b8064), +W64LIT(0xb4feb78c25f29455), +W64LIT(0x864afd5f66536d21), +W64LIT(0x6f16f51cc661f220), +W64LIT(0xde2c1f3879c21140), +W64LIT(0x195a2593dbaa863a), +W64LIT(0x2e2a32e8025a087b), +W64LIT(0x432584d533d3ccea), +W64LIT(0x2c3371c9f5b23eca), +W64LIT(0xa7d928ba3ffafc05), +W64LIT(0x42d35f3fb2a7d748), +W64LIT(0x85a5659410cf4032), +W64LIT(0x0864f984364ad8db), +W64LIT(0xf21f6ef18c702f8a), +W64LIT(0xf1f0f63afaec0299), +W64LIT(0xd9f101b1147b50c4), +W64LIT(0x2fdce902832e13d9), +W64LIT(0x4d6ab832e9544e17), +W64LIT(0xe0ce2a2d170c5c78), +W64LIT(0x51f4c009a8afbf18), +W64LIT(0x68cbeb95abd8b3a4), +W64LIT(0xc15dffc84ea5cd5c), +W64LIT(0x02194321f7e836b1), +W64LIT(0x113edc17ede05ee1), +W64LIT(0x521b58c2de33920b), +W64LIT(0x9ad4856427a89c2e), +W64LIT(0x5629de80c516fe9c), +W64LIT(0x77ba0b659cbf6fb8), +W64LIT(0x238a96c4ae41a795), +W64LIT(0x12d144dc9b7c73f2), +W64LIT(0xd807da5b950f4b66), +W64LIT(0x3686cc91588495e3), +W64LIT(0x18acfe795ade9d98), +W64LIT(0x5a7fa146e8794ad0), +W64LIT(0xc680e141231c8cd8), +W64LIT(0x1e873b1ab613c7be), +W64LIT(0xf434ab9260bd75ac), +W64LIT(0xcd0b800e63ca7910), +W64LIT(0xbc9a4e0813b84c8e), +W64LIT(0x3d0dadde1852602b), +W64LIT(0x40ca1c1e454fe1f9), +W64LIT(0x0a7dbaa5c1a2ee6a), +W64LIT(0x693d307f2aaca806), +W64LIT(0x0e4f3ce7da8782fd), +W64LIT(0xbd6c95e292cc572c), +W64LIT(0x3ad0b35775eb21af), +W64LIT(0x7e28290b2b81acc1), +W64LIT(0x01f6dbea81741ba2), +W64LIT(0x87bc26b5e7277683), +W64LIT(0x393f2b9c03770cbc), +W64LIT(0xddc387f30f5e3c53), +W64LIT(0xeb454b6257daa9b0), +W64LIT(0xb323a905484bd5d1), +W64LIT(0xb13aea24bfa3e360), +W64LIT(0x315bd218353dd467), +W64LIT(0x2bee6f40980b7f4e), +W64LIT(0xe95c0843a0329f01), +W64LIT(0xc56f798a5580a1cb), +W64LIT(0xbf75d6c36524619d), +W64LIT(0x29f72c616fe349ff), +W64LIT(0xc0ab2422cfd1d6fe), +/* box 4 */ +W64LIT(0x561fc423e957943c), +W64LIT(0x014287ca69079288), +W64LIT(0x2f086129dfcd1d21), +W64LIT(0xc537d4aea044fd99), +W64LIT(0xf1e8c3bfd7c8a457), +W64LIT(0x2971998a5cdf9bfb), +W64LIT(0x23fa649a2ce9e460), +W64LIT(0x3aa9e9c356a6716a), +W64LIT(0xd6efa4e7aa3d1708), +W64LIT(0x705a24b1fda5b5eb), +W64LIT(0x101e0ce2b170a9fc), +W64LIT(0x7ca821020e814caa), +W64LIT(0x0bc97ada1931ed13), +W64LIT(0x34df1711778c59ce), +W64LIT(0xd35020ef9226d2bf), +W64LIT(0x575d43e9805006b4), +W64LIT(0x91acebec9b1db840), +W64LIT(0x549b3f423b5945d9), +W64LIT(0x99a3ed9d3925163e), +W64LIT(0x7917a50a369a891d), +W64LIT(0xe372343cb4b6dc4e), +W64LIT(0x8d40e2bdd949e8fd), +W64LIT(0xcfbc29bed0728202), +W64LIT(0x969794857108ac12), +W64LIT(0xdd26de3db30cfa1b), +W64LIT(0x115c8b28d8773b74), +W64LIT(0xe9f9c92cc480a3d5), +W64LIT(0x4dc8b21b4116d0d3), +W64LIT(0x316093194f979c79), +W64LIT(0x5124bb4a0342806e), +W64LIT(0xb31408bcdef3cea8), +W64LIT(0xc1cad76cf158aaa6), +W64LIT(0x88ff66b5e1522d4a), +W64LIT(0xa8c37e8476b28a47), +W64LIT(0x15a188ea896b6c4b), +W64LIT(0xa24883940684f5dc), +W64LIT(0xda1da1545919ee49), +W64LIT(0x22b8e35045ee76e8), +W64LIT(0x6106af9925d28e9f), +W64LIT(0xef80318f4792250f), +W64LIT(0x663dd0f0cfc79acd), +W64LIT(0x302214d326900ef1), +W64LIT(0xdfa2255c61022bfe), +W64LIT(0xe6cdb0348cad19f9), +W64LIT(0x50663c806a4512e6), +W64LIT(0x65fbac5b74ced9a0), +W64LIT(0xc4755364c9436f11), +W64LIT(0x8fc419dc0b473918), +W64LIT(0x5c9439339961eba7), +W64LIT(0x3f166dcb6ebdb4dd), +W64LIT(0xba59890715ccf25e), +W64LIT(0xf0aa4475becf36df), +W64LIT(0x03c67cabbb09436d), +W64LIT(0xb99ff5acaec5b133), +W64LIT(0xf9e7c5ce75f00a29), +W64LIT(0x6df4aa2ad6f677de), +W64LIT(0xaeba8627f5a00c9d), +W64LIT(0xa573fcfdec91e18e), +W64LIT(0x7f6e5da9b5880fc7), +W64LIT(0xca03adb6e86947b5), +W64LIT(0x74a72773acb9e2d4), +W64LIT(0x604428534cd51c17), +W64LIT(0xf8a542041cf798a1), +W64LIT(0x448533a08a29ec25), +W64LIT(0x80f060c4436a8334), +W64LIT(0x0db082799a236bc9), +W64LIT(0xfa21b965cef94944), +W64LIT(0x64b92b911dc94b28), +W64LIT(0x7118a37b94a22763), +W64LIT(0xaff801ed9ca79e15), +W64LIT(0x1dae8e9b2b53c235), +W64LIT(0x13d870490a79ea91), +W64LIT(0x8a7b9dd4335cfcaf), +W64LIT(0x1f2a75faf95d13d0), +W64LIT(0xeec2b6452e95b787), +W64LIT(0xc34e2c0d23567b43), +W64LIT(0x47434f0b3120af48), +W64LIT(0xa18eff3fbd8db6b1), +W64LIT(0x98e16a57502284b6), +W64LIT(0x37196bbacc851aa3), +W64LIT(0x8e869e166240ab90), +W64LIT(0x9fda153eba3790e4), +W64LIT(0xf515c07d86d4f368), +W64LIT(0x72dedfd02fab640e), +W64LIT(0xe230b3f6ddb14ec6), +W64LIT(0x97d5134f180f3e9a), +W64LIT(0xe1f6cf5d66b80dab), +W64LIT(0xe78f37fee5aa8b71), +W64LIT(0xa30a045e6f836754), +W64LIT(0x90ee6c26f21a2ac8), +W64LIT(0xaa4785e5a4bc5ba2), +W64LIT(0x4e0eceb0fa1f93be), +W64LIT(0x94136fe4a3067df7), +W64LIT(0x7b935e6be49458f8), +W64LIT(0x9b2716fceb2bc7db), +W64LIT(0x840d63061276d40b), +W64LIT(0xed04caee959cf4ea), +W64LIT(0xea3fb5877f89e0b8), +W64LIT(0xb56df01f5de14872), +W64LIT(0x4935b1d9100a87ec), +W64LIT(0x82749ba5916452d1), +W64LIT(0x58693af1c87dbc98), +W64LIT(0x89bde17f8855bfc2), +W64LIT(0x677f573aa6c00845), +W64LIT(0xeb7d324d168e7230), +W64LIT(0x0284fb61d20ed1e5), +W64LIT(0xb190f3dd0cfd1f4d), +W64LIT(0x684b2e22eeedb269), +W64LIT(0x2bf562eb8ed14a1e), +W64LIT(0xe0b448970fbf9f23), +W64LIT(0x396f9568edaf3207), +W64LIT(0x52e2c7e1b84bc303), +W64LIT(0x77615bd817b0a1b9), +W64LIT(0x7e2cda63dc8f9d4f), +W64LIT(0xf22ebf146cc1e73a), +W64LIT(0xc08850a6985f382e), +W64LIT(0xd9dbddffe210ad24), +W64LIT(0xbfe60d0f2dd737e9), +W64LIT(0x9a659136822c5553), +W64LIT(0x87cb1fada97f9766), +W64LIT(0x4c8a35d12811425b), +W64LIT(0x83361c6ff863c059), +W64LIT(0xd212a725fb214037), +W64LIT(0x9e9892f4d330026c), +W64LIT(0x45c7b46ae32e7ead), +W64LIT(0x5baf465a7374fff5), +W64LIT(0xdc6459f7da0b6893), +W64LIT(0xd46b5f867833c6ed), +W64LIT(0x5dd6bef9f066792f), +W64LIT(0xcb412a7c816ed53d), +W64LIT(0x75e5a0b9c5be705c), +W64LIT(0xf6d3bcd63dddb005), +W64LIT(0xfb633eafa7fedbcc), +W64LIT(0xd529d84c11345465), +W64LIT(0xc9c5d11d536004d8), +W64LIT(0xdb5f269e301e7cc1), +W64LIT(0x86899867c07805ee), +W64LIT(0x3d9296aabcb36538), +W64LIT(0x2cce1d8264c45e4c), +W64LIT(0x5aedc1901a736d7d), +W64LIT(0x2e4ae6e3b6ca8fa9), +W64LIT(0x1e68f230905a8158), +W64LIT(0xdee0a2960805b976), +W64LIT(0xcd38d2df027c53e7), +W64LIT(0x6909a9e887ea20e1), +W64LIT(0x24c11bf3c6fcf032), +W64LIT(0x18110a9313480782), +W64LIT(0xa7f7079c3e9f306b), +W64LIT(0xd8995a358b173fac), +W64LIT(0x854fe4cc7b714683), +W64LIT(0xbd62f66effd9e60c), +W64LIT(0x14e30f20e06cfec3), +W64LIT(0x6e32d6816dff34b3), +W64LIT(0x217e9ffbfee73585), +W64LIT(0xc88756d73a679650), +W64LIT(0x359d90db1e8bcb46), +W64LIT(0x2645e09214f221d7), +W64LIT(0x04fd03c2511c573f), +W64LIT(0x739c581a46acf686), +W64LIT(0xb0d2741765fa8dc5), +W64LIT(0xa0cc78f5d48a2439), +W64LIT(0x5e10c2524b6f3a42), +W64LIT(0xe50bcc9f37a45a94), +W64LIT(0x53a0402bd14c518b), +W64LIT(0x413ab7a8b2322992), +W64LIT(0x203c183197e0a70d), +W64LIT(0xcc7a55156b7bc16f), +W64LIT(0x4601c8c158273dc0), +W64LIT(0xbea48ac544d0a561), +W64LIT(0x638254f8f7dc5f7a), +W64LIT(0xa6b580565798a2e3), +W64LIT(0x3cd01160d5b4f7b0), +W64LIT(0x8c026577b04e7a75), +W64LIT(0x7ad1d9a18d93ca70), +W64LIT(0x785522c05f9d1b95), +W64LIT(0x5f5245982268a8ca), +W64LIT(0x9551e82eca01ef7f), +W64LIT(0x0000000000000000), +W64LIT(0xbb1b0ecd7ccb60d6), +W64LIT(0x094d81bbcb3f3cf6), +W64LIT(0x28331e4035d80973), +W64LIT(0xf7913b1c54da228d), +W64LIT(0x6acfd5433ce3638c), +W64LIT(0x1bd77638a84144ef), +W64LIT(0x62c0d3329edbcdf2), +W64LIT(0x81b2e70e2a6d11bc), +W64LIT(0xd7ad232dc33a8580), +W64LIT(0x05bf8408381bc5b7), +W64LIT(0x33e468789d994d9c), +W64LIT(0xfedcbaa79fe51e7b), +W64LIT(0x4f4c497a93180136), +W64LIT(0x073b7f69ea151452), +W64LIT(0x0cf205b3f324f941), +W64LIT(0x382d12a284a8a08f), +W64LIT(0x1cec0951425450bd), +W64LIT(0x55d9b888525ed751), +W64LIT(0x6cb62de0bff1e556), +W64LIT(0xd1d4db8e4028035a), +W64LIT(0x25839c39affb62ba), +W64LIT(0x4af3cd72ab03c481), +W64LIT(0xa4317b3785967306), +W64LIT(0x1a95f1f2c146d667), +W64LIT(0x926a97472014fb2d), +W64LIT(0xb7e90b7e8fef9997), +W64LIT(0xcefeae74b975108a), +W64LIT(0x3e54ea0107ba2655), +W64LIT(0xd0965c44292f91d2), +W64LIT(0xab05022fcdbbc92a), +W64LIT(0xfd1ac60c24ec5d16), +W64LIT(0xfc5841c64debcf9e), +W64LIT(0xe4494b555ea3c81c), +W64LIT(0xb6ab8cb4e6e80b1f), +W64LIT(0x3beb6e093fa1e3e2), +W64LIT(0xf36c38de05c675b2), +W64LIT(0x9c1c6995013ed389), +W64LIT(0x8b391a1e5a5b6e27), +W64LIT(0xec464d24fc9b6662), +W64LIT(0xad7cfa8c4ea94ff0), +W64LIT(0x0f347918482dba2c), +W64LIT(0x9d5eee5f68394101), +W64LIT(0x7623dc127eb73331), +W64LIT(0x32a6efb2f49edf14), +W64LIT(0x2d8c9a480dc3ccc4), +W64LIT(0xb2568f76b7f45c20), +W64LIT(0x0e76fed2212a28a4), +W64LIT(0x48773613790d1564), +W64LIT(0x129af783637e7819), +W64LIT(0x080f0671a238ae7e), +W64LIT(0x365bec70a582882b), +W64LIT(0x42fccb03093b6aff), +W64LIT(0x0a8bfd1070367f9b), +W64LIT(0xff9e3d6df6e28cf3), +W64LIT(0xe8bb4ee6ad87315d), +W64LIT(0xc7b32fcf724a2c7c), +W64LIT(0xb8dd7266c7c223bb), +W64LIT(0x9328108d491369a5), +W64LIT(0x0679f8a3831286da), +W64LIT(0x270767587df5b35f), +W64LIT(0xa981f94e1fb518cf), +W64LIT(0x6b8d528955e4f104), +W64LIT(0x1667f44132622f26), +W64LIT(0x2ab7e521e7d6d896), +W64LIT(0xac3e7d4627aedd78), +W64LIT(0x7deaa6c86786de22), +W64LIT(0x1725738b5b65bdae), +W64LIT(0x4bb14ab8c2045609), +W64LIT(0x592bbd3ba17a2e10), +W64LIT(0xc20cabc74a51e9cb), +W64LIT(0x6f70514b04f8a63b), +W64LIT(0xbc2071a496de7484), +W64LIT(0x19538d597a4f950a), +W64LIT(0xf45747b7efd361e0), +W64LIT(0x43be4cc9603cf877), +W64LIT(0xc6f1a8051b4dbef4), +W64LIT(0xb42f77d534e6dafa), +W64LIT(0x40783062db35bb1a), +/* box 5 */ +W64LIT(0xf5a96c292deb0a4e), +W64LIT(0x211c9df6ee653c51), +W64LIT(0x04de5ddcbeeef596), +W64LIT(0xe1e5b06f7457c19f), +W64LIT(0x74ca30f014a54fb6), +W64LIT(0xc296f9f7c5457d85), +W64LIT(0x7d4ee08a484d10b0), +W64LIT(0xae87f2d0bf9b13ad), +W64LIT(0x8df4bb480e89afb7), +W64LIT(0x2d8b7a67d9a2d61e), +W64LIT(0x0f3559c8bd712adb), +W64LIT(0x541bc7312f013338), +W64LIT(0x9ec4848b636d5164), +W64LIT(0x952f809f60f28e29), +W64LIT(0x28984d8cb28d6357), +W64LIT(0xd4b5f1dfc38e361f), +W64LIT(0x5674135f7076b373), +W64LIT(0xb791a330042172ec), +W64LIT(0xab94c53bd4b4a6e4), +W64LIT(0xf17731f59305ffd8), +W64LIT(0x39c7a621801e1dcf), +W64LIT(0x20d1f7c13ba47c8e), +W64LIT(0x5e3da912f95facaa), +W64LIT(0xb1202a82e5b80731), +W64LIT(0x13303fc36de4fed3), +W64LIT(0x2e29c43e5314168a), +W64LIT(0x861fbf5c0d1670fa), +W64LIT(0x6458b16af3f771f1), +W64LIT(0x3043765bdcf642c9), +W64LIT(0x12fd55f4b825be0c), +W64LIT(0x0a266e23d65e9f92), +W64LIT(0x6595db5d2636312e), +W64LIT(0x85bd010587a0b06e), +W64LIT(0x9bd7b3600842e42d), +W64LIT(0xaa59af0c0175e63b), +W64LIT(0x240faa1d854a8918), +W64LIT(0xf464061ef82a4a91), +W64LIT(0x5c527d7ca6282ce1), +W64LIT(0x03a2be598ab6c094), +W64LIT(0x40571b7776bdf8e9), +W64LIT(0xe4f687841f7874d6), +W64LIT(0x115febad32937e98), +W64LIT(0x5108f0da442e8671), +W64LIT(0x9cab50e53c1ad12f), +W64LIT(0x33e1c8025640825d), +W64LIT(0x87d2d56bd8d73025), +W64LIT(0xc0f92d999a32fdce), +W64LIT(0x62e938d8126e042c), +W64LIT(0x4a717554a0e3677b), +W64LIT(0x0beb0414039fdf4d), +W64LIT(0xd6da25b19cf9b654), +W64LIT(0x55d6ad06fac073e7), +W64LIT(0x632452efc7af44f3), +W64LIT(0xb5fe775e5b56f2a7), +W64LIT(0x892ae694b0675a21), +W64LIT(0x7a32030f7c1525b2), +W64LIT(0x5d9f174b73e96c3e), +W64LIT(0xc35b93c010843d5a), +W64LIT(0x373f95dee8ae77cb), +W64LIT(0xfb515fd6455b604a), +W64LIT(0xa9fb11558bc326af), +W64LIT(0x22be23af64d3fcc5), +W64LIT(0xa8367b625e026670), +W64LIT(0xb8a4faf8b9505837), +W64LIT(0x785dd7612362a5f9), +W64LIT(0x588c20a018c6d977), +W64LIT(0xea0eb47b77c81ed2), +W64LIT(0xa6ce489d36b20c74), +W64LIT(0x0c97e79137c7ea4f), +W64LIT(0x7c838abd9d8c506f), +W64LIT(0x57b97968a5b7f3ac), +W64LIT(0x6c110b277ade6e28), +W64LIT(0xc785ce1cae6ac8cc), +W64LIT(0x1581b6718c7d8b0e), +W64LIT(0x614b868198d8c4b8), +W64LIT(0x27ad14440ffc498c), +W64LIT(0xdb80a8177eff1cc4), +W64LIT(0x472bf8f242e5cdeb), +W64LIT(0x8a8858cd3ad19ab5), +W64LIT(0xf60bd270a75dcada), +W64LIT(0x43f5a52efc0b387d), +W64LIT(0x6ddc6110af1f2ef7), +W64LIT(0xf0ba5bc246c4bf07), +W64LIT(0x6fb3b57ef068aebc), +W64LIT(0x18db3bd76e7b219e), +W64LIT(0x903cb7740bdd3b60), +W64LIT(0x7bff6938a9d4656d), +W64LIT(0xbdb7cd13d27fed7e), +W64LIT(0x051337eb6b2fb549), +W64LIT(0x77688ea99e138f22), +W64LIT(0xd9ef7c7921889c8f), +W64LIT(0x077ce38534583502), +W64LIT(0xf318e59bcc727f93), +W64LIT(0xb34ffeecbacf877a), +W64LIT(0xe9ac0a22fd7ede46), +W64LIT(0xfc2dbc5371035548), +W64LIT(0x026fd46e5f77804b), +W64LIT(0xe53bedb3cab93409), +W64LIT(0xcc6eca08adf51781), +W64LIT(0xe028da58a1968140), +W64LIT(0x3a6518780aa8dd5b), +W64LIT(0xce011e66f28297ca), +W64LIT(0xa4a19cf369c58c3f), +W64LIT(0xc5ea1a72f11d4887), +W64LIT(0xc427704524dc0858), +W64LIT(0x4238cf1929ca78a2), +W64LIT(0x481ea13aff94e730), +W64LIT(0xdf5ef5cbc011e952), +W64LIT(0x80ae36eeec8f0527), +W64LIT(0x5ae3f4ce47b1593c), +W64LIT(0xcda3a03f7834575e), +W64LIT(0x71d9071b7f8afaff), +W64LIT(0xcadf43ba4c6c625c), +W64LIT(0x1623082806cb4b9a), +W64LIT(0x17ee621fd30a0b45), +W64LIT(0x448946abc8530d7f), +W64LIT(0x974054f13f850e62), +W64LIT(0x73b6d37520fd7ab4), +W64LIT(0xc8b097d4131be217), +W64LIT(0x9f09eebcb6ac11bb), +W64LIT(0x45442c9c1d924da0), +W64LIT(0x1b79858ee4cde10a), +W64LIT(0x0984d07a5ce85f06), +W64LIT(0x4cc0fce6417a12a6), +W64LIT(0x99b8670e57356466), +W64LIT(0xad254c89352dd339), +W64LIT(0x322ca2358381c282), +W64LIT(0xcfcc74512743d715), +W64LIT(0x6b6de8a24e865b2a), +W64LIT(0xda4dc220ab3e5c1b), +W64LIT(0x88e78ca365a61afe), +W64LIT(0x939e092d816bfbf4), +W64LIT(0xcb12298d99ad2283), +W64LIT(0xeed0e9a7c926eb44), +W64LIT(0x98750d3982f424b9), +W64LIT(0xd5789be8164f76c0), +W64LIT(0xbe15734a58c92dea), +W64LIT(0x49d3cb0d2a55a7ef), +W64LIT(0x67fa0f337941b165), +W64LIT(0x8c39d17fdb48ef68), +W64LIT(0x25c2c02a508bc9c7), +W64LIT(0x349d2b876218b75f), +W64LIT(0x70146d2caa4bba20), +W64LIT(0x1c05660bd095d408), +W64LIT(0xfe42683d2e74d503), +W64LIT(0x9a1ad957dd83a4f2), +W64LIT(0xf2d58fac19b33f4c), +W64LIT(0x81635cd9394e45f8), +W64LIT(0xb65cc907d1e03233), +W64LIT(0xdd3121a59f666919), +W64LIT(0x318e1c6c09370216), +W64LIT(0x8b4532faef10da6a), +W64LIT(0x191651e0bbba6141), +W64LIT(0x3f762f9361876812), +W64LIT(0xb96990cf6c9118e8), +W64LIT(0xb4331d698e97b278), +W64LIT(0xd822164ef449dc50), +W64LIT(0x84706b325261f0b1), +W64LIT(0x4eaf28881e0d92ed), +W64LIT(0x69023ccc11f1db61), +W64LIT(0x66376504ac80f1ba), +W64LIT(0x0849ba4d89291fd9), +W64LIT(0xff8f020afbb595dc), +W64LIT(0x50c59aed91efc6ae), +W64LIT(0x1dc80c3c055494d7), +W64LIT(0x1e6ab2658fe25443), +W64LIT(0x3d19fbfd3ef0e859), +W64LIT(0xfa9c35e1909a2095), +W64LIT(0x52aa4e83ce9846e5), +W64LIT(0x419a7140a37cb836), +W64LIT(0xa07fc12fd72b79a9), +W64LIT(0x68cf56fbc4309bbe), +W64LIT(0x01cd6a37d5c140df), +W64LIT(0x9253631a54aabb2b), +W64LIT(0xd06bac037d60c389), +W64LIT(0x295527bb674c2388), +W64LIT(0xd204786d221743c2), +W64LIT(0x0000000000000000), +W64LIT(0xf7c6b847729c8a05), +W64LIT(0xdcfc4b924aa729c6), +W64LIT(0xe38a64012b2041d4), +W64LIT(0xb28294db6f0ec7a5), +W64LIT(0x9d663ad2e9db91f0), +W64LIT(0x91f1dd43de1c7bbf), +W64LIT(0x6086ecb64d198467), +W64LIT(0x59414a97cd0799a8), +W64LIT(0xace826bee0ec93e6), +W64LIT(0xa56cf6c4bc04cce0), +W64LIT(0x727bb942f53c3a6b), +W64LIT(0x6e7edf4925a9ee63), +W64LIT(0x26607e73da3d0953), +W64LIT(0xe75439dd95ceb442), +W64LIT(0x7990bd56f6a3e526), +W64LIT(0xecbf3dc996516b0f), +W64LIT(0x76a5e49e4bd2cffd), +W64LIT(0x968d3ec6ea444ebd), +W64LIT(0x5b2e9ef9927019e3), +W64LIT(0x6aa082959b471bf5), +W64LIT(0xbb0644a133e698a3), +W64LIT(0x830c88b76639c5b3), +W64LIT(0xe2470e36fee1010b), +W64LIT(0xb0ed40b5307947ee), +W64LIT(0x355041b0b7d9f780), +W64LIT(0x8e560511843f6f23), +W64LIT(0x7f2134e4173a90fb), +W64LIT(0x2af799e2edfae31c), +W64LIT(0x4bbc1f63752227a4), +W64LIT(0xf8f3e18fcfeda0de), +W64LIT(0x0d5a8da6e206aa90), +W64LIT(0x2c4610500c6396c1), +W64LIT(0xde939ffc15d0a98d), +W64LIT(0xaf4a98e76a5a5372), +W64LIT(0x8f9b6f2651fe2ffc), +W64LIT(0x36f2ffe93d6f3714), +W64LIT(0x0ef833ff68b06a04), +W64LIT(0xe69953ea400ff49d), +W64LIT(0x23734998b112bc1a), +W64LIT(0x3ebb45a4b44628cd), +W64LIT(0x1ab4efb9310ca1d5), +W64LIT(0x2fe4ae0986d55655), +W64LIT(0xebc3de4ca2095e0d), +W64LIT(0x536724b41b59063a), +W64LIT(0x46e692c597248d34), +W64LIT(0x2b3af3d5383ba3c3), +W64LIT(0x3ba8724fdf699d84), +W64LIT(0xc13447ae4ff3bd11), +W64LIT(0x4d0d96d194bb5279), +W64LIT(0xfde0d664a4c21597), +W64LIT(0xd7174f864938f68b), +W64LIT(0x7eec5ed3c2fbd024), +W64LIT(0xbfd8197d8d086d35), +W64LIT(0x4f6242bfcbccd232), +W64LIT(0xa70322aae3734cab), +W64LIT(0xa3dd7f765d9db93d), +W64LIT(0x94e2eaa8b533cef6), +W64LIT(0x144cdc4659bccbd1), +W64LIT(0xc648a42b7bab8813), +W64LIT(0xf93e8bb81a2ce001), +W64LIT(0xbacb2e96e627d87c), +W64LIT(0xbc7aa72407beada1), +W64LIT(0xc97dfde3c6daa2c8), +W64LIT(0xa1b2ab1802ea3976), +W64LIT(0x1fa7d8525a23149c), +W64LIT(0x75075ac7c1640f69), +W64LIT(0xe861601528bf9e99), +W64LIT(0xa2101541885cf9e2), +W64LIT(0xef1d83901ce7ab9b), +W64LIT(0x06b189b2e19975dd), +W64LIT(0x380acc1655df5d10), +W64LIT(0x1092819ae7523e47), +W64LIT(0xd3c9125af7d6031d), +W64LIT(0xd1a6c634a8a18356), +W64LIT(0x5ff0c3252c9eec75), +W64LIT(0x82c1e280b3f8856c), +W64LIT(0xed7257fe43902bd0), +W64LIT(0x3cd491caeb31a886), +/* box 6 */ +W64LIT(0x94af9eb6fad9e7df), +W64LIT(0x9208ae5e03c94ddd), +W64LIT(0x1d8de8d67158480b), +W64LIT(0xfd093cd2ba147af8), +W64LIT(0xa45ceb22e6597ccf), +W64LIT(0x9bbde6e77bf113da), +W64LIT(0xe4edf4b465fffe5c), +W64LIT(0x7125622e4e8d2a2f), +W64LIT(0x1791b81b8f68430d), +W64LIT(0xb56a63d1902195c0), +W64LIT(0xa980832b30d2ee67), +W64LIT(0x4c0a7fb384862397), +W64LIT(0xed58bc0d1dc7a05b), +W64LIT(0x5955d7f05c4d0637), +W64LIT(0xd2b9b1c8806fcf4e), +W64LIT(0x06a730e8f910aa02), +W64LIT(0xb8b60bd846aa0768), +W64LIT(0x45bf370afcbe7d90), +W64LIT(0x16f6b0375ec370a1), +W64LIT(0x892276608b81afd4), +W64LIT(0xdcccc1b5d0ec08e7), +W64LIT(0xe856949162df5f58), +W64LIT(0x82592e81a41a977e), +W64LIT(0xac8eabb74fca1164), +W64LIT(0xfac9041692afe356), +W64LIT(0x3b882d75331ba3ba), +W64LIT(0xa39cd3e6cee2e561), +W64LIT(0xd077a190d7cca9e3), +W64LIT(0x9c7dde23534a8a74), +W64LIT(0x80973ed9f3b9f1d3), +W64LIT(0xce535132209cb4e9), +W64LIT(0xaa299b5fb6dabb66), +W64LIT(0x2d7e9d426dd8d31b), +W64LIT(0x8a8b6e140d89fad5), +W64LIT(0x6ca88af83fd56224), +W64LIT(0xf5db7c4713871753), +W64LIT(0xeef1a4799bcff55a), +W64LIT(0x76e55aea6636b381), +W64LIT(0x8ee24ea4a33a367a), +W64LIT(0x25acddd7c44bbeb0), +W64LIT(0x9adaeecbaa5a2076), +W64LIT(0x0e75707d5083c7a9), +W64LIT(0x2bd9adaa94c87919), +W64LIT(0x19e4c866dfeb84a4), +W64LIT(0x129f9087f070bc0e), +W64LIT(0xd9c2e929aff4f7e4), +W64LIT(0x6f01928cb9dd3725), +W64LIT(0x39463d2d64b8c517), +W64LIT(0xebff8ce5e4d70a59), +W64LIT(0xb40d6bfd418aa66c), +W64LIT(0xf21b44833b3c8efd), +W64LIT(0x3654457ce5903112), +W64LIT(0x431807e205aed792), +W64LIT(0xb10343613e92596f), +W64LIT(0x0a1c50cdfe300b06), +W64LIT(0x778252c6b79d802d), +W64LIT(0x0cbb60250720a104), +W64LIT(0xe1e3dc281ae7015f), +W64LIT(0x0f1278518128f405), +W64LIT(0x47712752ab1d1b3d), +W64LIT(0xe24ac45c9cef545e), +W64LIT(0x1ceae0faa0f37ba7), +W64LIT(0x9814fe93fdf946db), +W64LIT(0xec3fb421cc6c93f7), +W64LIT(0x833e26ad75b1a4d2), +W64LIT(0x6b68b23c176efb8a), +W64LIT(0x4904572ffb9edc94), +W64LIT(0x4bca4777ac3dba39), +W64LIT(0x2762cd8f93e8d81d), +W64LIT(0x9eb3ce7b04e9ecd9), +W64LIT(0xc2e8311727bc15ed), +W64LIT(0xea9884c9357c39f5), +W64LIT(0xfc6e34fe6bbf4954), +W64LIT(0x13f898ab21db8fa2), +W64LIT(0xb7a47389c782f36d), +W64LIT(0x7b3932e3b0bd2129), +W64LIT(0xaf27b3c3c9c24465), +W64LIT(0xb6c37ba51629c0c1), +W64LIT(0x84fe1e695d0a3d7c), +W64LIT(0x1a4dd01259e3d1a5), +W64LIT(0xab4e9373677188ca), +W64LIT(0x90c6be06546a2b70), +W64LIT(0xf37c4cafea97bd51), +W64LIT(0x647aca6d96460f8f), +W64LIT(0x4ec46febd325453a), +W64LIT(0x3e8605e94c035cb9), +W64LIT(0x0ddc6809d68b92a8), +W64LIT(0x8bec6638dc22c979), +W64LIT(0x67d3d219104e5a8e), +W64LIT(0x2abea58645634ab5), +W64LIT(0x5b9bc7a80bee609a), +W64LIT(0x936fa672d2627e71), +W64LIT(0x7d9e020b49ad8b2b), +W64LIT(0x5832dfdc8de6359b), +W64LIT(0xc7e6198b58a4eaee), +W64LIT(0xd41e8120797f654c), +W64LIT(0xf4bc746bc22c24ff), +W64LIT(0xe084d404cb4c32f3), +W64LIT(0x48635f032a35ef38), +W64LIT(0x8757061ddb02687d), +W64LIT(0x522e8f1173d63e9d), +W64LIT(0xbcdf2b68e819cbc7), +W64LIT(0xbf76331c6e119ec6), +W64LIT(0x08d24095a9936dab), +W64LIT(0x728c7a5ac8857f2e), +W64LIT(0xd110a9bc06679a4f), +W64LIT(0x1f43f88e26fb2ea6), +W64LIT(0xb2aa5b15b89a0c6e), +W64LIT(0x4aad4f5b7d968995), +W64LIT(0x9fd4c657d542df75), +W64LIT(0x323d65cc4b23fdbd), +W64LIT(0xc38f393bf6172641), +W64LIT(0xa152c3be994183cc), +W64LIT(0x9d1ad60f82e1b9d8), +W64LIT(0xe744ecc0e3f7ab5d), +W64LIT(0x38213501b513f6bb), +W64LIT(0xade9a39b9e6122c8), +W64LIT(0x37334d50343b02be), +W64LIT(0x55eeb7d55b6da733), +W64LIT(0x970686c27cd1b2de), +W64LIT(0x427f0fced405e43e), +W64LIT(0xc026214f701f7340), +W64LIT(0x40b11f9683a68293), +W64LIT(0x02ce105857a366ad), +W64LIT(0x7e371a7fcfa5de2a), +W64LIT(0xffc72c8aedb71c55), +W64LIT(0x68c1aa489166ae8b), +W64LIT(0xc68111a7890fd942), +W64LIT(0x79f722bbe71e4784), +W64LIT(0xd579890ca8d456e0), +W64LIT(0x70426a029f261983), +W64LIT(0xb0644b4def396ac3), +W64LIT(0xdb0cf971f8579149), +W64LIT(0x5489bff98ac6949f), +W64LIT(0x046920b0aeb3ccaf), +W64LIT(0x7cf90a279806b887), +W64LIT(0x050e289c7f18ff03), +W64LIT(0x651dc24147ed3c23), +W64LIT(0x5e95ef3474f69f99), +W64LIT(0x6dcf82d4ee7e5188), +W64LIT(0x8f854688729105d6), +W64LIT(0x81f036f52212c27f), +W64LIT(0xb9d103f4970134c4), +W64LIT(0x5349873da27d0d31), +W64LIT(0x20a2f54bbb5341b3), +W64LIT(0xf0d554db6c9fe850), +W64LIT(0x07c038c428bb99ae), +W64LIT(0x30f375941c809b10), +W64LIT(0x3fe10dc59da86f15), +W64LIT(0x46162f7e7ab62891), +W64LIT(0xe623e4ec325c98f1), +W64LIT(0xfea024a63c1c2ff9), +W64LIT(0x349a5524b23357bf), +W64LIT(0x35fd5d0863986413), +W64LIT(0x96618eeead7a8172), +W64LIT(0xcb5d79ae5f844bea), +W64LIT(0x21c5fd676af8721f), +W64LIT(0x5720a78d0ccec19e), +W64LIT(0xf6726433958f4252), +W64LIT(0x8d4b56d02532637b), +W64LIT(0x24cbd5fb15e08d1c), +W64LIT(0x3aef2559e2b09016), +W64LIT(0x5afccf84da455336), +W64LIT(0x51879765f5de6b9c), +W64LIT(0x2917bdf2c36b1fb4), +W64LIT(0xa7f5f356605129ce), +W64LIT(0xc1412963a1b440ec), +W64LIT(0x3d2f1d9dca0b09b8), +W64LIT(0xa53be30e37f24f63), +W64LIT(0x5ff2e718a55dac35), +W64LIT(0xa2fbdbca1f49d6cd), +W64LIT(0xf7156c1f442471fe), +W64LIT(0x7a5e3acf61161285), +W64LIT(0xca3a71828e2f7846), +W64LIT(0x1b2ad83e8848e209), +W64LIT(0xa8e78b07e179ddcb), +W64LIT(0xef96ac554a64c6f6), +W64LIT(0x0000000000000000), +W64LIT(0x6013eadd38f5c320), +W64LIT(0x3c4815b11ba03a14), +W64LIT(0x09b548b978385e07), +W64LIT(0x226ce513ecf0271e), +W64LIT(0x63baf2a9befd9621), +W64LIT(0x44d83f262d154e3c), +W64LIT(0xcdfa4946a694e1e8), +W64LIT(0x113688f37678e90f), +W64LIT(0x859916458ca10ed0), +W64LIT(0xc52809d30f078c43), +W64LIT(0x4d6d779f552d103b), +W64LIT(0x1e24f0a2f7501d0a), +W64LIT(0x0167082cd1ab33ac), +W64LIT(0x1438a06f0960160c), +W64LIT(0xf9601c6214a7b657), +W64LIT(0xa035cb9248eab060), +W64LIT(0x50e09f4924755830), +W64LIT(0xd7b79954ff77304d), +W64LIT(0xe58afc98b454cdf0), +W64LIT(0x03a9187486085501), +W64LIT(0x62ddfa856f56a58d), +W64LIT(0xc44f01ffdeacbfef), +W64LIT(0x73eb7276192e4c82), +W64LIT(0xd6d091782edc03e1), +W64LIT(0xfbae0c3a4304d0fa), +W64LIT(0x9973f6bf2c527577), +W64LIT(0x105180dfa7d3daa3), +W64LIT(0x2605c5a34243ebb1), +W64LIT(0x91a1b62a85c118dc), +W64LIT(0xc99369f608272d47), +W64LIT(0x5d3cf740f2feca98), +W64LIT(0xcf34591ef1378745), +W64LIT(0xc8f461dad98c1eeb), +W64LIT(0x0b7b58e12f9b38aa), +W64LIT(0xe32dcc704d4467f2), +W64LIT(0x754c429ee03ee680), +W64LIT(0xd3deb9e451c4fce2), +W64LIT(0x6e669aa068760489), +W64LIT(0x66b4da35c1e56922), +W64LIT(0x4fa367c7028e7696), +W64LIT(0xba781b80110961c5), +W64LIT(0x41d617ba520db13f), +W64LIT(0x335a6de09a88ce11), +W64LIT(0xdf65d9c156e45de6), +W64LIT(0xcc9d416a773fd244), +W64LIT(0x5c5bff6c2355f934), +W64LIT(0x2870b5de12c02c18), +W64LIT(0x155fa843d8cb25a0), +W64LIT(0x78902a9736b57428), +W64LIT(0xae40bbef186977c9), +W64LIT(0x88457e4c5a2a9c78), +W64LIT(0x6a0fba10c6c5c826), +W64LIT(0x7f5012531e0eed86), +W64LIT(0x8c2c5efcf49950d7), +W64LIT(0x31947db8cd2ba8bc), +W64LIT(0x2c19956ebc73e0b7), +W64LIT(0x230bed3f3d5b14b2), +W64LIT(0x69a6a26440cd9d27), +W64LIT(0x86300e310aa95bd1), +W64LIT(0xb3cd533969313fc2), +W64LIT(0x1883c04a0e40b708), +W64LIT(0xf1b25cf7bd34dbfc), +W64LIT(0x2fb08d1a3a7bb5b6), +W64LIT(0xd8a5e1057e5fc448), +W64LIT(0xddabc99901473b4b), +W64LIT(0xde02d1ed874f6e4a), +W64LIT(0xbdb8234439b2f86b), +W64LIT(0x5647afa1dd65f232), +W64LIT(0x2ed78536ebd0861a), +W64LIT(0xe9319cbdb3746cf4), +W64LIT(0xa692fb7ab1fa1a62), +W64LIT(0x742b4ab23195d52c), +W64LIT(0x95c8969a2b72d473), +W64LIT(0x6174e2f1e95ef08c), +W64LIT(0xf807144ec50c85fb), +W64LIT(0xbe113b30bfbaad6a), +W64LIT(0xda6bf15d29fca2e5), +W64LIT(0xbb1f13acc0a25269), +/* box 7 */ +W64LIT(0xc22b27f0f9e37bf9), +W64LIT(0x93fad23f0955ef09), +W64LIT(0x32ed4b84a22a91a2), +W64LIT(0x3898b57bcc61b1cc), +W64LIT(0x55825ba9ad98e5ad), +W64LIT(0xb2eeb8069421ec94), +W64LIT(0xc7eb5875ce3c6bce), +W64LIT(0x4b1dac5d1f45851f), +W64LIT(0xc16ba1204705d847), +W64LIT(0xc5380f461a2ba91a), +W64LIT(0xb908971a909bad90), +W64LIT(0x303e1cb7763d5376), +W64LIT(0xe6ff324c53486853), +W64LIT(0x6d1aeed261f95461), +W64LIT(0x0193d1e36af1616a), +W64LIT(0x51d1f5cff0b694f0), +W64LIT(0x29b2c3f52728e127), +W64LIT(0x112a768eeb4950eb), +W64LIT(0x8fb672f86f9f4d6f), +W64LIT(0xf0c66c745bc9ea5b), +W64LIT(0x3f8b9dcd2fa9632f), +W64LIT(0x65bc471edba5b6db), +W64LIT(0x4d9d5508967c3696), +W64LIT(0x3a4be24818767318), +W64LIT(0x2794936c144db014), +W64LIT(0x2af2452599ce4299), +W64LIT(0x4a8e7dbe75b4e475), +W64LIT(0x9ddc82a63a30be3a), +W64LIT(0xade29e114c0ded4c), +W64LIT(0xd1d2064dc6bde9c6), +W64LIT(0x7da349bfe04165e0), +W64LIT(0x6b9a1787e8c0e7e8), +W64LIT(0xa54437ddf6510ff6), +W64LIT(0x2254ece92392a023), +W64LIT(0x79f0e7d9bd6f14bd), +W64LIT(0x57510c9a798f2779), +W64LIT(0x346db2d12b13222b), +W64LIT(0x54118a4ac76984c7), +W64LIT(0xefca4a6383e5eb83), +W64LIT(0xca8d8e3c43bf9943), +W64LIT(0xfc336bdebcbb79bc), +W64LIT(0x3e184c2e45580245), +W64LIT(0xf495c21206e79b06), +W64LIT(0xff73ed0e025dda02), +W64LIT(0x4228d472cfe806cf), +W64LIT(0xbcc8e89fa744bda7), +W64LIT(0xab626744c5345ec5), +W64LIT(0xb6bd1660c90f9dc9), +W64LIT(0xb72ec783a3fefca3), +W64LIT(0x8be5dc9e32b13c32), +W64LIT(0x485d2a8da1a326a1), +W64LIT(0xc6788996a4cd0aa4), +W64LIT(0x40fb83411bffc41b), +W64LIT(0x08a6a9ccba5ce2ba), +W64LIT(0xf386eaa4e52f49e5), +W64LIT(0x1acc5992eff311ef), +W64LIT(0xa2571f6b1599dd15), +W64LIT(0x44a82d2746d1b546), +W64LIT(0x70c59ff66dc2976d), +W64LIT(0x8d6525cbbb888fbb), +W64LIT(0x963aadba3e8aff3e), +W64LIT(0x7c30985c8ab0048a), +W64LIT(0x607c389bec7aa6ec), +W64LIT(0xa822e1947bd2fd7b), +W64LIT(0x034086d0bee6a3be), +W64LIT(0x66fcc1ce65431565), +W64LIT(0xb37d69e5fed08dfe), +W64LIT(0x2f323aa0ae1152ae), +W64LIT(0x56c2dd79137e4613), +W64LIT(0x31adcd541ccc321c), +W64LIT(0xdff456d4f5d8b8f5), +W64LIT(0xf9f3145b8b64698b), +W64LIT(0x764566a3e4fb24e4), +W64LIT(0x0cf507aae77293e7), +W64LIT(0x59775c034aea764a), +W64LIT(0xb89b46f9fa6accfa), +W64LIT(0xe8d962d5602d3960), +W64LIT(0x17aa8fdb6270e362), +W64LIT(0x1c4ca0c766caa266), +W64LIT(0x2de16d937a06907a), +W64LIT(0x2547c45fc05a72c0), +W64LIT(0x0fb5817a59943059), +W64LIT(0x0680f9558939b389), +W64LIT(0x16395e3808818208), +W64LIT(0xac714ff226fc8c26), +W64LIT(0xa9b1307711239c11), +W64LIT(0xec8accb33d03483d), +W64LIT(0x6c893f310b08350b), +W64LIT(0xc4abdea570dac870), +W64LIT(0xba4811ca2e7d0e2e), +W64LIT(0xf155bd9731388b31), +W64LIT(0xdd2701e721cf7a21), +W64LIT(0xe94ab3360adc580a), +W64LIT(0x23c73d0a4963c149), +W64LIT(0x5cb723867d35667d), +W64LIT(0x5042242c9a47f59a), +W64LIT(0x198cdf425115b251), +W64LIT(0x0a75feff6e4b206e), +W64LIT(0xfda0ba3dd64a18d6), +W64LIT(0xcede205a1e91e81e), +W64LIT(0xd041d7aeac4c88ac), +W64LIT(0xe42c657f875faa87), +W64LIT(0x36bee5e2ff04e0ff), +W64LIT(0x6fc9b9e1b5ee96b5), +W64LIT(0x998f2cc0671ecf67), +W64LIT(0xd301517e12aa2b12), +W64LIT(0xaea218c1f2eb4ef2), +W64LIT(0xda342951c207a8c2), +W64LIT(0x61efe978868bc786), +W64LIT(0x7f701e8c3456a734), +W64LIT(0x0be62f1c04ba4104), +W64LIT(0x9129850cdd422ddd), +W64LIT(0xd6c12efb25753b25), +W64LIT(0xe33f4dc964977864), +W64LIT(0x1579d8e8b66721b6), +W64LIT(0xf860c5b8e19508e1), +W64LIT(0x7496319030ece630), +W64LIT(0x88a55a4e8c579f8c), +W64LIT(0xcf4df1b974608974), +W64LIT(0x10b9a76d81b83181), +W64LIT(0x0e26509933655133), +W64LIT(0x43bb0591a51967a5), +W64LIT(0x926903dc63a48e63), +W64LIT(0x9c4f534550c1df50), +W64LIT(0x3bd833ab72871272), +W64LIT(0xa4d7e63e9ca06e9c), +W64LIT(0xb46e41531d185f1d), +W64LIT(0x126af05e55aff355), +W64LIT(0x24d415bcaaab13aa), +W64LIT(0x1e9ff7f4b2dd60b2), +W64LIT(0x05c07f8537df1037), +W64LIT(0x467b7a1492c67792), +W64LIT(0x2087bbdaf78562f7), +W64LIT(0x819022615cfa1c5c), +W64LIT(0xcd9ea68aa0774ba0), +W64LIT(0xa79760ee2246cd22), +W64LIT(0x8343755288edde88), +W64LIT(0x58e48de0201b1720), +W64LIT(0x7216c8c5b9d555b9), +W64LIT(0x372d340195f58195), +W64LIT(0xa11799bbab7f7eab), +W64LIT(0x9f0fd595ee277cee), +W64LIT(0x676f102d0fb2740f), +W64LIT(0x9e9c047684d61d84), +W64LIT(0x49cefb6ecb5247cb), +W64LIT(0xd41279c8f162f9f1), +W64LIT(0x1f0c2617d82c01d8), +W64LIT(0x97a97c59547b9e54), +W64LIT(0xe76ce3af39b90939), +W64LIT(0xc3b8f61393121a93), +W64LIT(0x5ba40b309efdb49e), +W64LIT(0xea0a35e6b43afbb4), +W64LIT(0x5a37dad3f40cd5f4), +W64LIT(0x14ea090bdc9640dc), +W64LIT(0x5e6474b5a922a4a9), +W64LIT(0xfee03ced68acbb68), +W64LIT(0x071328b6e3c8d2e3), +W64LIT(0x5302a2fc24a15624), +W64LIT(0x85c38c0701d46d01), +W64LIT(0x3d58cafefbbea1fb), +W64LIT(0x84505de46b250c6b), +W64LIT(0x642f96fdb154d7b1), +W64LIT(0xbf886e4f19a21e19), +W64LIT(0x02d35733d417c2d4), +W64LIT(0x68da915756264456), +W64LIT(0x8710db34d5c3afd5), +W64LIT(0x0d66d6498d83f28d), +W64LIT(0x7b23b0ea6978d669), +W64LIT(0x1b5f887185027085), +W64LIT(0x3ccb1b1d914fc091), +W64LIT(0x0453ae665d2e715d), +W64LIT(0xcb1e5fdf294ef829), +W64LIT(0xf6469521d2f059d2), +W64LIT(0xb03def3540362e40), +W64LIT(0x633cbe4b529c0552), +W64LIT(0xf7d544c2b80138b8), +W64LIT(0x7ab061090389b703), +W64LIT(0x0000000000000000), +W64LIT(0xdba7f8b2a8f6c9a8), +W64LIT(0x35fe633241e24341), +W64LIT(0x21146a399d74039d), +W64LIT(0xd581a82b9b93989b), +W64LIT(0x0935782fd0ad83d0), +W64LIT(0x5ff7a556c3d3c5c3), +W64LIT(0xaf31c922981a2f98), +W64LIT(0x90ba54efb7b34cb7), +W64LIT(0x5291731f4e50374e), +W64LIT(0xc0f870c32df4b92d), +W64LIT(0x7ee3cf6f5ea7c65e), +W64LIT(0xe07fcb19da71dbda), +W64LIT(0x4eddd3d8289a9528), +W64LIT(0x13f921bd3f5e923f), +W64LIT(0xf50613f16c16fa6c), +W64LIT(0x981cfd230defae0d), +W64LIT(0x4c0e84ebfc8d57fc), +W64LIT(0x82d0a4b1e21cbfe2), +W64LIT(0x89368bade6a6fee6), +W64LIT(0xd292809d785b4a78), +W64LIT(0x47e8abf7f83716f8), +W64LIT(0x8e25a31b056e2c05), +W64LIT(0xd752ff184f845a4f), +W64LIT(0xcc0d7769ca862aca), +W64LIT(0x694940b43cd7253c), +W64LIT(0x2ea1eb43c4e033c4), +W64LIT(0xde6787379f29d99f), +W64LIT(0x181f0ea13be4d33b), +W64LIT(0x416852a2710ea571), +W64LIT(0x62af6fa8386d6438), +W64LIT(0xa0844858c18e1fc1), +W64LIT(0x337e9a67c8dbf0c8), +W64LIT(0x2c72bc7010f7f110), +W64LIT(0xbd5b397ccdb5dccd), +W64LIT(0xd8e77e6216106a16), +W64LIT(0x86830ad7bf32cebf), +W64LIT(0x4f4e023b426bf442), +W64LIT(0xe5bfb49cedaecbed), +W64LIT(0x8a760d7d58405d58), +W64LIT(0xe2ac9c2a0e66190e), +W64LIT(0xb5fd90b077e93e77), +W64LIT(0xdcb4d0044b3e1b4b), +W64LIT(0x453bfcc42c20d42c), +W64LIT(0xed191d5057f22957), +W64LIT(0xe1ec1afab080bab0), +W64LIT(0xee599b80e9148ae9), +W64LIT(0x2607428f7ebcd17e), +W64LIT(0x5d24f26517c40717), +W64LIT(0x6a09c66482318682), +W64LIT(0xa604b10d48b7ac48), +W64LIT(0xbe1bbfac73537f73), +W64LIT(0x282112164dd9804d), +W64LIT(0x7505e0735a1d875a), +W64LIT(0x73851926d32434d3), +W64LIT(0xd974af817ce10b7c), +W64LIT(0xeb99e405decb9ade), +W64LIT(0x9b5c7bf3b3090db3), +W64LIT(0xfab3928b3582ca35), +W64LIT(0x8003f382360b7d36), +W64LIT(0x94e9fa89ea9d3dea), +W64LIT(0xb1ae3ed62ac74f2a), +W64LIT(0x9acfaa10d9f86cd9), +W64LIT(0x390b6498a690d0a6), +W64LIT(0xf2153b478fde288f), +W64LIT(0x71564e150733f607), +W64LIT(0xa3c4ce887f68bc7f), +W64LIT(0xaaf1b6a7afc53faf), +W64LIT(0x1ddf71240c3bc30c), +W64LIT(0x77d6b7408e0a458e), +W64LIT(0x2b6194c6f33f23f3), +W64LIT(0xc9cd08ecfd593afd), +W64LIT(0xc85ed90f97a85b97), +W64LIT(0x8cf6f428d179eed1), +W64LIT(0x957a2b6a806c5c80), +W64LIT(0xbbdbc029448c6f44), +W64LIT(0x7863363ad79e75d7), +W64LIT(0x6e5a6802df1ff7df), +W64LIT(0xfb2043685f73ab5f), +}; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/simeck.cpp b/external/ours/library/crypto/src/shared/original/simeck.cpp new file mode 100755 index 000000000..a1a5316e1 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/simeck.cpp @@ -0,0 +1,154 @@ +// simeck.cpp - 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 + +#include "pch.h" +#include "config.h" + +#include "simeck.h" +#include "misc.h" +#include "cpu.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::rotlConstant; +using CryptoPP::rotrConstant; + +/// \brief SIMECK encryption round +/// \tparam T word type +/// \param key the key for the round or iteration +/// \param left the first value +/// \param right the second value +/// \details SIMECK_Encryption serves as the key schedule, encryption and +/// decryption functions. +template +inline void SIMECK_Encryption(const T key, T& left, T& right) +{ + const T temp = left; + left = (left & rotlConstant<5>(left)) ^ rotlConstant<1>(left) ^ right ^ key; + right = temp; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +std::string SIMECK32::Base::AlgorithmProvider() const +{ + return "C++"; +} + +void SIMECK32::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + CRYPTOPP_UNUSED(keyLength); + + GetBlock kblock(userKey); + kblock(m_t[3])(m_t[2])(m_t[1])(m_t[0]); + + word16 constant = 0xFFFC; + word32 sequence = 0x9A42BB1F; + for (unsigned int i = 0; i < ROUNDS; ++i) + { + m_rk[i] = m_t[0]; + + constant &= 0xFFFC; + constant |= sequence & 1; + sequence >>= 1; + + SIMECK_Encryption(static_cast(constant), m_t[1], m_t[0]); + + // rotate the LFSR of m_t + m_t[4] = m_t[1]; + m_t[1] = m_t[2]; + m_t[2] = m_t[3]; + m_t[3] = m_t[4]; + } +} + +void SIMECK32::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_t[1])(m_t[0]); + + for (int idx = 0; idx < ROUNDS; ++idx) + SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]); + + PutBlock oblock(xorBlock, outBlock); + oblock(m_t[1])(m_t[0]); +} + +void SIMECK32::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_t[0])(m_t[1]); + + for (int idx = ROUNDS - 1; idx >= 0; --idx) + SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]); + + PutBlock oblock(xorBlock, outBlock); + oblock(m_t[0])(m_t[1]); +} + +std::string SIMECK64::Base::AlgorithmProvider() const +{ + return "C++"; +} + +void SIMECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + CRYPTOPP_UNUSED(keyLength); + + GetBlock kblock(userKey); + kblock(m_t[3])(m_t[2])(m_t[1])(m_t[0]); + + word64 constant = W64LIT(0xFFFFFFFC); + word64 sequence = W64LIT(0x938BCA3083F); + for (unsigned int i = 0; i < ROUNDS; ++i) + { + m_rk[i] = m_t[0]; + + constant &= W64LIT(0xFFFFFFFC); + constant |= sequence & 1; + sequence >>= 1; + + SIMECK_Encryption(static_cast(constant), m_t[1], m_t[0]); + + // rotate the LFSR of m_t + m_t[4] = m_t[1]; + m_t[1] = m_t[2]; + m_t[2] = m_t[3]; + m_t[3] = m_t[4]; + } +} + +void SIMECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_t[1])(m_t[0]); + + for (int idx = 0; idx < ROUNDS; ++idx) + SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]); + + PutBlock oblock(xorBlock, outBlock); + oblock(m_t[1])(m_t[0]); +} + +void SIMECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do not cast the buffer. It will SIGBUS on some ARM and SPARC. + GetBlock iblock(inBlock); + iblock(m_t[0])(m_t[1]); + + for (int idx = ROUNDS - 1; idx >= 0; --idx) + SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]); + + PutBlock oblock(xorBlock, outBlock); + oblock(m_t[0])(m_t[1]); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/simeck.h b/external/ours/library/crypto/src/shared/original/simeck.h new file mode 100755 index 000000000..3449c7f84 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/simon.cpp b/external/ours/library/crypto/src/shared/original/simon.cpp new file mode 100755 index 000000000..a0eacea4c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/simon.cpp @@ -0,0 +1,505 @@ +// simon.h - written and placed in the public domain by Jeffrey Walton + +#include "pch.h" +#include "config.h" + +#include "simon.h" +#include "misc.h" +#include "cpu.h" + +// Uncomment for benchmarking C++ against SSE or NEON. +// Do so in both simon.cpp and simon_simd.cpp. +// #undef CRYPTOPP_SSSE3_AVAILABLE +// #undef CRYPTOPP_SSE41_AVAILABLE +// #undef CRYPTOPP_ARM_NEON_AVAILABLE + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::rotlConstant; +using CryptoPP::rotrConstant; + +/// \brief Round transformation helper +/// \tparam W word type +/// \param v value +template +inline W f(const W v) +{ + return (rotlConstant<1>(v) & rotlConstant<8>(v)) ^ rotlConstant<2>(v); +} + +/// \brief Round transformation +/// \tparam W word type +/// \param x value +/// \param y value +/// \param k value +/// \param l value +template +inline void R2(W& x, W& y, const W k, const W l) +{ + y ^= f(x); y ^= k; + x ^= f(y); x ^= l; +} + +/// \brief Forward transformation +/// \tparam W word type +/// \tparam R number of rounds +/// \param c output array +/// \param p input array +/// \param k subkey array +template +inline void SIMON_Encrypt(W c[2], const W p[2], const W k[R]) +{ + c[0]=p[0]; c[1]=p[1]; + + for (int i = 0; i < static_cast(R-1); i += 2) + R2(c[0], c[1], k[i], k[i + 1]); + + if (R & 1) + { + c[1] ^= f(c[0]); c[1] ^= k[R-1]; + W t = c[0]; c[0] = c[1]; c[1] = t; + } +} + +/// \brief Reverse transformation +/// \tparam W word type +/// \tparam R number of rounds +/// \param p output array +/// \param c input array +/// \param k subkey array +template +inline void SIMON_Decrypt(W p[2], const W c[2], const W k[R]) +{ + p[0]=c[0]; p[1]=c[1]; + unsigned int rounds = R; + + if (R & 1) + { + const W t = p[1]; p[1] = p[0]; p[0] = t; + p[1] ^= k[R - 1]; p[1] ^= f(p[0]); + rounds--; + } + + for (int i = static_cast(rounds - 2); i >= 0; i -= 2) + R2(p[1], p[0], k[i + 1], k[i]); +} + +/// \brief Subkey generation function +/// \details Used for SIMON-64 with 96-bit key and 42 rounds. A template was +/// not worthwhile because all instantiations would need specialization. +/// \param key empty subkey array +/// \param k user key array +inline void SIMON64_ExpandKey_3W(word32 key[42], const word32 k[3]) +{ + const word32 c = 0xfffffffc; + word64 z = W64LIT(0x7369f885192c0ef5); + + key[0] = k[2]; key[1] = k[1]; key[2] = k[0]; + for (size_t i = 3; i<42; ++i) + { + key[i] = static_cast(c ^ (z & 1) ^ key[i - 3] ^ + rotrConstant<3>(key[i - 1]) ^ rotrConstant<4>(key[i - 1])); + z >>= 1; + } +} + +/// \brief Subkey generation function +/// \details Used for SIMON-64 with 128-bit key and 44 rounds. A template was +/// not worthwhile because all instantiations would need specialization. +/// \param key empty subkey array +/// \param k user key array +inline void SIMON64_ExpandKey_4W(word32 key[44], const word32 k[4]) +{ + const word32 c = 0xfffffffc; + word64 z = W64LIT(0xfc2ce51207a635db); + + key[0] = k[3]; key[1] = k[2]; key[2] = k[1]; key[3] = k[0]; + for (size_t i = 4; i<44; ++i) + { + key[i] = static_cast(c ^ (z & 1) ^ key[i - 4] ^ + rotrConstant<3>(key[i - 1]) ^ key[i - 3] ^ rotrConstant<4>(key[i - 1]) ^ + rotrConstant<1>(key[i - 3])); + z >>= 1; + } +} + +/// \brief Subkey generation function +/// \details Used for SIMON-128 with 128-bit key and 68 rounds. A template was +/// not worthwhile because all instantiations would need specialization. +/// \param key empty subkey array +/// \param k user key array +inline void SIMON128_ExpandKey_2W(word64 key[68], const word64 k[2]) +{ + const word64 c = W64LIT(0xfffffffffffffffc); + word64 z = W64LIT(0x7369f885192c0ef5); + + key[0] = k[1]; key[1] = k[0]; + for (size_t i=2; i<66; ++i) + { + key[i] = c ^ (z & 1) ^ key[i - 2] ^ rotrConstant<3>(key[i - 1]) ^ rotrConstant<4>(key[i - 1]); + z>>=1; + } + + key[66] = c ^ 1 ^ key[64] ^ rotrConstant<3>(key[65]) ^ rotrConstant<4>(key[65]); + key[67] = c^key[65] ^ rotrConstant<3>(key[66]) ^ rotrConstant<4>(key[66]); +} + +/// \brief Subkey generation function +/// \details Used for SIMON-128 with 192-bit key and 69 rounds. A template was +/// not worthwhile because all instantiations would need specialization. +/// \param key empty subkey array +/// \param k user key array +inline void SIMON128_ExpandKey_3W(word64 key[69], const word64 k[3]) +{ + const word64 c = W64LIT(0xfffffffffffffffc); + word64 z = W64LIT(0xfc2ce51207a635db); + + key[0]=k[2]; key[1]=k[1]; key[2]=k[0]; + for (size_t i=3; i<67; ++i) + { + key[i] = c ^ (z & 1) ^ key[i - 3] ^ rotrConstant<3>(key[i - 1]) ^ rotrConstant<4>(key[i - 1]); + z>>=1; + } + + key[67] = c^key[64] ^ rotrConstant<3>(key[66]) ^ rotrConstant<4>(key[66]); + key[68] = c ^ 1 ^ key[65] ^ rotrConstant<3>(key[67]) ^ rotrConstant<4>(key[67]); +} + +/// \brief Subkey generation function +/// \details Used for SIMON-128 with 256-bit key and 72 rounds. A template was +/// not worthwhile because all instantiations would need specialization. +/// \param key empty subkey array +/// \param k user key array +inline void SIMON128_ExpandKey_4W(word64 key[72], const word64 k[4]) +{ + const word64 c = W64LIT(0xfffffffffffffffc); + word64 z = W64LIT(0xfdc94c3a046d678b); + + key[0]=k[3]; key[1]=k[2]; key[2]=k[1]; key[3]=k[0]; + for (size_t i=4; i<68; ++i) + { + key[i] = c ^ (z & 1) ^ key[i - 4] ^ rotrConstant<3>(key[i - 1]) ^ key[i - 3] ^ rotrConstant<4>(key[i - 1]) ^ rotrConstant<1>(key[i - 3]); + z>>=1; + } + + key[68] = c^key[64] ^ rotrConstant<3>(key[67]) ^ key[65] ^ rotrConstant<4>(key[67]) ^ rotrConstant<1>(key[65]); + key[69] = c ^ 1 ^ key[65] ^ rotrConstant<3>(key[68]) ^ key[66] ^ rotrConstant<4>(key[68]) ^ rotrConstant<1>(key[66]); + key[70] = c^key[66] ^ rotrConstant<3>(key[69]) ^ key[67] ^ rotrConstant<4>(key[69]) ^ rotrConstant<1>(key[67]); + key[71] = c^key[67] ^ rotrConstant<3>(key[70]) ^ key[68] ^ rotrConstant<4>(key[70]) ^ rotrConstant<1>(key[68]); +} + +ANONYMOUS_NAMESPACE_END + +/////////////////////////////////////////////////////////// + +NAMESPACE_BEGIN(CryptoPP) + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) +extern size_t SIMON128_Enc_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t SIMON128_Dec_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +#if (CRYPTOPP_SSSE3_AVAILABLE) +extern size_t SIMON128_Enc_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t SIMON128_Dec_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) +extern size_t SIMON128_Enc_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t SIMON128_Dec_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +std::string SIMON64::Base::AlgorithmProvider() const +{ + return "C++"; +} + +unsigned int SIMON64::Base::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +void SIMON64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16); + CRYPTOPP_UNUSED(params); + + // Building the key schedule table requires {3,4} words workspace. + // Encrypting and decrypting requires 4 words workspace. + m_kwords = keyLength/sizeof(word32); + m_wspace.New(4U); + + // Do the endian gyrations from the paper and align pointers + typedef GetBlock KeyBlock; + KeyBlock kblk(userKey); + + switch (m_kwords) + { + case 3: + m_rkeys.New((m_rounds = 42)); + kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]); + SIMON64_ExpandKey_3W(m_rkeys, m_wspace); + break; + case 4: + m_rkeys.New((m_rounds = 44)); + kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]); + SIMON64_ExpandKey_4W(m_rkeys, m_wspace); + break; + default: + CRYPTOPP_ASSERT(0); + } +} + +void SIMON64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do the endian gyrations from the paper and align pointers + typedef GetBlock InBlock; + InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]); + + switch (m_rounds) + { + case 42: + SIMON_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 44: + SIMON_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + default: + CRYPTOPP_ASSERT(0); + } + + // Do the endian gyrations from the paper and align pointers + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]); +} + +void SIMON64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do the endian gyrations from the paper and align pointers + typedef GetBlock InBlock; + InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]); + + switch (m_rounds) + { + case 42: + SIMON_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 44: + SIMON_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + default: + CRYPTOPP_ASSERT(0); + } + + // Do the endian gyrations from the paper and align pointers + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]); +} + +/////////////////////////////////////////////////////////// + +std::string SIMON128::Base::AlgorithmProvider() const +{ +#if (CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS) +# if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return "SSSE3"; +# endif +# if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return "NEON"; +# endif +# if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return "Altivec"; +# endif +#endif + return "C++"; +} + +unsigned int SIMON128::Base::OptimalDataAlignment() const +{ +#if (CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS) +# if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return 16; // load __m128i +# endif +# if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return 8; // load uint64x2_t +# endif +# if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return 16; // load uint64x2_p +# endif +#endif + return GetAlignmentOf(); +} + +void SIMON128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32); + CRYPTOPP_UNUSED(params); + + // Building the key schedule table requires {2,3,4} words workspace. + // Encrypting and decrypting requires 4 words workspace. + m_kwords = keyLength/sizeof(word64); + m_wspace.New(4U); + + // Do the endian gyrations from the paper and align pointers + typedef GetBlock KeyBlock; + KeyBlock kblk(userKey); + + switch (m_kwords) + { + case 2: + m_rkeys.New((m_rounds = 68)); + kblk(m_wspace[1])(m_wspace[0]); + SIMON128_ExpandKey_2W(m_rkeys, m_wspace); + break; + case 3: + m_rkeys.New((m_rounds = 69)); + kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]); + SIMON128_ExpandKey_3W(m_rkeys, m_wspace); + break; + case 4: + m_rkeys.New((m_rounds = 72)); + kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]); + SIMON128_ExpandKey_4W(m_rkeys, m_wspace); + break; + default: + CRYPTOPP_ASSERT(0); + } + +#if CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS + + // Pre-splat the round keys for Altivec forward transformation +#if CRYPTOPP_ALTIVEC_AVAILABLE + if (IsForwardTransformation() && HasAltivec()) + { + AlignedSecBlock presplat(m_rkeys.size()*2); + for (size_t i=0, j=0; i InBlock; + InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]); + + switch (m_rounds) + { + case 68: + SIMON_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 69: + SIMON_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 72: + SIMON_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + default: + CRYPTOPP_ASSERT(0); + } + + // Do the endian gyrations from the paper and align pointers + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]); +} + +void SIMON128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do the endian gyrations from the paper and align pointers + typedef GetBlock InBlock; + InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]); + + switch (m_rounds) + { + case 68: + SIMON_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 69: + SIMON_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 72: + SIMON_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + default: + CRYPTOPP_ASSERT(0); + } + + // Do the endian gyrations from the paper and align pointers + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]); +} + +#if (CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS) +size_t SIMON128::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, + byte *outBlocks, size_t length, word32 flags) const +{ +#if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return SIMON128_Enc_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return SIMON128_Enc_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return SIMON128_Enc_AdvancedProcessBlocks_ALTIVEC(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t SIMON128::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, + byte *outBlocks, size_t length, word32 flags) const +{ +#if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return SIMON128_Dec_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return SIMON128_Dec_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return SIMON128_Dec_AdvancedProcessBlocks_ALTIVEC(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/simon.h b/external/ours/library/crypto/src/shared/original/simon.h new file mode 100755 index 000000000..107aae541 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/simon128_simd.cpp b/external/ours/library/crypto/src/shared/original/simon128_simd.cpp new file mode 100755 index 000000000..5a0aaddf2 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/simon128_simd.cpp @@ -0,0 +1,862 @@ +// simon_simd.cpp - written and placed in the public domain by Jeffrey Walton +// +// This source file uses intrinsics and built-ins to gain access to +// SSSE3, ARM NEON and ARMv8a, and Altivec instructions. A separate +// source file is needed because additional CXXFLAGS are required to enable +// the appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" + +#include "simon.h" +#include "misc.h" + +// Uncomment for benchmarking C++ against SSE or NEON. +// Do so in both simon.cpp and simon_simd.cpp. +// #undef CRYPTOPP_SSSE3_AVAILABLE +// #undef CRYPTOPP_ARM_NEON_AVAILABLE + +#if (CRYPTOPP_SSSE3_AVAILABLE) +# include "adv_simd.h" +# include +# include +#endif + +#if defined(__XOP__) +# include +# if defined(__GNUC__) +# include +# endif +#endif + +#if (CRYPTOPP_ARM_NEON_HEADER) +# include "adv_simd.h" +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +#if defined(_M_ARM64) +# include "adv_simd.h" +#endif + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) +# include "adv_simd.h" +# include "ppc_simd.h" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char SIMON128_SIMD_FNAME[] = __FILE__; + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::vec_swap; // SunCC + +// *************************** ARM NEON ************************** // + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + +// Missing from Microsoft's ARM A-32 implementation +#if defined(_MSC_VER) && !defined(_M_ARM64) +inline uint64x2_t vld1q_dup_u64(const uint64_t* ptr) +{ + return vmovq_n_u64(*ptr); +} +#endif + +template +inline T UnpackHigh64(const T& a, const T& b) +{ + const uint64x1_t x(vget_high_u64((uint64x2_t)a)); + const uint64x1_t y(vget_high_u64((uint64x2_t)b)); + return (T)vcombine_u64(x, y); +} + +template +inline T UnpackLow64(const T& a, const T& b) +{ + const uint64x1_t x(vget_low_u64((uint64x2_t)a)); + const uint64x1_t y(vget_low_u64((uint64x2_t)b)); + return (T)vcombine_u64(x, y); +} + +template +inline uint64x2_t RotateLeft64(const uint64x2_t& val) +{ + const uint64x2_t a(vshlq_n_u64(val, R)); + const uint64x2_t b(vshrq_n_u64(val, 64 - R)); + return vorrq_u64(a, b); +} + +template +inline uint64x2_t RotateRight64(const uint64x2_t& val) +{ + const uint64x2_t a(vshlq_n_u64(val, 64 - R)); + const uint64x2_t b(vshrq_n_u64(val, R)); + return vorrq_u64(a, b); +} + +#if defined(__aarch32__) || defined(__aarch64__) +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +inline uint64x2_t RotateLeft64<8>(const uint64x2_t& val) +{ + const uint8_t maskb[16] = { 7,0,1,2, 3,4,5,6, 15,8,9,10, 11,12,13,14 }; + const uint8x16_t mask = vld1q_u8(maskb); + + return vreinterpretq_u64_u8( + vqtbl1q_u8(vreinterpretq_u8_u64(val), mask)); +} + +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +inline uint64x2_t RotateRight64<8>(const uint64x2_t& val) +{ + const uint8_t maskb[16] = { 1,2,3,4, 5,6,7,0, 9,10,11,12, 13,14,15,8 }; + const uint8x16_t mask = vld1q_u8(maskb); + + return vreinterpretq_u64_u8( + vqtbl1q_u8(vreinterpretq_u8_u64(val), mask)); +} +#endif + +inline uint64x2_t SIMON128_f(const uint64x2_t& val) +{ + return veorq_u64(RotateLeft64<2>(val), + vandq_u64(RotateLeft64<1>(val), RotateLeft64<8>(val))); +} + +inline void SIMON128_Enc_Block(uint64x2_t &block0, uint64x2_t &block1, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + uint64x2_t x1 = UnpackHigh64(block0, block1); + uint64x2_t y1 = UnpackLow64(block0, block1); + + for (size_t i = 0; i < static_cast(rounds & ~1)-1; i += 2) + { + const uint64x2_t rk1 = vld1q_dup_u64(subkeys+i); + y1 = veorq_u64(veorq_u64(y1, SIMON128_f(x1)), rk1); + + const uint64x2_t rk2 = vld1q_dup_u64(subkeys+i+1); + x1 = veorq_u64(veorq_u64(x1, SIMON128_f(y1)), rk2); + } + + if (rounds & 1) + { + const uint64x2_t rk = vld1q_dup_u64(subkeys+rounds-1); + + y1 = veorq_u64(veorq_u64(y1, SIMON128_f(x1)), rk); + std::swap(x1, y1); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = UnpackLow64(y1, x1); + block1 = UnpackHigh64(y1, x1); +} + +inline void SIMON128_Enc_6_Blocks(uint64x2_t &block0, uint64x2_t &block1, + uint64x2_t &block2, uint64x2_t &block3, uint64x2_t &block4, uint64x2_t &block5, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + uint64x2_t x1 = UnpackHigh64(block0, block1); + uint64x2_t y1 = UnpackLow64(block0, block1); + uint64x2_t x2 = UnpackHigh64(block2, block3); + uint64x2_t y2 = UnpackLow64(block2, block3); + uint64x2_t x3 = UnpackHigh64(block4, block5); + uint64x2_t y3 = UnpackLow64(block4, block5); + + for (size_t i = 0; i < static_cast(rounds & ~1) - 1; i += 2) + { + const uint64x2_t rk1 = vld1q_dup_u64(subkeys+i); + y1 = veorq_u64(veorq_u64(y1, SIMON128_f(x1)), rk1); + y2 = veorq_u64(veorq_u64(y2, SIMON128_f(x2)), rk1); + y3 = veorq_u64(veorq_u64(y3, SIMON128_f(x3)), rk1); + + const uint64x2_t rk2 = vld1q_dup_u64(subkeys+i+1); + x1 = veorq_u64(veorq_u64(x1, SIMON128_f(y1)), rk2); + x2 = veorq_u64(veorq_u64(x2, SIMON128_f(y2)), rk2); + x3 = veorq_u64(veorq_u64(x3, SIMON128_f(y3)), rk2); + } + + if (rounds & 1) + { + const uint64x2_t rk = vld1q_dup_u64(subkeys + rounds - 1); + + y1 = veorq_u64(veorq_u64(y1, SIMON128_f(x1)), rk); + y2 = veorq_u64(veorq_u64(y2, SIMON128_f(x2)), rk); + y3 = veorq_u64(veorq_u64(y3, SIMON128_f(x3)), rk); + std::swap(x1, y1); std::swap(x2, y2); std::swap(x3, y3); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = UnpackLow64(y1, x1); + block1 = UnpackHigh64(y1, x1); + block2 = UnpackLow64(y2, x2); + block3 = UnpackHigh64(y2, x2); + block4 = UnpackLow64(y3, x3); + block5 = UnpackHigh64(y3, x3); +} + +inline void SIMON128_Dec_Block(uint64x2_t &block0, uint64x2_t &block1, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + uint64x2_t x1 = UnpackHigh64(block0, block1); + uint64x2_t y1 = UnpackLow64(block0, block1); + + if (rounds & 1) + { + std::swap(x1, y1); + const uint64x2_t rk = vld1q_dup_u64(subkeys + rounds - 1); + + y1 = veorq_u64(veorq_u64(y1, rk), SIMON128_f(x1)); + rounds--; + } + + for (int i = static_cast(rounds-2); i >= 0; i -= 2) + { + const uint64x2_t rk1 = vld1q_dup_u64(subkeys+i+1); + x1 = veorq_u64(veorq_u64(x1, SIMON128_f(y1)), rk1); + + const uint64x2_t rk2 = vld1q_dup_u64(subkeys+i); + y1 = veorq_u64(veorq_u64(y1, SIMON128_f(x1)), rk2); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = UnpackLow64(y1, x1); + block1 = UnpackHigh64(y1, x1); +} + +inline void SIMON128_Dec_6_Blocks(uint64x2_t &block0, uint64x2_t &block1, + uint64x2_t &block2, uint64x2_t &block3, uint64x2_t &block4, uint64x2_t &block5, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + uint64x2_t x1 = UnpackHigh64(block0, block1); + uint64x2_t y1 = UnpackLow64(block0, block1); + uint64x2_t x2 = UnpackHigh64(block2, block3); + uint64x2_t y2 = UnpackLow64(block2, block3); + uint64x2_t x3 = UnpackHigh64(block4, block5); + uint64x2_t y3 = UnpackLow64(block4, block5); + + if (rounds & 1) + { + std::swap(x1, y1); std::swap(x2, y2); std::swap(x3, y3); + const uint64x2_t rk = vld1q_dup_u64(subkeys + rounds - 1); + + y1 = veorq_u64(veorq_u64(y1, rk), SIMON128_f(x1)); + y2 = veorq_u64(veorq_u64(y2, rk), SIMON128_f(x2)); + y3 = veorq_u64(veorq_u64(y3, rk), SIMON128_f(x3)); + rounds--; + } + + for (int i = static_cast(rounds-2); i >= 0; i -= 2) + { + const uint64x2_t rk1 = vld1q_dup_u64(subkeys + i + 1); + x1 = veorq_u64(veorq_u64(x1, SIMON128_f(y1)), rk1); + x2 = veorq_u64(veorq_u64(x2, SIMON128_f(y2)), rk1); + x3 = veorq_u64(veorq_u64(x3, SIMON128_f(y3)), rk1); + + const uint64x2_t rk2 = vld1q_dup_u64(subkeys + i); + y1 = veorq_u64(veorq_u64(y1, SIMON128_f(x1)), rk2); + y2 = veorq_u64(veorq_u64(y2, SIMON128_f(x2)), rk2); + y3 = veorq_u64(veorq_u64(y3, SIMON128_f(x3)), rk2); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = UnpackLow64(y1, x1); + block1 = UnpackHigh64(y1, x1); + block2 = UnpackLow64(y2, x2); + block3 = UnpackHigh64(y2, x2); + block4 = UnpackLow64(y3, x3); + block5 = UnpackHigh64(y3, x3); +} + +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +// ***************************** IA-32 ***************************** // + +#if (CRYPTOPP_SSSE3_AVAILABLE) + +// GCC double casts, https://www.spinics.net/lists/gcchelp/msg47735.html +#ifndef DOUBLE_CAST +# define DOUBLE_CAST(x) ((double *)(void *)(x)) +#endif +#ifndef CONST_DOUBLE_CAST +# define CONST_DOUBLE_CAST(x) ((const double *)(const void *)(x)) +#endif + +inline void Swap128(__m128i& a,__m128i& b) +{ +#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x5120) + // __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. + vec_swap(a, b); +#else + std::swap(a, b); +#endif +} + +template +inline __m128i RotateLeft64(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi64(val, R); +#else + return _mm_or_si128( + _mm_slli_epi64(val, R), _mm_srli_epi64(val, 64-R)); +#endif +} + +template +inline __m128i RotateRight64(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi64(val, 64-R); +#else + return _mm_or_si128( + _mm_slli_epi64(val, 64-R), _mm_srli_epi64(val, R)); +#endif +} + +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +__m128i RotateLeft64<8>(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi64(val, 8); +#else + const __m128i mask = _mm_set_epi8(14,13,12,11, 10,9,8,15, 6,5,4,3, 2,1,0,7); + return _mm_shuffle_epi8(val, mask); +#endif +} + +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +__m128i RotateRight64<8>(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi64(val, 64-8); +#else + const __m128i mask = _mm_set_epi8(8,15,14,13, 12,11,10,9, 0,7,6,5, 4,3,2,1); + return _mm_shuffle_epi8(val, mask); +#endif +} + +inline __m128i SIMON128_f(const __m128i& v) +{ + return _mm_xor_si128(RotateLeft64<2>(v), + _mm_and_si128(RotateLeft64<1>(v), RotateLeft64<8>(v))); +} + +inline void SIMON128_Enc_Block(__m128i &block0, __m128i &block1, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + __m128i x1 = _mm_unpackhi_epi64(block0, block1); + __m128i y1 = _mm_unpacklo_epi64(block0, block1); + + for (size_t i = 0; i < static_cast(rounds & ~1)-1; i += 2) + { + // Round keys are pre-splated in forward direction + const __m128i rk1 = _mm_load_si128(CONST_M128_CAST(subkeys+i*2)); + y1 = _mm_xor_si128(_mm_xor_si128(y1, SIMON128_f(x1)), rk1); + + const __m128i rk2 = _mm_load_si128(CONST_M128_CAST(subkeys+(i+1)*2)); + x1 = _mm_xor_si128(_mm_xor_si128(x1, SIMON128_f(y1)), rk2); + } + + if (rounds & 1) + { + // Round keys are pre-splated in forward direction + const __m128i rk = _mm_load_si128(CONST_M128_CAST(subkeys+(rounds-1)*2)); + + y1 = _mm_xor_si128(_mm_xor_si128(y1, SIMON128_f(x1)), rk); + Swap128(x1, y1); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = _mm_unpacklo_epi64(y1, x1); + block1 = _mm_unpackhi_epi64(y1, x1); +} + +inline void SIMON128_Enc_6_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, __m128i &block4, __m128i &block5, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + __m128i x1 = _mm_unpackhi_epi64(block0, block1); + __m128i y1 = _mm_unpacklo_epi64(block0, block1); + __m128i x2 = _mm_unpackhi_epi64(block2, block3); + __m128i y2 = _mm_unpacklo_epi64(block2, block3); + __m128i x3 = _mm_unpackhi_epi64(block4, block5); + __m128i y3 = _mm_unpacklo_epi64(block4, block5); + + for (size_t i = 0; i < static_cast(rounds & ~1) - 1; i += 2) + { + // Round keys are pre-splated in forward direction + const __m128i rk1 = _mm_load_si128(CONST_M128_CAST(subkeys+i*2)); + y1 = _mm_xor_si128(_mm_xor_si128(y1, SIMON128_f(x1)), rk1); + y2 = _mm_xor_si128(_mm_xor_si128(y2, SIMON128_f(x2)), rk1); + y3 = _mm_xor_si128(_mm_xor_si128(y3, SIMON128_f(x3)), rk1); + + // Round keys are pre-splated in forward direction + const __m128i rk2 = _mm_load_si128(CONST_M128_CAST(subkeys+(i+1)*2)); + x1 = _mm_xor_si128(_mm_xor_si128(x1, SIMON128_f(y1)), rk2); + x2 = _mm_xor_si128(_mm_xor_si128(x2, SIMON128_f(y2)), rk2); + x3 = _mm_xor_si128(_mm_xor_si128(x3, SIMON128_f(y3)), rk2); + } + + if (rounds & 1) + { + // Round keys are pre-splated in forward direction + const __m128i rk = _mm_load_si128(CONST_M128_CAST(subkeys+(rounds-1)*2)); + y1 = _mm_xor_si128(_mm_xor_si128(y1, SIMON128_f(x1)), rk); + y2 = _mm_xor_si128(_mm_xor_si128(y2, SIMON128_f(x2)), rk); + y3 = _mm_xor_si128(_mm_xor_si128(y3, SIMON128_f(x3)), rk); + Swap128(x1, y1); Swap128(x2, y2); Swap128(x3, y3); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = _mm_unpacklo_epi64(y1, x1); + block1 = _mm_unpackhi_epi64(y1, x1); + block2 = _mm_unpacklo_epi64(y2, x2); + block3 = _mm_unpackhi_epi64(y2, x2); + block4 = _mm_unpacklo_epi64(y3, x3); + block5 = _mm_unpackhi_epi64(y3, x3); +} + +inline void SIMON128_Dec_Block(__m128i &block0, __m128i &block1, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + __m128i x1 = _mm_unpackhi_epi64(block0, block1); + __m128i y1 = _mm_unpacklo_epi64(block0, block1); + + if (rounds & 1) + { + const __m128i rk = _mm_castpd_si128( + _mm_loaddup_pd(CONST_DOUBLE_CAST(subkeys + rounds - 1))); + + Swap128(x1, y1); + y1 = _mm_xor_si128(_mm_xor_si128(y1, rk), SIMON128_f(x1)); + rounds--; + } + + for (int i = static_cast(rounds-2); i >= 0; i -= 2) + { + const __m128i rk1 = _mm_castpd_si128( + _mm_loaddup_pd(CONST_DOUBLE_CAST(subkeys+i+1))); + x1 = _mm_xor_si128(_mm_xor_si128(x1, SIMON128_f(y1)), rk1); + + const __m128i rk2 = _mm_castpd_si128( + _mm_loaddup_pd(CONST_DOUBLE_CAST(subkeys+i))); + y1 = _mm_xor_si128(_mm_xor_si128(y1, SIMON128_f(x1)), rk2); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = _mm_unpacklo_epi64(y1, x1); + block1 = _mm_unpackhi_epi64(y1, x1); +} + +inline void SIMON128_Dec_6_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, __m128i &block4, __m128i &block5, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + __m128i x1 = _mm_unpackhi_epi64(block0, block1); + __m128i y1 = _mm_unpacklo_epi64(block0, block1); + __m128i x2 = _mm_unpackhi_epi64(block2, block3); + __m128i y2 = _mm_unpacklo_epi64(block2, block3); + __m128i x3 = _mm_unpackhi_epi64(block4, block5); + __m128i y3 = _mm_unpacklo_epi64(block4, block5); + + if (rounds & 1) + { + const __m128i rk = _mm_castpd_si128( + _mm_loaddup_pd(CONST_DOUBLE_CAST(subkeys + rounds - 1))); + + Swap128(x1, y1); Swap128(x2, y2); Swap128(x3, y3); + y1 = _mm_xor_si128(_mm_xor_si128(y1, rk), SIMON128_f(x1)); + y2 = _mm_xor_si128(_mm_xor_si128(y2, rk), SIMON128_f(x2)); + y3 = _mm_xor_si128(_mm_xor_si128(y3, rk), SIMON128_f(x3)); + rounds--; + } + + for (int i = static_cast(rounds-2); i >= 0; i -= 2) + { + const __m128i rk1 = _mm_castpd_si128( + _mm_loaddup_pd(CONST_DOUBLE_CAST(subkeys + i + 1))); + x1 = _mm_xor_si128(_mm_xor_si128(x1, SIMON128_f(y1)), rk1); + x2 = _mm_xor_si128(_mm_xor_si128(x2, SIMON128_f(y2)), rk1); + x3 = _mm_xor_si128(_mm_xor_si128(x3, SIMON128_f(y3)), rk1); + + const __m128i rk2 = _mm_castpd_si128( + _mm_loaddup_pd(CONST_DOUBLE_CAST(subkeys + i))); + y1 = _mm_xor_si128(_mm_xor_si128(y1, SIMON128_f(x1)), rk2); + y2 = _mm_xor_si128(_mm_xor_si128(y2, SIMON128_f(x2)), rk2); + y3 = _mm_xor_si128(_mm_xor_si128(y3, SIMON128_f(x3)), rk2); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = _mm_unpacklo_epi64(y1, x1); + block1 = _mm_unpackhi_epi64(y1, x1); + block2 = _mm_unpacklo_epi64(y2, x2); + block3 = _mm_unpackhi_epi64(y2, x2); + block4 = _mm_unpacklo_epi64(y3, x3); + block5 = _mm_unpackhi_epi64(y3, x3); +} + +#endif // CRYPTOPP_SSSE3_AVAILABLE + +// ***************************** Altivec ***************************** // + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + +// Altivec uses native 64-bit types on 64-bit environments, or 32-bit types +// in 32-bit environments. Speck128 will use the appropriate type for the +// environment. Functions like VecAdd64 have two overloads, one for each +// environment. The 32-bit overload treats uint32x4_p like a 64-bit type, +// and does things like perform a add with carry or subtract with borrow. + +// Speck128 on Power8 performed as expected because of 64-bit environment. +// Performance sucked on old PowerPC machines because of 32-bit environments. +// At Crypto++ 8.3 we added an implementation that operated on 32-bit words. +// Native 64-bit Speck128 performance dropped from about 4.1 to 6.3 cpb, but +// 32-bit Speck128 improved from 66.5 cpb to 10.4 cpb. Overall it was a +// good win even though we lost some performance in 64-bit environments. + +using CryptoPP::uint8x16_p; +using CryptoPP::uint32x4_p; +#if defined(_ARCH_PWR8) +using CryptoPP::uint64x2_p; +#endif + +using CryptoPP::VecAdd64; +using CryptoPP::VecSub64; +using CryptoPP::VecAnd64; +using CryptoPP::VecOr64; +using CryptoPP::VecXor64; +using CryptoPP::VecRotateLeft64; +using CryptoPP::VecRotateRight64; +using CryptoPP::VecSplatElement64; +using CryptoPP::VecLoad; +using CryptoPP::VecLoadAligned; +using CryptoPP::VecPermute; + +#if defined(_ARCH_PWR8) +#define simon128_t uint64x2_p +#else +#define simon128_t uint32x4_p +#endif + +inline simon128_t SIMON128_f(const simon128_t val) +{ + return (simon128_t)VecXor64(VecRotateLeft64<2>(val), + VecAnd64(VecRotateLeft64<1>(val), VecRotateLeft64<8>(val))); +} + +inline void SIMON128_Enc_Block(uint32x4_p &block, const word64 *subkeys, unsigned int rounds) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m1 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m2 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m1 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m2 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + simon128_t x1 = (simon128_t)VecPermute(block, block, m1); + simon128_t y1 = (simon128_t)VecPermute(block, block, m2); + + for (size_t i = 0; i < static_cast(rounds & ~1)-1; i += 2) + { + // Round keys are pre-splated in forward direction + const word32* ptr1 = reinterpret_cast(subkeys+i*2); + const simon128_t rk1 = (simon128_t)VecLoadAligned(ptr1); + const word32* ptr2 = reinterpret_cast(subkeys+(i+1)*2); + const simon128_t rk2 = (simon128_t)VecLoadAligned(ptr2); + + y1 = VecXor64(VecXor64(y1, SIMON128_f(x1)), rk1); + x1 = VecXor64(VecXor64(x1, SIMON128_f(y1)), rk2); + } + + if (rounds & 1) + { + // Round keys are pre-splated in forward direction + const word32* ptr = reinterpret_cast(subkeys+(rounds-1)*2); + const simon128_t rk = (simon128_t)VecLoadAligned(ptr); + + y1 = VecXor64(VecXor64(y1, SIMON128_f(x1)), rk); + + std::swap(x1, y1); + } + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m3 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + //const uint8x16_p m4 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m3 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + //const uint8x16_p m4 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block = (uint32x4_p)VecPermute(x1, y1, m3); +} + +inline void SIMON128_Dec_Block(uint32x4_p &block, const word64 *subkeys, unsigned int rounds) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m1 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m2 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m1 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m2 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + simon128_t x1 = (simon128_t)VecPermute(block, block, m1); + simon128_t y1 = (simon128_t)VecPermute(block, block, m2); + + if (rounds & 1) + { + std::swap(x1, y1); + + const word32* ptr = reinterpret_cast(subkeys+rounds-1); + const simon128_t tk = (simon128_t)VecLoad(ptr); + const simon128_t rk = (simon128_t)VecSplatElement64<0>(tk); + + y1 = VecXor64(VecXor64(y1, rk), SIMON128_f(x1)); + rounds--; + } + + for (int i = static_cast(rounds-2); i >= 0; i -= 2) + { + const word32* ptr = reinterpret_cast(subkeys+i); + const simon128_t tk = (simon128_t)VecLoad(ptr); + const simon128_t rk1 = (simon128_t)VecSplatElement64<1>(tk); + const simon128_t rk2 = (simon128_t)VecSplatElement64<0>(tk); + + x1 = VecXor64(VecXor64(x1, SIMON128_f(y1)), rk1); + y1 = VecXor64(VecXor64(y1, SIMON128_f(x1)), rk2); + } + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m3 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + //const uint8x16_p m4 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m3 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + //const uint8x16_p m4 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block = (uint32x4_p)VecPermute(x1, y1, m3); +} + +inline void SIMON128_Enc_6_Blocks(uint32x4_p &block0, uint32x4_p &block1, + uint32x4_p &block2, uint32x4_p &block3, uint32x4_p &block4, + uint32x4_p &block5, const word64 *subkeys, unsigned int rounds) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m1 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m2 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m1 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m2 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + simon128_t x1 = (simon128_t)VecPermute(block0, block1, m1); + simon128_t y1 = (simon128_t)VecPermute(block0, block1, m2); + simon128_t x2 = (simon128_t)VecPermute(block2, block3, m1); + simon128_t y2 = (simon128_t)VecPermute(block2, block3, m2); + simon128_t x3 = (simon128_t)VecPermute(block4, block5, m1); + simon128_t y3 = (simon128_t)VecPermute(block4, block5, m2); + + for (size_t i = 0; i < static_cast(rounds & ~1)-1; i += 2) + { + // Round keys are pre-splated in forward direction + const word32* ptr1 = reinterpret_cast(subkeys+i*2); + const simon128_t rk1 = (simon128_t)VecLoadAligned(ptr1); + + const word32* ptr2 = reinterpret_cast(subkeys+(i+1)*2); + const simon128_t rk2 = (simon128_t)VecLoadAligned(ptr2); + + y1 = VecXor64(VecXor64(y1, SIMON128_f(x1)), rk1); + y2 = VecXor64(VecXor64(y2, SIMON128_f(x2)), rk1); + y3 = VecXor64(VecXor64(y3, SIMON128_f(x3)), rk1); + + x1 = VecXor64(VecXor64(x1, SIMON128_f(y1)), rk2); + x2 = VecXor64(VecXor64(x2, SIMON128_f(y2)), rk2); + x3 = VecXor64(VecXor64(x3, SIMON128_f(y3)), rk2); + } + + if (rounds & 1) + { + // Round keys are pre-splated in forward direction + const word32* ptr = reinterpret_cast(subkeys+(rounds-1)*2); + const simon128_t rk = (simon128_t)VecLoadAligned(ptr); + + y1 = VecXor64(VecXor64(y1, SIMON128_f(x1)), rk); + y2 = VecXor64(VecXor64(y2, SIMON128_f(x2)), rk); + y3 = VecXor64(VecXor64(y3, SIMON128_f(x3)), rk); + + std::swap(x1, y1); std::swap(x2, y2); std::swap(x3, y3); + } + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m3 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m4 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m3 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m4 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = (uint32x4_p)VecPermute(x1, y1, m3); + block1 = (uint32x4_p)VecPermute(x1, y1, m4); + block2 = (uint32x4_p)VecPermute(x2, y2, m3); + block3 = (uint32x4_p)VecPermute(x2, y2, m4); + block4 = (uint32x4_p)VecPermute(x3, y3, m3); + block5 = (uint32x4_p)VecPermute(x3, y3, m4); +} + +inline void SIMON128_Dec_6_Blocks(uint32x4_p &block0, uint32x4_p &block1, + uint32x4_p &block2, uint32x4_p &block3, uint32x4_p &block4, + uint32x4_p &block5, const word64 *subkeys, unsigned int rounds) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m1 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m2 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m1 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m2 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + simon128_t x1 = (simon128_t)VecPermute(block0, block1, m1); + simon128_t y1 = (simon128_t)VecPermute(block0, block1, m2); + simon128_t x2 = (simon128_t)VecPermute(block2, block3, m1); + simon128_t y2 = (simon128_t)VecPermute(block2, block3, m2); + simon128_t x3 = (simon128_t)VecPermute(block4, block5, m1); + simon128_t y3 = (simon128_t)VecPermute(block4, block5, m2); + + if (rounds & 1) + { + std::swap(x1, y1); std::swap(x2, y2); std::swap(x3, y3); + + const word32* ptr = reinterpret_cast(subkeys+rounds-1); + const simon128_t tk = (simon128_t)VecLoad(ptr); + const simon128_t rk = (simon128_t)VecSplatElement64<0>(tk); + + y1 = VecXor64(VecXor64(y1, rk), SIMON128_f(x1)); + y2 = VecXor64(VecXor64(y2, rk), SIMON128_f(x2)); + y3 = VecXor64(VecXor64(y3, rk), SIMON128_f(x3)); + rounds--; + } + + for (int i = static_cast(rounds-2); i >= 0; i -= 2) + { + const word32* ptr = reinterpret_cast(subkeys+i); + const simon128_t tk = (simon128_t)VecLoad(ptr); + const simon128_t rk1 = (simon128_t)VecSplatElement64<1>(tk); + const simon128_t rk2 = (simon128_t)VecSplatElement64<0>(tk); + + x1 = VecXor64(VecXor64(x1, SIMON128_f(y1)), rk1); + x2 = VecXor64(VecXor64(x2, SIMON128_f(y2)), rk1); + x3 = VecXor64(VecXor64(x3, SIMON128_f(y3)), rk1); + + y1 = VecXor64(VecXor64(y1, SIMON128_f(x1)), rk2); + y2 = VecXor64(VecXor64(y2, SIMON128_f(x2)), rk2); + y3 = VecXor64(VecXor64(y3, SIMON128_f(x3)), rk2); + } + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m3 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m4 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m3 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m4 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = (uint32x4_p)VecPermute(x1, y1, m3); + block1 = (uint32x4_p)VecPermute(x1, y1, m4); + block2 = (uint32x4_p)VecPermute(x2, y2, m3); + block3 = (uint32x4_p)VecPermute(x2, y2, m4); + block4 = (uint32x4_p)VecPermute(x3, y3, m3); + block5 = (uint32x4_p)VecPermute(x3, y3, m4); +} + +#endif // CRYPTOPP_ALTIVEC_AVAILABLE + +ANONYMOUS_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////// + +NAMESPACE_BEGIN(CryptoPP) + +// *************************** ARM NEON **************************** // + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) +size_t SIMON128_Enc_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x2_NEON(SIMON128_Enc_Block, SIMON128_Enc_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t SIMON128_Dec_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x2_NEON(SIMON128_Dec_Block, SIMON128_Dec_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +// ***************************** IA-32 ***************************** // + +#if (CRYPTOPP_SSSE3_AVAILABLE) +size_t SIMON128_Enc_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x2_SSE(SIMON128_Enc_Block, SIMON128_Enc_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t SIMON128_Dec_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x2_SSE(SIMON128_Dec_Block, SIMON128_Dec_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_SSSE3_AVAILABLE + +// ***************************** Altivec ***************************** // + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) +size_t SIMON128_Enc_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x1_ALTIVEC(SIMON128_Enc_Block, SIMON128_Enc_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t SIMON128_Dec_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x1_ALTIVEC(SIMON128_Dec_Block, SIMON128_Dec_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_ALTIVEC_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/simple.cpp b/external/ours/library/crypto/src/shared/original/simple.cpp new file mode 100755 index 000000000..b897cc129 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/simple.cpp @@ -0,0 +1,13 @@ +// simple.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "simple.h" + +NAMESPACE_BEGIN(CryptoPP) + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/simple.h b/external/ours/library/crypto/src/shared/original/simple.h new file mode 100755 index 000000000..d3047e228 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 alogorithm +/// \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 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 A Sink doesnot 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/external/ours/library/crypto/src/shared/original/siphash.h b/external/ours/library/crypto/src/shared/original/siphash.h new file mode 100755 index 000000000..4ffe1b50d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/siphash.h @@ -0,0 +1,313 @@ +// 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 "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); + 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) + { + 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/external/ours/library/crypto/src/shared/original/skipjack.cpp b/external/ours/library/crypto/src/shared/original/skipjack.cpp new file mode 100755 index 000000000..d3f59ff71 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/skipjack.cpp @@ -0,0 +1,202 @@ +// skipjack.cpp - modified by Wei Dai from Paulo Barreto's skipjack32.c, +// which is public domain according to his web site. + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "skipjack.h" + +/* + * Optimized implementation of SKIPJACK algorithm + * + * originally written by Panu Rissanen 1998.06.24 + * optimized by Mark Tillotson 1998.06.25 + * optimized by Paulo Barreto 1998.06.30 + */ + +NAMESPACE_BEGIN(CryptoPP) + +/** + * The F-table byte permutation (see description of the G-box permutation) + */ +const byte SKIPJACK::Base::fTable[256] = { + 0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9, + 0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28, + 0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53, + 0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2, + 0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8, + 0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90, + 0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76, + 0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d, + 0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18, + 0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4, + 0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40, + 0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5, + 0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2, + 0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8, + 0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac, + 0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46 +}; + +/** + * The key-dependent permutation G on V^16 is a four-round Feistel network. + * The round function is a fixed byte-substitution table (permutation on V^8), + * the F-table. Each round of G incorporates a single byte from the key. + */ +#define g(tab, w, i, j, k, l) \ +{ \ + w ^= (word)tab[i*256 + (w & 0xff)] << 8; \ + w ^= (word)tab[j*256 + (w >> 8)]; \ + w ^= (word)tab[k*256 + (w & 0xff)] << 8; \ + w ^= (word)tab[l*256 + (w >> 8)]; \ +} + +#define g0(tab, w) g(tab, w, 0, 1, 2, 3) +#define g1(tab, w) g(tab, w, 4, 5, 6, 7) +#define g2(tab, w) g(tab, w, 8, 9, 0, 1) +#define g3(tab, w) g(tab, w, 2, 3, 4, 5) +#define g4(tab, w) g(tab, w, 6, 7, 8, 9) + +/** + * The inverse of the G permutation. + */ +#define h(tab, w, i, j, k, l) \ +{ \ + w ^= (word)tab[l*256 + (w >> 8)]; \ + w ^= (word)tab[k*256 + (w & 0xff)] << 8; \ + w ^= (word)tab[j*256 + (w >> 8)]; \ + w ^= (word)tab[i*256 + (w & 0xff)] << 8; \ +} + +#define h0(tab, w) h(tab, w, 0, 1, 2, 3) +#define h1(tab, w) h(tab, w, 4, 5, 6, 7) +#define h2(tab, w) h(tab, w, 8, 9, 0, 1) +#define h3(tab, w) h(tab, w, 2, 3, 4, 5) +#define h4(tab, w) h(tab, w, 6, 7, 8, 9) + +/** + * Preprocess a user key into a table to save an XOR at each F-table access. + */ +void SKIPJACK::Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + /* tab[i][c] = fTable[c ^ key[i]] */ + int i; + for (i = 0; i < 10; i++) { + byte *t = tab+i*256, k = key[9-i]; + int c; + for (c = 0; c < 256; c++) { + t[c] = fTable[c ^ k]; + } + } +} + +typedef BlockGetAndPut Block; + +/** + * Encrypt a single block of data. + */ +void SKIPJACK::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word16 w1, w2, w3, w4; + Block::Get(inBlock)(w4)(w3)(w2)(w1); + + /* stepping rule A: */ + g0(tab, w1); w4 ^= w1 ^ 1; + g1(tab, w4); w3 ^= w4 ^ 2; + g2(tab, w3); w2 ^= w3 ^ 3; + g3(tab, w2); w1 ^= w2 ^ 4; + g4(tab, w1); w4 ^= w1 ^ 5; + g0(tab, w4); w3 ^= w4 ^ 6; + g1(tab, w3); w2 ^= w3 ^ 7; + g2(tab, w2); w1 ^= w2 ^ 8; + + /* stepping rule B: */ + w2 ^= w1 ^ 9; g3(tab, w1); + w1 ^= w4 ^ 10; g4(tab, w4); + w4 ^= w3 ^ 11; g0(tab, w3); + w3 ^= w2 ^ 12; g1(tab, w2); + w2 ^= w1 ^ 13; g2(tab, w1); + w1 ^= w4 ^ 14; g3(tab, w4); + w4 ^= w3 ^ 15; g4(tab, w3); + w3 ^= w2 ^ 16; g0(tab, w2); + + /* stepping rule A: */ + g1(tab, w1); w4 ^= w1 ^ 17; + g2(tab, w4); w3 ^= w4 ^ 18; + g3(tab, w3); w2 ^= w3 ^ 19; + g4(tab, w2); w1 ^= w2 ^ 20; + g0(tab, w1); w4 ^= w1 ^ 21; + g1(tab, w4); w3 ^= w4 ^ 22; + g2(tab, w3); w2 ^= w3 ^ 23; + g3(tab, w2); w1 ^= w2 ^ 24; + + /* stepping rule B: */ + w2 ^= w1 ^ 25; g4(tab, w1); + w1 ^= w4 ^ 26; g0(tab, w4); + w4 ^= w3 ^ 27; g1(tab, w3); + w3 ^= w2 ^ 28; g2(tab, w2); + w2 ^= w1 ^ 29; g3(tab, w1); + w1 ^= w4 ^ 30; g4(tab, w4); + w4 ^= w3 ^ 31; g0(tab, w3); + w3 ^= w2 ^ 32; g1(tab, w2); + + Block::Put(xorBlock, outBlock)(w4)(w3)(w2)(w1); +} + +/** + * Decrypt a single block of data. + */ +void SKIPJACK::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word16 w1, w2, w3, w4; + Block::Get(inBlock)(w4)(w3)(w2)(w1); + + /* stepping rule A: */ + h1(tab, w2); w3 ^= w2 ^ 32; + h0(tab, w3); w4 ^= w3 ^ 31; + h4(tab, w4); w1 ^= w4 ^ 30; + h3(tab, w1); w2 ^= w1 ^ 29; + h2(tab, w2); w3 ^= w2 ^ 28; + h1(tab, w3); w4 ^= w3 ^ 27; + h0(tab, w4); w1 ^= w4 ^ 26; + h4(tab, w1); w2 ^= w1 ^ 25; + + /* stepping rule B: */ + w1 ^= w2 ^ 24; h3(tab, w2); + w2 ^= w3 ^ 23; h2(tab, w3); + w3 ^= w4 ^ 22; h1(tab, w4); + w4 ^= w1 ^ 21; h0(tab, w1); + w1 ^= w2 ^ 20; h4(tab, w2); + w2 ^= w3 ^ 19; h3(tab, w3); + w3 ^= w4 ^ 18; h2(tab, w4); + w4 ^= w1 ^ 17; h1(tab, w1); + + /* stepping rule A: */ + h0(tab, w2); w3 ^= w2 ^ 16; + h4(tab, w3); w4 ^= w3 ^ 15; + h3(tab, w4); w1 ^= w4 ^ 14; + h2(tab, w1); w2 ^= w1 ^ 13; + h1(tab, w2); w3 ^= w2 ^ 12; + h0(tab, w3); w4 ^= w3 ^ 11; + h4(tab, w4); w1 ^= w4 ^ 10; + h3(tab, w1); w2 ^= w1 ^ 9; + + /* stepping rule B: */ + w1 ^= w2 ^ 8; h2(tab, w2); + w2 ^= w3 ^ 7; h1(tab, w3); + w3 ^= w4 ^ 6; h0(tab, w4); + w4 ^= w1 ^ 5; h4(tab, w1); + w1 ^= w2 ^ 4; h3(tab, w2); + w2 ^= w3 ^ 3; h2(tab, w3); + w3 ^= w4 ^ 2; h1(tab, w4); + w4 ^= w1 ^ 1; h0(tab, w1); + + Block::Put(xorBlock, outBlock)(w4)(w3)(w2)(w1); +} + +NAMESPACE_END + +#endif diff --git a/external/ours/library/crypto/src/shared/original/skipjack.h b/external/ours/library/crypto/src/shared/original/skipjack.h new file mode 100755 index 000000000..f158005aa --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/sm3.cpp b/external/ours/library/crypto/src/shared/original/sm3.cpp new file mode 100755 index 000000000..bf01dd53f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/sm3.cpp @@ -0,0 +1,255 @@ +// sm3.cpp - 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. +// +// We understand future ARMv8 enhancements are supposed +// to include SM3 and SM4 related instructions so the function +// is stubbed for an eventual SM3_HashMultipleBlocks_ARMV8. + +#include "pch.h" +#include "config.h" + +#include "sm3.h" +#include "misc.h" +#include "cpu.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::rotlConstant; + +using CryptoPP::SM3; +using CryptoPP::GetBlock; +using CryptoPP::BigEndian; + +inline word32 P0(word32 X) +{ + return X ^ rotlConstant<9>(X) ^ rotlConstant<17>(X); +} + +inline word32 P1(word32 X) +{ + return X ^ rotlConstant<15>(X) ^ rotlConstant<23>(X); +} + +inline word32 EE(word32 W0, word32 W7, word32 W13, word32 W3, word32 W10) +{ + return P1(W0 ^ W7 ^ rotlConstant<15>(W13)) ^ rotlConstant<7>(W3) ^ W10; +} + +inline word32 FF(word32 X, word32 Y, word32 Z) +{ + return (X & Y) | ((X | Y) & Z); +} + +inline word32 GG(word32 X, word32 Y, word32 Z) +{ + return ((Z ^ (X & (Y ^ Z)))); +} + +inline void R1(word32 A, word32& B, word32 C, word32& D, word32 E, word32& F, + word32 G, word32& H, word32 TJ, word32 Wi, word32 Wj) +{ + const word32 A12 = rotlConstant<12>(A); + const word32 TT0 = rotlConstant<7>(A12 + E + TJ); + const word32 TT1 = (A ^ B ^ C) + D + (TT0 ^ A12) + Wj; + const word32 TT2 = (E ^ F ^ G) + H + TT0 + Wi; + + B = rotlConstant<9>(B); D = TT1; + F = rotlConstant<19>(F); H = P0(TT2); +} + +inline void R2(word32 A, word32& B, word32 C, word32& D, word32 E, word32& F, + word32 G, word32& H, word32 TJ, word32 Wi, word32 Wj) +{ + const word32 A12 = rotlConstant<12>(A); + const word32 TT0 = rotlConstant<7>(A12 + E + TJ); + const word32 TT1 = FF(A, B, C) + D + (TT0 ^ A12) + Wj; + const word32 TT2 = GG(E, F, G) + H + TT0 + Wi; + + B = rotlConstant<9>(B); D = TT1; + F = rotlConstant<19>(F); H = P0(TT2); +} + +// Krzysztof Kwiatkowski did a very nice job with this function. +size_t SM3_HashMultipleBlocks_CXX(word32 *state, const word32 *data, size_t length) +{ + CRYPTOPP_ASSERT(data); + + word32 A = state[0], B = state[1], C = state[2], D = state[3]; + word32 E = state[4], F = state[5], G = state[6], H = state[7]; + + while (length >= SM3::BLOCKSIZE) + { + // Reverse bytes on LittleEndian; align pointer on BigEndian + typedef GetBlock InBlock; + InBlock iblk(data); + + word32 W00, W01, W02, W03, W04, W05, W06, W07, W08, W09, W10, W11, W12, W13, W14, W15; + iblk(W00)(W01)(W02)(W03)(W04)(W05)(W06)(W07)(W08)(W09)(W10)(W11)(W12)(W13)(W14)(W15); + + R1(A, B, C, D, E, F, G, H, 0x79CC4519, W00, W00 ^ W04); + W00 = EE(W00, W07, W13, W03, W10); + R1(D, A, B, C, H, E, F, G, 0xF3988A32, W01, W01 ^ W05); + W01 = EE(W01, W08, W14, W04, W11); + R1(C, D, A, B, G, H, E, F, 0xE7311465, W02, W02 ^ W06); + W02 = EE(W02, W09, W15, W05, W12); + R1(B, C, D, A, F, G, H, E, 0xCE6228CB, W03, W03 ^ W07); + W03 = EE(W03, W10, W00, W06, W13); + R1(A, B, C, D, E, F, G, H, 0x9CC45197, W04, W04 ^ W08); + W04 = EE(W04, W11, W01, W07, W14); + R1(D, A, B, C, H, E, F, G, 0x3988A32F, W05, W05 ^ W09); + W05 = EE(W05, W12, W02, W08, W15); + R1(C, D, A, B, G, H, E, F, 0x7311465E, W06, W06 ^ W10); + W06 = EE(W06, W13, W03, W09, W00); + R1(B, C, D, A, F, G, H, E, 0xE6228CBC, W07, W07 ^ W11); + W07 = EE(W07, W14, W04, W10, W01); + R1(A, B, C, D, E, F, G, H, 0xCC451979, W08, W08 ^ W12); + W08 = EE(W08, W15, W05, W11, W02); + R1(D, A, B, C, H, E, F, G, 0x988A32F3, W09, W09 ^ W13); + W09 = EE(W09, W00, W06, W12, W03); + R1(C, D, A, B, G, H, E, F, 0x311465E7, W10, W10 ^ W14); + W10 = EE(W10, W01, W07, W13, W04); + R1(B, C, D, A, F, G, H, E, 0x6228CBCE, W11, W11 ^ W15); + W11 = EE(W11, W02, W08, W14, W05); + R1(A, B, C, D, E, F, G, H, 0xC451979C, W12, W12 ^ W00); + W12 = EE(W12, W03, W09, W15, W06); + R1(D, A, B, C, H, E, F, G, 0x88A32F39, W13, W13 ^ W01); + W13 = EE(W13, W04, W10, W00, W07); + R1(C, D, A, B, G, H, E, F, 0x11465E73, W14, W14 ^ W02); + W14 = EE(W14, W05, W11, W01, W08); + R1(B, C, D, A, F, G, H, E, 0x228CBCE6, W15, W15 ^ W03); + W15 = EE(W15, W06, W12, W02, W09); + R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04); + W00 = EE(W00, W07, W13, W03, W10); + R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05); + W01 = EE(W01, W08, W14, W04, W11); + R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06); + W02 = EE(W02, W09, W15, W05, W12); + R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07); + W03 = EE(W03, W10, W00, W06, W13); + R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08); + W04 = EE(W04, W11, W01, W07, W14); + R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09); + W05 = EE(W05, W12, W02, W08, W15); + R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10); + W06 = EE(W06, W13, W03, W09, W00); + R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11); + W07 = EE(W07, W14, W04, W10, W01); + R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12); + W08 = EE(W08, W15, W05, W11, W02); + R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13); + W09 = EE(W09, W00, W06, W12, W03); + R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14); + W10 = EE(W10, W01, W07, W13, W04); + R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15); + W11 = EE(W11, W02, W08, W14, W05); + R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00); + W12 = EE(W12, W03, W09, W15, W06); + R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01); + W13 = EE(W13, W04, W10, W00, W07); + R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02); + W14 = EE(W14, W05, W11, W01, W08); + R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03); + W15 = EE(W15, W06, W12, W02, W09); + R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W00, W00 ^ W04); + W00 = EE(W00, W07, W13, W03, W10); + R2(D, A, B, C, H, E, F, G, 0xF50F3B14, W01, W01 ^ W05); + W01 = EE(W01, W08, W14, W04, W11); + R2(C, D, A, B, G, H, E, F, 0xEA1E7629, W02, W02 ^ W06); + W02 = EE(W02, W09, W15, W05, W12); + R2(B, C, D, A, F, G, H, E, 0xD43CEC53, W03, W03 ^ W07); + W03 = EE(W03, W10, W00, W06, W13); + R2(A, B, C, D, E, F, G, H, 0xA879D8A7, W04, W04 ^ W08); + W04 = EE(W04, W11, W01, W07, W14); + R2(D, A, B, C, H, E, F, G, 0x50F3B14F, W05, W05 ^ W09); + W05 = EE(W05, W12, W02, W08, W15); + R2(C, D, A, B, G, H, E, F, 0xA1E7629E, W06, W06 ^ W10); + W06 = EE(W06, W13, W03, W09, W00); + R2(B, C, D, A, F, G, H, E, 0x43CEC53D, W07, W07 ^ W11); + W07 = EE(W07, W14, W04, W10, W01); + R2(A, B, C, D, E, F, G, H, 0x879D8A7A, W08, W08 ^ W12); + W08 = EE(W08, W15, W05, W11, W02); + R2(D, A, B, C, H, E, F, G, 0x0F3B14F5, W09, W09 ^ W13); + W09 = EE(W09, W00, W06, W12, W03); + R2(C, D, A, B, G, H, E, F, 0x1E7629EA, W10, W10 ^ W14); + W10 = EE(W10, W01, W07, W13, W04); + R2(B, C, D, A, F, G, H, E, 0x3CEC53D4, W11, W11 ^ W15); + W11 = EE(W11, W02, W08, W14, W05); + R2(A, B, C, D, E, F, G, H, 0x79D8A7A8, W12, W12 ^ W00); + W12 = EE(W12, W03, W09, W15, W06); + R2(D, A, B, C, H, E, F, G, 0xF3B14F50, W13, W13 ^ W01); + W13 = EE(W13, W04, W10, W00, W07); + R2(C, D, A, B, G, H, E, F, 0xE7629EA1, W14, W14 ^ W02); + W14 = EE(W14, W05, W11, W01, W08); + R2(B, C, D, A, F, G, H, E, 0xCEC53D43, W15, W15 ^ W03); + W15 = EE(W15, W06, W12, W02, W09); + R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04); + W00 = EE(W00, W07, W13, W03, W10); + R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05); + W01 = EE(W01, W08, W14, W04, W11); + R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06); + W02 = EE(W02, W09, W15, W05, W12); + R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07); + W03 = EE(W03, W10, W00, W06, W13); + R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08); + R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09); + R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10); + R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11); + R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12); + R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13); + R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14); + R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15); + R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00); + R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01); + R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02); + R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03); + + A = (state[0] ^= A); + B = (state[1] ^= B); + C = (state[2] ^= C); + D = (state[3] ^= D); + E = (state[4] ^= E); + F = (state[5] ^= F); + G = (state[6] ^= G); + H = (state[7] ^= H); + + data += SM3::BLOCKSIZE/sizeof(word32); + length -= SM3::BLOCKSIZE; + } + + return length; +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void SM3::InitState(HashWordType *state) +{ + const word32 s[] = { + 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, + 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e + }; + + std::memcpy(state, s, sizeof(s)); +} + +void SM3::Transform(word32 *state, const word32 *data) +{ + CRYPTOPP_ASSERT(state); + CRYPTOPP_ASSERT(data); + + SM3_HashMultipleBlocks_CXX(state, data, SM3::BLOCKSIZE); +} + +size_t SM3::HashMultipleBlocks(const HashWordType *input, size_t length) +{ + const size_t res = length & (SM3::BLOCKSIZE - 1); + SM3_HashMultipleBlocks_CXX(m_state, input, length-res); + return res; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/sm3.h b/external/ours/library/crypto/src/shared/original/sm3.h new file mode 100755 index 000000000..746ccc580 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/sm4.cpp b/external/ours/library/crypto/src/shared/original/sm4.cpp new file mode 100755 index 000000000..ad7f32224 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/sm4.cpp @@ -0,0 +1,212 @@ +// sm4.cpp - written and placed in the public domain by Jeffrey Walton and Han Lulu +// +// We understand future ARMv8 enhancements are supposed +// to include SM3 and SM4 related instructions so the function +// is stubbed for an eventual SM4_Round_ARMV8. + +#include "pch.h" +#include "config.h" + +#include "sm4.h" +#include "misc.h" +#include "cpu.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4307) +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::rotlConstant; + +CRYPTOPP_ALIGN_DATA(4) +const byte S[256] = +{ + 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, + 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, + 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, + 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, + 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, + 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, + 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, + 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, + 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, + 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, + 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, + 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, + 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, + 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, + 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48 +}; + +const word32 CK[32] = +{ + 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, + 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, + 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, + 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, + 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, + 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, + 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, + 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 +}; + +inline word32 SM4_H(word32 x) +{ + return (S[GETBYTE(x, 3)] << 24) | (S[GETBYTE(x, 2)] << 16) | (S[GETBYTE(x, 1)] << 8) | (S[GETBYTE(x, 0)]); +} + +inline word32 SM4_G(word32 x) +{ + const word32 t = SM4_H(x); + return t ^ rotlConstant<13>(t) ^ rotlConstant<23>(t); +} + +inline word32 SM4_F(word32 x) +{ + const word32 t = SM4_H(x); + return t ^ rotlConstant<2>(t) ^ rotlConstant<10>(t) ^ rotlConstant<18>(t) ^ rotlConstant<24>(t); +} + +template +inline void SM4_Round(word32 wspace[4], const word32 rkeys[32]) +{ + if (FWD) + { + wspace[0] ^= SM4_F(wspace[1] ^ wspace[2] ^ wspace[3] ^ rkeys[R+0]); + wspace[1] ^= SM4_F(wspace[0] ^ wspace[2] ^ wspace[3] ^ rkeys[R+1]); + wspace[2] ^= SM4_F(wspace[0] ^ wspace[1] ^ wspace[3] ^ rkeys[R+2]); + wspace[3] ^= SM4_F(wspace[0] ^ wspace[1] ^ wspace[2] ^ rkeys[R+3]); + } + else + { + wspace[0] ^= SM4_F(wspace[1] ^ wspace[2] ^ wspace[3] ^ rkeys[R-0]); + wspace[1] ^= SM4_F(wspace[0] ^ wspace[2] ^ wspace[3] ^ rkeys[R-1]); + wspace[2] ^= SM4_F(wspace[0] ^ wspace[1] ^ wspace[3] ^ rkeys[R-2]); + wspace[3] ^= SM4_F(wspace[0] ^ wspace[1] ^ wspace[2] ^ rkeys[R-3]); + } +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if CRYPTOPP_SM4_ADVANCED_PROCESS_BLOCKS +# if defined(CRYPTOPP_AESNI_AVAILABLE) +extern size_t SM4_Enc_AdvancedProcessBlocks_AESNI(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +# endif +#endif + +std::string SM4::Enc::AlgorithmProvider() const +{ +#if defined(CRYPTOPP_AESNI_AVAILABLE) + if (HasAESNI()) + return "AESNI"; +#endif + return "C++"; +} + +void SM4::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_ASSERT(keyLength == 16); + CRYPTOPP_UNUSED(params); + + m_rkeys.New(32); + m_wspace.New(5); + + GetUserKey(BIG_ENDIAN_ORDER, m_wspace.begin(), 4, userKey, keyLength); + m_wspace[0] ^= 0xa3b1bac6; m_wspace[1] ^= 0x56aa3350; + m_wspace[2] ^= 0x677d9197; m_wspace[3] ^= 0xb27022dc; + + size_t i=0; + do + { + m_rkeys[i] = (m_wspace[0] ^= SM4_G(m_wspace[1] ^ m_wspace[2] ^ m_wspace[3] ^ CK[i])); i++; + m_rkeys[i] = (m_wspace[1] ^= SM4_G(m_wspace[2] ^ m_wspace[3] ^ m_wspace[0] ^ CK[i])); i++; + m_rkeys[i] = (m_wspace[2] ^= SM4_G(m_wspace[3] ^ m_wspace[0] ^ m_wspace[1] ^ CK[i])); i++; + m_rkeys[i] = (m_wspace[3] ^= SM4_G(m_wspace[0] ^ m_wspace[1] ^ m_wspace[2] ^ CK[i])); i++; + } + while (i < 32); +} + +void SM4::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Reverse bytes on LittleEndian; align pointer on BigEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1])(m_wspace[2])(m_wspace[3]); + + // Timing attack countermeasure, see comments in Rijndael for more details. + // The hardening does not materially affect benchmarks. SM4 runs at + // 30.5 cpb on a Core i5 Skylake with and without the code below. + const int cacheLineSize = GetCacheLineSize(); + volatile word32 _u = 0; + word32 u = _u; + + for (unsigned int i=0; i(m_wspace, m_rkeys); + SM4_Round< 4, true>(m_wspace, m_rkeys); + SM4_Round< 8, true>(m_wspace, m_rkeys); + SM4_Round<12, true>(m_wspace, m_rkeys); + SM4_Round<16, true>(m_wspace, m_rkeys); + SM4_Round<20, true>(m_wspace, m_rkeys); + SM4_Round<24, true>(m_wspace, m_rkeys); + SM4_Round<28, true>(m_wspace, m_rkeys); + + // Reverse bytes on LittleEndian; align pointer on BigEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]); +} + +void SM4::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Reverse bytes on LittleEndian; align pointer on BigEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1])(m_wspace[2])(m_wspace[3]); + + // Timing attack countermeasure, see comments in Rijndael for more details. + // The hardening does not materially affect benchmarks. SM4 runs at + // 30.5 cpb on a Core i5 Skylake with and without the code below. + const int cacheLineSize = GetCacheLineSize(); + volatile word32 _u = 0; + word32 u = _u; + + for (unsigned int i=0; i(m_wspace, m_rkeys); + SM4_Round<27, false>(m_wspace, m_rkeys); + SM4_Round<23, false>(m_wspace, m_rkeys); + SM4_Round<19, false>(m_wspace, m_rkeys); + SM4_Round<15, false>(m_wspace, m_rkeys); + SM4_Round<11, false>(m_wspace, m_rkeys); + SM4_Round< 7, false>(m_wspace, m_rkeys); + SM4_Round< 3, false>(m_wspace, m_rkeys); + + // Reverse bytes on LittleEndian; align pointer on BigEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]); +} + +#if CRYPTOPP_SM4_ADVANCED_PROCESS_BLOCKS +size_t SM4::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, + byte *outBlocks, size_t length, word32 flags) const +{ +#if defined(CRYPTOPP_AESNI_AVAILABLE) + if (HasAESNI()) { + return SM4_Enc_AdvancedProcessBlocks_AESNI(m_rkeys, 32, + inBlocks, xorBlocks, outBlocks, length, flags); + } +#endif + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_SM4_ADVANCED_PROCESS_BLOCKS + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/sm4.h b/external/ours/library/crypto/src/shared/original/sm4.h new file mode 100755 index 000000000..67f76052f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 formely known as SMS4. +/// \details SM4 encryption is accelerated on machines with AES-NI. Decryption is not acclerated 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 formely 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 acclerated 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 acclerated 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/external/ours/library/crypto/src/shared/original/sm4_simd.cpp b/external/ours/library/crypto/src/shared/original/sm4_simd.cpp new file mode 100755 index 000000000..d19e05924 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/sm4_simd.cpp @@ -0,0 +1,323 @@ +// sm4_simd.cpp - written and placed in the public domain by +// Markku-Juhani O. Saarinen and Jeffrey Walton +// +// This source file uses intrinsics and built-ins to gain access to +// AESNI, ARM NEON and ARMv8a, and Power7 Altivec instructions. A separate +// source file is needed because additional CXXFLAGS are required to enable +// the appropriate instructions sets in some build configurations. +// +// AES-NI based on Markku-Juhani O. Saarinen work at https://github.com/mjosaarinen/sm4ni. +// +// ARMv8 is upcoming. + +#include "pch.h" +#include "config.h" + +#include "sm4.h" +#include "misc.h" + +// Uncomment for benchmarking C++ against SSE. +// Do so in both simon.cpp and simon_simd.cpp. +// #undef CRYPTOPP_AESNI_AVAILABLE + +#if (CRYPTOPP_AESNI_AVAILABLE) +# include "adv_simd.h" +# include +# include +# include +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char SM4_SIMD_FNAME[] = __FILE__; + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; + +#if (CRYPTOPP_AESNI_AVAILABLE) + +template +inline __m128i ShiftLeft(const __m128i& val) +{ + return _mm_slli_epi32(val, R); +} + +template +inline __m128i ShiftRight(const __m128i& val) +{ + return _mm_srli_epi32(val, R); +} + +template +inline __m128i ShiftLeft64(const __m128i& val) +{ + return _mm_slli_epi64(val, R); +} + +template +inline __m128i ShiftRight64(const __m128i& val) +{ + return _mm_srli_epi64(val, R); +} + +template +inline __m128i RotateLeft(const __m128i& val) +{ + return _mm_or_si128( + _mm_slli_epi32(val, R), _mm_srli_epi32(val, 32-R)); +} + +template +inline __m128i RotateRight(const __m128i& val) +{ + return _mm_or_si128( + _mm_slli_epi32(val, 32-R), _mm_srli_epi32(val, R)); +} + +template <> +inline __m128i RotateLeft<8>(const __m128i& val) +{ + const __m128i r08 = _mm_set_epi32(0x0E0D0C0F, 0x0A09080B, 0x06050407, 0x02010003); + return _mm_shuffle_epi8(val, r08); +} + +template <> +inline __m128i RotateLeft<16>(const __m128i& val) +{ + const __m128i mask = _mm_set_epi32(0x0D0C0F0E, 0x09080B0A, 0x05040706, 0x01000302); + return _mm_shuffle_epi8(val, mask); +} + +template <> +inline __m128i RotateLeft<24>(const __m128i& val) +{ + const __m128i mask = _mm_set_epi32(0x0C0F0E0D, 0x080B0A09, 0x04070605, 0x00030201); + return _mm_shuffle_epi8(val, mask); +} + +/// \brief Unpack XMM words +/// \tparam IDX the element from each XMM word +/// \param a the first XMM word +/// \param b the second XMM word +/// \param c the third XMM word +/// \param d the fourth XMM word +/// \details UnpackXMM selects the IDX element from a, b, c, d and returns a concatenation +/// equivalent to a[IDX] || b[IDX] || c[IDX] || d[IDX]. +template +inline __m128i UnpackXMM(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + // Should not be instantiated + CRYPTOPP_UNUSED(a); CRYPTOPP_UNUSED(b); + CRYPTOPP_UNUSED(c); CRYPTOPP_UNUSED(d); + CRYPTOPP_ASSERT(0); + return _mm_setzero_si128(); +} + +template <> +inline __m128i UnpackXMM<0>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + const __m128i r1 = _mm_unpacklo_epi32(a, b); + const __m128i r2 = _mm_unpacklo_epi32(c, d); + return _mm_unpacklo_epi64(r1, r2); +} + +template <> +inline __m128i UnpackXMM<1>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + const __m128i r1 = _mm_unpacklo_epi32(a, b); + const __m128i r2 = _mm_unpacklo_epi32(c, d); + return _mm_unpackhi_epi64(r1, r2); +} + +template <> +inline __m128i UnpackXMM<2>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + const __m128i r1 = _mm_unpackhi_epi32(a, b); + const __m128i r2 = _mm_unpackhi_epi32(c, d); + return _mm_unpacklo_epi64(r1, r2); +} + +template <> +inline __m128i UnpackXMM<3>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + const __m128i r1 = _mm_unpackhi_epi32(a, b); + const __m128i r2 = _mm_unpackhi_epi32(c, d); + return _mm_unpackhi_epi64(r1, r2); +} + +/// \brief Unpack a XMM word +/// \tparam IDX the element from each XMM word +/// \param v the first XMM word +/// \details UnpackXMM selects the IDX element from v and returns a concatenation +/// equivalent to v[IDX] || v[IDX] || v[IDX] || v[IDX]. +template +inline __m128i UnpackXMM(const __m128i& v) +{ + // Should not be instantiated + CRYPTOPP_UNUSED(v); CRYPTOPP_ASSERT(0); + return _mm_setzero_si128(); +} + +template <> +inline __m128i UnpackXMM<0>(const __m128i& v) +{ + // Splat to all lanes + return _mm_shuffle_epi8(v, _mm_set_epi8(3,2,1,0, 3,2,1,0, 3,2,1,0, 3,2,1,0)); +} + +template <> +inline __m128i UnpackXMM<1>(const __m128i& v) +{ + // Splat to all lanes + return _mm_shuffle_epi8(v, _mm_set_epi8(7,6,5,4, 7,6,5,4, 7,6,5,4, 7,6,5,4)); +} + +template <> +inline __m128i UnpackXMM<2>(const __m128i& v) +{ + // Splat to all lanes + return _mm_shuffle_epi8(v, _mm_set_epi8(11,10,9,8, 11,10,9,8, 11,10,9,8, 11,10,9,8)); +} + +template <> +inline __m128i UnpackXMM<3>(const __m128i& v) +{ + // Splat to all lanes + return _mm_shuffle_epi8(v, _mm_set_epi8(15,14,13,12, 15,14,13,12, 15,14,13,12, 15,14,13,12)); +} + +template +inline __m128i RepackXMM(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d) +{ + return UnpackXMM(a, b, c, d); +} + +template +inline __m128i RepackXMM(const __m128i& v) +{ + return UnpackXMM(v); +} + +inline void SM4_Encrypt(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, const word32 *subkeys) +{ + // nibble mask + const __m128i c0f = _mm_set_epi32(0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F); + + // flip all bytes in all 32-bit words + const __m128i flp = _mm_set_epi32(0x0C0D0E0F, 0x08090A0B, 0x04050607, 0x00010203); + + // inverse shift rows + const __m128i shr = _mm_set_epi32(0x0306090C, 0x0F020508, 0x0B0E0104, 0x070A0D00); + + // Affine transform 1 (low and high hibbles) + const __m128i m1l = _mm_set_epi32(0xC7C1B4B2, 0x22245157, 0x9197E2E4, 0x74720701); + const __m128i m1h = _mm_set_epi32(0xF052B91B, 0xF95BB012, 0xE240AB09, 0xEB49A200); + + // Affine transform 2 (low and high hibbles) + const __m128i m2l = _mm_set_epi32(0xEDD14478, 0x172BBE82, 0x5B67F2CE, 0xA19D0834); + const __m128i m2h = _mm_set_epi32(0x11CDBE62, 0xCC1063BF, 0xAE7201DD, 0x73AFDC00); + + __m128i t0 = UnpackXMM<0>(block0, block1, block2, block3); + __m128i t1 = UnpackXMM<1>(block0, block1, block2, block3); + __m128i t2 = UnpackXMM<2>(block0, block1, block2, block3); + __m128i t3 = UnpackXMM<3>(block0, block1, block2, block3); + + t0 = _mm_shuffle_epi8(t0, flp); + t1 = _mm_shuffle_epi8(t1, flp); + t2 = _mm_shuffle_epi8(t2, flp); + t3 = _mm_shuffle_epi8(t3, flp); + + const unsigned int ROUNDS = 32; + for (unsigned int i = 0; i < ROUNDS; i++) + { + const __m128i k = _mm_shuffle_epi32(_mm_castps_si128( + _mm_load_ss((const float*)(subkeys+i))), _MM_SHUFFLE(0,0,0,0)); + + __m128i x, y; + x = _mm_xor_si128(t1, _mm_xor_si128(t2, _mm_xor_si128(t3, k))); + + y = _mm_and_si128(x, c0f); // inner affine + y = _mm_shuffle_epi8(m1l, y); + x = _mm_and_si128(ShiftRight64<4>(x), c0f); + x = _mm_xor_si128(_mm_shuffle_epi8(m1h, x), y); + + x = _mm_shuffle_epi8(x, shr); // inverse MixColumns + x = _mm_aesenclast_si128(x, c0f); // AESNI instruction + + y = _mm_andnot_si128(x, c0f); // outer affine + y = _mm_shuffle_epi8(m2l, y); + x = _mm_and_si128(ShiftRight64<4>(x), c0f); + x = _mm_xor_si128(_mm_shuffle_epi8(m2h, x), y); + + // 4 parallel L1 linear transforms + y = _mm_xor_si128(x, RotateLeft<8>(x)); + y = _mm_xor_si128(y, RotateLeft<16>(x)); + y = _mm_xor_si128(ShiftLeft<2>(y), ShiftRight<30>(y)); + x = _mm_xor_si128(x, _mm_xor_si128(y, RotateLeft<24>(x))); + + // rotate registers + x = _mm_xor_si128(x, t0); + t0 = t1; t1 = t2; + t2 = t3; t3 = x; + } + + t0 = _mm_shuffle_epi8(t0, flp); + t1 = _mm_shuffle_epi8(t1, flp); + t2 = _mm_shuffle_epi8(t2, flp); + t3 = _mm_shuffle_epi8(t3, flp); + + block0 = RepackXMM<0>(t3,t2,t1,t0); + block1 = RepackXMM<1>(t3,t2,t1,t0); + block2 = RepackXMM<2>(t3,t2,t1,t0); + block3 = RepackXMM<3>(t3,t2,t1,t0); +} + +inline void SM4_Enc_4_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, const word32 *subkeys, unsigned int /*rounds*/) +{ + SM4_Encrypt(block0, block1, block2, block3, subkeys); +} + +inline void SM4_Dec_4_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, const word32 *subkeys, unsigned int /*rounds*/) +{ + SM4_Encrypt(block0, block1, block2, block3, subkeys); +} + +inline void SM4_Enc_Block(__m128i &block0, + const word32 *subkeys, unsigned int /*rounds*/) +{ + __m128i t1 = _mm_setzero_si128(); + __m128i t2 = _mm_setzero_si128(); + __m128i t3 = _mm_setzero_si128(); + + SM4_Encrypt(block0, t1, t2, t3, subkeys); +} + +inline void SM4_Dec_Block(__m128i &block0, + const word32 *subkeys, unsigned int /*rounds*/) +{ + __m128i t1 = _mm_setzero_si128(); + __m128i t2 = _mm_setzero_si128(); + __m128i t3 = _mm_setzero_si128(); + + SM4_Encrypt(block0, t1, t2, t3, subkeys); +} + +#endif // CRYPTOPP_AESNI_AVAILABLE + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_AESNI_AVAILABLE) +size_t SM4_Enc_AdvancedProcessBlocks_AESNI(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_4x1_SSE(SM4_Enc_Block, SM4_Enc_4_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_AESNI_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/smartptr.h b/external/ours/library/crypto/src/shared/original/smartptr.h index f5c0b41bd..04cb9a420 100755 --- a/external/ours/library/crypto/src/shared/original/smartptr.h +++ b/external/ours/library/crypto/src/shared/original/smartptr.h @@ -1,195 +1,257 @@ -#ifndef CRYPTOPP_SMARTPTR_H -#define CRYPTOPP_SMARTPTR_H - -#include "config.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -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 = 0; - return old_p; - } - - void reset(T *p = 0); - -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;} - -// ******************************************************** - -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; -} - -// ******************************************************** - -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; -} - -// ******************************************************** - -template class counted_ptr -{ -public: - explicit counted_ptr(T *p = 0); - 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 m_p; } - - const T* get() const { return m_p; } - T* get() { return m_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 counted_ptr & counted_ptr::operator=(const counted_ptr& rhs) -{ - 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; -} - -// ******************************************************** - -template class vector_member_ptrs -{ -public: - vector_member_ptrs(unsigned int size=0) - : _size(size) {ptr = new member_ptr[_size];} - ~vector_member_ptrs() - {delete [] ptr;} - - member_ptr& operator[](unsigned int index) - {assert(index<_size); return ptr[index];} - const member_ptr& operator[](unsigned int index) const - {assert(index<_size); return ptr[index];} - - unsigned int size() const {return _size;} - void resize(unsigned int newSize) - { - member_ptr *newPtr = new member_ptr[newSize]; - for (unsigned int i=0; i &c); // copy not allowed - void operator=(const vector_member_ptrs &x); // assignment not allowed - - unsigned int _size; - member_ptr *ptr; -}; - -// ******************************************************** - -// derive from this class for a temporary variable -// that can be used during base/member initialization -template -class ConstructorTemp -{ -protected: - ConstructorTemp(const ConstructorTemp ©) : m_temp(nullptr) {} - ConstructorTemp(T *t = nullptr) : m_temp(t) {} - ConstructorTemp(const T &t) : m_temp(new T(t)) {} - member_ptr m_temp; -}; - -NAMESPACE_END - -#endif +// 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 arry 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/external/ours/library/crypto/src/shared/original/sosemanuk.cpp b/external/ours/library/crypto/src/shared/original/sosemanuk.cpp new file mode 100755 index 000000000..82cf8c92b --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/sosemanuk.cpp @@ -0,0 +1,728 @@ +// sosemanuk.cpp - originally written and placed in the public domain by Wei Dai + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sosemanuk.cpp" to generate MASM code + +#include "pch.h" +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4702 4731) +#endif + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#include "sosemanuk.h" +#include "serpentp.h" +#include "secblock.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +std::string SosemanukPolicy::AlgorithmProvider() const +{ +#ifndef CRYPTOPP_DISABLE_SOSEMANUK_ASM +# if CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return "SSE2"; +# endif +#endif + return "C++"; +} + +void SosemanukPolicy::CipherSetKey(const NameValuePairs ¶ms, const byte *userKey, size_t keylen) +{ + CRYPTOPP_UNUSED(params); + Serpent_KeySchedule(m_key, 24, userKey, keylen); +} + +void SosemanukPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(iv), CRYPTOPP_UNUSED(length); + CRYPTOPP_ASSERT(length==16); + + word32 a, b, c, d, e; + + typedef BlockGetAndPut Block; + Block::Get(iv)(a)(b)(c)(d); + + const word32 *k = m_key; + unsigned int i=1; + + do + { + beforeS0(KX); beforeS0(S0); afterS0(LT); + afterS0(KX); afterS0(S1); afterS1(LT); + if (i == 3) // after 18th round + { + m_state[4] = b; + m_state[5] = e; + m_state[10] = c; + m_state[11] = a; + } + afterS1(KX); afterS1(S2); afterS2(LT); + afterS2(KX); afterS2(S3); afterS3(LT); + if (i == 2) // after 12th round + { + m_state[6] = c; + m_state[7] = d; + m_state[8] = b; + m_state[9] = e; + } + afterS3(KX); afterS3(S4); afterS4(LT); + afterS4(KX); afterS4(S5); afterS5(LT); + afterS5(KX); afterS5(S6); afterS6(LT); + afterS6(KX); afterS6(S7); afterS7(LT); + + if (i == 3) + break; + + ++i; + c = b; + b = e; + e = d; + d = a; + a = e; + k += 32; + } + while (true); + + afterS7(KX); + + m_state[0] = a; + m_state[1] = b; + m_state[2] = e; + m_state[3] = d; + +#define XMUX(c, x, y) (x ^ (y & (0 - (c & 1)))) + m_state[11] += XMUX(m_state[10], m_state[1], m_state[8]); + m_state[10] = rotlConstant<7>(m_state[10] * 0x54655307); +} + +extern "C" { +word32 s_sosemanukMulTables[512] = { +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) && !defined(CRYPTOPP_DISABLE_SOSEMANUK_ASM) + 0x00000000, 0xE19FCF12, 0x6B973724, 0x8A08F836, + 0xD6876E48, 0x3718A15A, 0xBD10596C, 0x5C8F967E, + 0x05A7DC90, 0xE4381382, 0x6E30EBB4, 0x8FAF24A6, + 0xD320B2D8, 0x32BF7DCA, 0xB8B785FC, 0x59284AEE, + 0x0AE71189, 0xEB78DE9B, 0x617026AD, 0x80EFE9BF, + 0xDC607FC1, 0x3DFFB0D3, 0xB7F748E5, 0x566887F7, + 0x0F40CD19, 0xEEDF020B, 0x64D7FA3D, 0x8548352F, + 0xD9C7A351, 0x38586C43, 0xB2509475, 0x53CF5B67, + 0x146722BB, 0xF5F8EDA9, 0x7FF0159F, 0x9E6FDA8D, + 0xC2E04CF3, 0x237F83E1, 0xA9777BD7, 0x48E8B4C5, + 0x11C0FE2B, 0xF05F3139, 0x7A57C90F, 0x9BC8061D, + 0xC7479063, 0x26D85F71, 0xACD0A747, 0x4D4F6855, + 0x1E803332, 0xFF1FFC20, 0x75170416, 0x9488CB04, + 0xC8075D7A, 0x29989268, 0xA3906A5E, 0x420FA54C, + 0x1B27EFA2, 0xFAB820B0, 0x70B0D886, 0x912F1794, + 0xCDA081EA, 0x2C3F4EF8, 0xA637B6CE, 0x47A879DC, + 0x28CE44DF, 0xC9518BCD, 0x435973FB, 0xA2C6BCE9, + 0xFE492A97, 0x1FD6E585, 0x95DE1DB3, 0x7441D2A1, + 0x2D69984F, 0xCCF6575D, 0x46FEAF6B, 0xA7616079, + 0xFBEEF607, 0x1A713915, 0x9079C123, 0x71E60E31, + 0x22295556, 0xC3B69A44, 0x49BE6272, 0xA821AD60, + 0xF4AE3B1E, 0x1531F40C, 0x9F390C3A, 0x7EA6C328, + 0x278E89C6, 0xC61146D4, 0x4C19BEE2, 0xAD8671F0, + 0xF109E78E, 0x1096289C, 0x9A9ED0AA, 0x7B011FB8, + 0x3CA96664, 0xDD36A976, 0x573E5140, 0xB6A19E52, + 0xEA2E082C, 0x0BB1C73E, 0x81B93F08, 0x6026F01A, + 0x390EBAF4, 0xD89175E6, 0x52998DD0, 0xB30642C2, + 0xEF89D4BC, 0x0E161BAE, 0x841EE398, 0x65812C8A, + 0x364E77ED, 0xD7D1B8FF, 0x5DD940C9, 0xBC468FDB, + 0xE0C919A5, 0x0156D6B7, 0x8B5E2E81, 0x6AC1E193, + 0x33E9AB7D, 0xD276646F, 0x587E9C59, 0xB9E1534B, + 0xE56EC535, 0x04F10A27, 0x8EF9F211, 0x6F663D03, + 0x50358817, 0xB1AA4705, 0x3BA2BF33, 0xDA3D7021, + 0x86B2E65F, 0x672D294D, 0xED25D17B, 0x0CBA1E69, + 0x55925487, 0xB40D9B95, 0x3E0563A3, 0xDF9AACB1, + 0x83153ACF, 0x628AF5DD, 0xE8820DEB, 0x091DC2F9, + 0x5AD2999E, 0xBB4D568C, 0x3145AEBA, 0xD0DA61A8, + 0x8C55F7D6, 0x6DCA38C4, 0xE7C2C0F2, 0x065D0FE0, + 0x5F75450E, 0xBEEA8A1C, 0x34E2722A, 0xD57DBD38, + 0x89F22B46, 0x686DE454, 0xE2651C62, 0x03FAD370, + 0x4452AAAC, 0xA5CD65BE, 0x2FC59D88, 0xCE5A529A, + 0x92D5C4E4, 0x734A0BF6, 0xF942F3C0, 0x18DD3CD2, + 0x41F5763C, 0xA06AB92E, 0x2A624118, 0xCBFD8E0A, + 0x97721874, 0x76EDD766, 0xFCE52F50, 0x1D7AE042, + 0x4EB5BB25, 0xAF2A7437, 0x25228C01, 0xC4BD4313, + 0x9832D56D, 0x79AD1A7F, 0xF3A5E249, 0x123A2D5B, + 0x4B1267B5, 0xAA8DA8A7, 0x20855091, 0xC11A9F83, + 0x9D9509FD, 0x7C0AC6EF, 0xF6023ED9, 0x179DF1CB, + 0x78FBCCC8, 0x996403DA, 0x136CFBEC, 0xF2F334FE, + 0xAE7CA280, 0x4FE36D92, 0xC5EB95A4, 0x24745AB6, + 0x7D5C1058, 0x9CC3DF4A, 0x16CB277C, 0xF754E86E, + 0xABDB7E10, 0x4A44B102, 0xC04C4934, 0x21D38626, + 0x721CDD41, 0x93831253, 0x198BEA65, 0xF8142577, + 0xA49BB309, 0x45047C1B, 0xCF0C842D, 0x2E934B3F, + 0x77BB01D1, 0x9624CEC3, 0x1C2C36F5, 0xFDB3F9E7, + 0xA13C6F99, 0x40A3A08B, 0xCAAB58BD, 0x2B3497AF, + 0x6C9CEE73, 0x8D032161, 0x070BD957, 0xE6941645, + 0xBA1B803B, 0x5B844F29, 0xD18CB71F, 0x3013780D, + 0x693B32E3, 0x88A4FDF1, 0x02AC05C7, 0xE333CAD5, + 0xBFBC5CAB, 0x5E2393B9, 0xD42B6B8F, 0x35B4A49D, + 0x667BFFFA, 0x87E430E8, 0x0DECC8DE, 0xEC7307CC, + 0xB0FC91B2, 0x51635EA0, 0xDB6BA696, 0x3AF46984, + 0x63DC236A, 0x8243EC78, 0x084B144E, 0xE9D4DB5C, + 0xB55B4D22, 0x54C48230, 0xDECC7A06, 0x3F53B514, +#else + 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835, + 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679, + 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, + 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1, + 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, + 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0, + 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, + 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78, + 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, + 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2, + 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, + 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A, + 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, + 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B, + 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, + 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3, + 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, + 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6, + 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, + 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E, + 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, + 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F, + 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, + 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7, + 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, + 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D, + 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, + 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5, + 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, + 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4, + 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, + 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C, + 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, + 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE, + 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, + 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276, + 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, + 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77, + 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, + 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF, + 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, + 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75, + 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, + 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED, + 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, + 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC, + 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, + 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174, + 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, + 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71, + 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, + 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9, + 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, + 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8, + 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, + 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770, + 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6, + 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA, + 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E, + 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472, + 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F, + 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973, + 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7, + 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB, +#endif + 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, + 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998, + 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, + 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254, + 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, + 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9, + 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, + 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65, + 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, + 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA, + 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, + 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36, + 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, + 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB, + 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, + 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307, + 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, + 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C, + 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, + 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790, + 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, + 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D, + 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, + 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1, + 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, + 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E, + 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094, + 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2, + 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, + 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F, + 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5, + 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3, + 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, + 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9, + 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813, + 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175, + 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, + 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588, + 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, + 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44, + 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, + 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB, + 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, + 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17, + 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, + 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA, + 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, + 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026, + 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, + 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D, + 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, + 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1, + 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, + 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C, + 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, + 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80, + 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879, + 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F, + 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, + 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3, + 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748, + 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E, + 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, + 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2 +}; +} + +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +unsigned int SosemanukPolicy::GetAlignment() const +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE +#ifdef __INTEL_COMPILER + if (HasSSE2() && !IsP4()) // Intel compiler produces faster code for this algorithm on the P4 +#else + if (HasSSE2()) +#endif + return 16; + else +#endif + return GetAlignmentOf(); +} + +unsigned int SosemanukPolicy::GetOptimalBlockSize() const +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE +#ifdef __INTEL_COMPILER + if (HasSSE2() && !IsP4()) // Intel compiler produces faster code for this algorithm on the P4 +#else + if (HasSSE2()) +#endif + return 4*BYTES_PER_ITERATION; + else +#endif + return BYTES_PER_ITERATION; +} +#endif + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void Sosemanuk_OperateKeystream(size_t iterationCount, const byte *input, byte *output, word32 *state); +} +#endif + +void SosemanukPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ +#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE + Sosemanuk_OperateKeystream(iterationCount, input, output, m_state.data()); + return; +#endif + +#if CRYPTOPP_SSE2_ASM_AVAILABLE && !defined(CRYPTOPP_DISABLE_SOSEMANUK_ASM) +#ifdef CRYPTOPP_GENERATE_X64_MASM + ALIGN 8 + Sosemanuk_OperateKeystream PROC FRAME + rex_push_reg rsi + push_reg rdi + alloc_stack(80*4*2+12*4+8*WORD_SZ + 2*16+8) + save_xmm128 xmm6, 02f0h + save_xmm128 xmm7, 0300h + .endprolog + mov rdi, r8 + mov rax, r9 +#else +#ifdef __INTEL_COMPILER + if (HasSSE2() && !IsP4()) // Intel compiler produces faster code for this algorithm on the P4 +#else + if (HasSSE2()) +#endif + { +#ifdef __GNUC__ + #if CRYPTOPP_BOOL_X64 + FixedSizeAlignedSecBlock workspace; + #endif + __asm__ __volatile__ + ( + INTEL_NOPREFIX + AS_PUSH_IF86( bx) +#else + word32 *state = m_state; + AS2( mov WORD_REG(ax), state) + AS2( mov WORD_REG(di), output) + AS2( mov WORD_REG(dx), input) + AS2( mov WORD_REG(cx), iterationCount) +#endif +#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM + +#if defined(__GNUC__) && CRYPTOPP_BOOL_X64 + #define SSE2_workspace %5 +#else + #define SSE2_workspace WORD_REG(sp) +#endif + +#define SSE2_output WORD_PTR [SSE2_workspace+1*WORD_SZ] +#define SSE2_input WORD_PTR [SSE2_workspace+2*WORD_SZ] +#define SSE2_wordsLeft WORD_PTR [SSE2_workspace+3*WORD_SZ] +#define SSE2_diEnd WORD_PTR [SSE2_workspace+4*WORD_SZ] +#define SSE2_pMulTables WORD_PTR [SSE2_workspace+5*WORD_SZ] +#define SSE2_state WORD_PTR [SSE2_workspace+6*WORD_SZ] +#define SSE2_wordsLeft2 WORD_PTR [SSE2_workspace+7*WORD_SZ] +#define SSE2_stateCopy SSE2_workspace + 8*WORD_SZ +#define SSE2_uvStart SSE2_stateCopy + 12*4 + +#if (CRYPTOPP_BOOL_X86) && !defined(CRYPTOPP_DISABLE_SOSEMANUK_ASM) + AS_PUSH_IF86( bp) + AS2( mov AS_REG_6, esp) + AS2( and esp, -16) + AS2( sub esp, 80*4*2+12*4+8*WORD_SZ) // 80 v's, 80 u's, 12 state, 8 locals + AS2( mov [esp], AS_REG_6) +#endif + AS2( mov SSE2_output, WORD_REG(di)) + AS2( mov SSE2_input, WORD_REG(dx)) + AS2( mov SSE2_state, WORD_REG(ax)) +#ifndef _MSC_VER + AS2( mov SSE2_pMulTables, WORD_REG(si)) +#endif + AS2( lea WORD_REG(cx), [4*WORD_REG(cx)+WORD_REG(cx)]) + AS2( lea WORD_REG(si), [4*WORD_REG(cx)]) + AS2( mov SSE2_wordsLeft, WORD_REG(si)) + AS2( movdqa xmm0, [WORD_REG(ax)+0*16]) // copy state to stack to save a register + AS2( movdqa [SSE2_stateCopy+0*16], xmm0) + AS2( movdqa xmm0, [WORD_REG(ax)+1*16]) + AS2( movdqa [SSE2_stateCopy+1*16], xmm0) + AS2( movq xmm0, QWORD PTR [WORD_REG(ax)+2*16]) + AS2( movq QWORD PTR [SSE2_stateCopy+2*16], xmm0) + AS2( psrlq xmm0, 32) + AS2( movd AS_REG_6d, xmm0) // s(9) + AS2( mov ecx, [WORD_REG(ax)+10*4]) + AS2( mov edx, [WORD_REG(ax)+11*4]) + AS2( pcmpeqb xmm7, xmm7) // all ones + +#define s(i) SSE2_stateCopy + ASM_MOD(i,10)*4 +#define u(j) WORD_REG(di) + (ASM_MOD(j,4)*20 + (j/4)) * 4 +#define v(j) WORD_REG(di) + (ASM_MOD(j,4)*20 + (j/4)) * 4 + 80*4 + +#define R10 ecx +#define R11 edx +#define R20 edx +#define R21 ecx +// workaround bug in GAS 2.15 +#define R20r WORD_REG(dx) +#define R21r WORD_REG(cx) + +#define SSE2_STEP(i, j) \ + AS2( mov eax, [s(i+0)])\ + AS2( mov [v(i)], eax)\ + AS2( rol eax, 8)\ + AS2( lea AS_REG_7, [AS_REG_6 + R2##j##r])\ + AS2( xor AS_REG_7d, R1##j)\ + AS2( mov [u(i)], AS_REG_7d)\ + AS2( mov AS_REG_7d, 1)\ + AS2( and AS_REG_7d, R2##j)\ + AS1( neg AS_REG_7d)\ + AS2( and AS_REG_7d, AS_REG_6d)\ + AS2( xor AS_REG_6d, eax)\ + AS2( movzx eax, al)\ + AS2( xor AS_REG_6d, [WORD_REG(si)+WORD_REG(ax)*4])\ + AS2( mov eax, [s(i+3)])\ + AS2( xor AS_REG_7d, [s(i+2)])\ + AS2( add R1##j, AS_REG_7d)\ + AS2( movzx AS_REG_7d, al)\ + AS2( shr eax, 8)\ + AS2( xor AS_REG_6d, [WORD_REG(si)+1024+AS_REG_7*4])\ + AS2( xor AS_REG_6d, eax)\ + AS2( imul R2##j, AS_HEX(54655307))\ + AS2( rol R2##j, 7)\ + AS2( mov [s(i+0)], AS_REG_6d)\ + + ASL(2) // outer loop, each iteration of this processes 80 words + AS2( lea WORD_REG(di), [SSE2_uvStart]) // start of v and u + AS2( mov WORD_REG(ax), 80) + AS2( cmp WORD_REG(si), 80) + AS2( cmovg WORD_REG(si), WORD_REG(ax)) + AS2( mov SSE2_wordsLeft2, WORD_REG(si)) + AS2( lea WORD_REG(si), [WORD_REG(di)+WORD_REG(si)]) // use to end first inner loop + AS2( mov SSE2_diEnd, WORD_REG(si)) +#ifdef _MSC_VER + AS2( lea WORD_REG(si), s_sosemanukMulTables) +#else + AS2( mov WORD_REG(si), SSE2_pMulTables) +#endif + + ASL(0) // first inner loop, 20 words each, 4 iterations + SSE2_STEP(0, 0) + SSE2_STEP(1, 1) + SSE2_STEP(2, 0) + SSE2_STEP(3, 1) + SSE2_STEP(4, 0) + SSE2_STEP(5, 1) + SSE2_STEP(6, 0) + SSE2_STEP(7, 1) + SSE2_STEP(8, 0) + SSE2_STEP(9, 1) + SSE2_STEP(10, 0) + SSE2_STEP(11, 1) + SSE2_STEP(12, 0) + SSE2_STEP(13, 1) + SSE2_STEP(14, 0) + SSE2_STEP(15, 1) + SSE2_STEP(16, 0) + SSE2_STEP(17, 1) + SSE2_STEP(18, 0) + SSE2_STEP(19, 1) + // loop + AS2( add WORD_REG(di), 5*4) + AS2( cmp WORD_REG(di), SSE2_diEnd) + ASJ( jne, 0, b) + + AS2( mov WORD_REG(ax), SSE2_input) + AS2( mov AS_REG_7, SSE2_output) + AS2( lea WORD_REG(di), [SSE2_uvStart]) // start of v and u + AS2( mov WORD_REG(si), SSE2_wordsLeft2) + + ASL(1) // second inner loop, 16 words each, 5 iterations + AS2( movdqa xmm0, [WORD_REG(di)+0*20*4]) + AS2( movdqa xmm2, [WORD_REG(di)+2*20*4]) + AS2( movdqa xmm3, [WORD_REG(di)+3*20*4]) + AS2( movdqa xmm1, [WORD_REG(di)+1*20*4]) + // S2 + AS2( movdqa xmm4, xmm0) + AS2( pand xmm0, xmm2) + AS2( pxor xmm0, xmm3) + AS2( pxor xmm2, xmm1) + AS2( pxor xmm2, xmm0) + AS2( por xmm3, xmm4) + AS2( pxor xmm3, xmm1) + AS2( pxor xmm4, xmm2) + AS2( movdqa xmm1, xmm3) + AS2( por xmm3, xmm4) + AS2( pxor xmm3, xmm0) + AS2( pand xmm0, xmm1) + AS2( pxor xmm4, xmm0) + AS2( pxor xmm1, xmm3) + AS2( pxor xmm1, xmm4) + AS2( pxor xmm4, xmm7) + // xor with v + AS2( pxor xmm2, [WORD_REG(di)+80*4]) + AS2( pxor xmm3, [WORD_REG(di)+80*5]) + AS2( pxor xmm1, [WORD_REG(di)+80*6]) + AS2( pxor xmm4, [WORD_REG(di)+80*7]) + // exit loop early if less than 16 words left to output + // this is necessary because block size is 20 words, and we output 16 words in each iteration of this loop + AS2( cmp WORD_REG(si), 16) + ASJ( jl, 4, f) + // unpack + AS2( movdqa xmm6, xmm2) + AS2( punpckldq xmm2, xmm3) + AS2( movdqa xmm5, xmm1) + AS2( punpckldq xmm1, xmm4) + AS2( movdqa xmm0, xmm2) + AS2( punpcklqdq xmm2, xmm1) + AS2( punpckhqdq xmm0, xmm1) + AS2( punpckhdq xmm6, xmm3) + AS2( punpckhdq xmm5, xmm4) + AS2( movdqa xmm3, xmm6) + AS2( punpcklqdq xmm6, xmm5) + AS2( punpckhqdq xmm3, xmm5) + + // output keystream + AS_XMM_OUTPUT4(SSE2_Sosemanuk_Output, WORD_REG(ax), AS_REG_7, 2,0,6,3, 1, 0,1,2,3, 4) + + // loop + AS2( add WORD_REG(di), 4*4) + AS2( sub WORD_REG(si), 16) + ASJ( jnz, 1, b) + + // outer loop + AS2( mov WORD_REG(si), SSE2_wordsLeft) + AS2( sub WORD_REG(si), 80) + ASJ( jz, 6, f) + AS2( mov SSE2_wordsLeft, WORD_REG(si)) + AS2( mov SSE2_input, WORD_REG(ax)) + AS2( mov SSE2_output, AS_REG_7) + ASJ( jmp, 2, b) + + ASL(4) // final output of less than 16 words + AS2( test WORD_REG(ax), WORD_REG(ax)) + ASJ( jz, 5, f) + AS2( movd xmm0, dword ptr [WORD_REG(ax)+0*4]) + AS2( pxor xmm2, xmm0) + AS2( movd xmm0, dword ptr [WORD_REG(ax)+1*4]) + AS2( pxor xmm3, xmm0) + AS2( movd xmm0, dword ptr [WORD_REG(ax)+2*4]) + AS2( pxor xmm1, xmm0) + AS2( movd xmm0, dword ptr [WORD_REG(ax)+3*4]) + AS2( pxor xmm4, xmm0) + AS2( add WORD_REG(ax), 16) + ASL(5) + AS2( movd dword ptr [AS_REG_7+0*4], xmm2) + AS2( movd dword ptr [AS_REG_7+1*4], xmm3) + AS2( movd dword ptr [AS_REG_7+2*4], xmm1) + AS2( movd dword ptr [AS_REG_7+3*4], xmm4) + AS2( sub WORD_REG(si), 4) + ASJ( jz, 6, f) + AS2( add AS_REG_7, 16) + AS2( psrldq xmm2, 4) + AS2( psrldq xmm3, 4) + AS2( psrldq xmm1, 4) + AS2( psrldq xmm4, 4) + ASJ( jmp, 4, b) + + ASL(6) // save state + AS2( mov AS_REG_6, SSE2_state) + AS2( movdqa xmm0, [SSE2_stateCopy+0*16]) + AS2( movdqa [AS_REG_6+0*16], xmm0) + AS2( movdqa xmm0, [SSE2_stateCopy+1*16]) + AS2( movdqa [AS_REG_6+1*16], xmm0) + AS2( movq xmm0, QWORD PTR [SSE2_stateCopy+2*16]) + AS2( movq QWORD PTR [AS_REG_6+2*16], xmm0) + AS2( mov [AS_REG_6+10*4], ecx) + AS2( mov [AS_REG_6+11*4], edx) + + AS_POP_IF86( sp) + AS_POP_IF86( bp) + +#ifdef __GNUC__ + AS_POP_IF86( bx) + ATT_PREFIX + : + : "a" (m_state.data()), "c" (iterationCount), "S" (s_sosemanukMulTables), "D" (output), "d" (input) + #if CRYPTOPP_BOOL_X64 + , "r" (workspace.data()) + : "memory", "cc", "%r9", "%r10", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" + #else + : "memory", "cc" + #endif + ); +#endif +#ifdef CRYPTOPP_GENERATE_X64_MASM + movdqa xmm6, [rsp + 02f0h] + movdqa xmm7, [rsp + 0300h] + add rsp, 80*4*2+12*4+8*WORD_SZ + 2*16+8 + pop rdi + pop rsi + ret + Sosemanuk_OperateKeystream ENDP +#else + } + else +#endif +#endif +#ifndef CRYPTOPP_GENERATE_X64_MASM + { +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) && !defined(CRYPTOPP_DISABLE_SOSEMANUK_ASM) +#define MUL_A(x) (x = (rotlConstant<8>(x)), x ^ s_sosemanukMulTables[byte(x)]) +#else +#define MUL_A(x) (((x) << 8) ^ s_sosemanukMulTables[(x) >> 24]) +#endif + +#define DIV_A(x) (((x) >> 8) ^ s_sosemanukMulTables[256 + byte(x)]) + +#define r1(i) ((i%2) ? reg2 : reg1) +#define r2(i) ((i%2) ? reg1 : reg2) + +#define STEP(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, v, u) \ + u = (s##x9 + r2(x0)) ^ r1(x0);\ + t = v = s##x0;\ + s##x0 = MUL_A(t) ^ DIV_A(s##x3) ^ s##x9;\ + r1(x0) += XMUX(r2(x0), s##x2, s##x9);\ + r2(x0) = rotlFixed(r2(x0) * 0x54655307, 7);\ + +#define SOSEMANUK_OUTPUT(x) \ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, u2 ^ v0);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, u3 ^ v1);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, u1 ^ v2);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, u4 ^ v3); + +#define OUTPUT4 \ + S2(0, u0, u1, u2, u3, u4);\ + CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(SOSEMANUK_OUTPUT, 4*4); + + word32 s0 = m_state[0]; + word32 s1 = m_state[1]; + word32 s2 = m_state[2]; + word32 s3 = m_state[3]; + word32 s4 = m_state[4]; + word32 s5 = m_state[5]; + word32 s6 = m_state[6]; + word32 s7 = m_state[7]; + word32 s8 = m_state[8]; + word32 s9 = m_state[9]; + word32 reg1 = m_state[10]; + word32 reg2 = m_state[11]; + word32 t, u0, u1, u2, u3, u4, v0, v1, v2, v3; + + do + { + STEP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, v0, u0) + STEP(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, v1, u1) + STEP(2, 3, 4, 5, 6, 7, 8, 9, 0, 1, v2, u2) + STEP(3, 4, 5, 6, 7, 8, 9, 0, 1, 2, v3, u3) + OUTPUT4 + STEP(4, 5, 6, 7, 8, 9, 0, 1, 2, 3, v0, u0) + STEP(5, 6, 7, 8, 9, 0, 1, 2, 3, 4, v1, u1) + STEP(6, 7, 8, 9, 0, 1, 2, 3, 4, 5, v2, u2) + STEP(7, 8, 9, 0, 1, 2, 3, 4, 5, 6, v3, u3) + OUTPUT4 + STEP(8, 9, 0, 1, 2, 3, 4, 5, 6, 7, v0, u0) + STEP(9, 0, 1, 2, 3, 4, 5, 6, 7, 8, v1, u1) + STEP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, v2, u2) + STEP(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, v3, u3) + OUTPUT4 + STEP(2, 3, 4, 5, 6, 7, 8, 9, 0, 1, v0, u0) + STEP(3, 4, 5, 6, 7, 8, 9, 0, 1, 2, v1, u1) + STEP(4, 5, 6, 7, 8, 9, 0, 1, 2, 3, v2, u2) + STEP(5, 6, 7, 8, 9, 0, 1, 2, 3, 4, v3, u3) + OUTPUT4 + STEP(6, 7, 8, 9, 0, 1, 2, 3, 4, 5, v0, u0) + STEP(7, 8, 9, 0, 1, 2, 3, 4, 5, 6, v1, u1) + STEP(8, 9, 0, 1, 2, 3, 4, 5, 6, 7, v2, u2) + STEP(9, 0, 1, 2, 3, 4, 5, 6, 7, 8, v3, u3) + OUTPUT4 + } + while (--iterationCount); + + m_state[0] = s0; + m_state[1] = s1; + m_state[2] = s2; + m_state[3] = s3; + m_state[4] = s4; + m_state[5] = s5; + m_state[6] = s6; + m_state[7] = s7; + m_state[8] = s8; + m_state[9] = s9; + m_state[10] = reg1; + m_state[11] = reg2; + } +} + +NAMESPACE_END + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM diff --git a/external/ours/library/crypto/src/shared/original/sosemanuk.h b/external/ours/library/crypto/src/shared/original/sosemanuk.h new file mode 100755 index 000000000..94ebcfead --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/speck.cpp b/external/ours/library/crypto/src/shared/original/speck.cpp new file mode 100755 index 000000000..00b960d78 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/speck.cpp @@ -0,0 +1,487 @@ +// speck.cpp - written and placed in the public domain by Jeffrey Walton + +#include "pch.h" +#include "config.h" + +#include "speck.h" +#include "misc.h" +#include "cpu.h" + +// Uncomment for benchmarking C++ against SSE or NEON. +// Do so in both speck.cpp and speck_simd.cpp. +// #undef CRYPTOPP_SSSE3_AVAILABLE +// #undef CRYPTOPP_SSE41_AVAILABLE +// #undef CRYPTOPP_ARM_NEON_AVAILABLE + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::rotlConstant; +using CryptoPP::rotrConstant; + +/// \brief Forward round transformation +/// \tparam W word type +/// \details TF83() is the forward round transformation using a=8 and b=3 rotations. +/// The initial test implementation provided template parameters, but they were +/// removed because SPECK32 using a=7 and b=2 was not on the road map. The +/// additional template parameters also made calling SPECK_Encrypt and SPECK_Decrypt +/// kind of messy. +template +inline void TF83(W& x, W& y, const W k) +{ + x = rotrConstant<8>(x); + x += y; x ^= k; + y = rotlConstant<3>(y); + y ^= x; +} + +/// \brief Reverse round transformation +/// \tparam W word type +/// \details TR83() is the reverse round transformation using a=8 and b=3 rotations. +/// The initial test implementation provided template parameters, but they were +/// removed because SPECK32 using a=7 and b=2 was not on the road map. The +/// additional template parameters also made calling SPECK_Encrypt and SPECK_Decrypt +/// kind of messy. +template +inline void TR83(W& x, W& y, const W k) +{ + y ^= x; + y = rotrConstant<3>(y); + x ^= k; x -= y; + x = rotlConstant<8>(x); +} + +/// \brief Forward transformation +/// \tparam W word type +/// \tparam R number of rounds +/// \param c output array +/// \param p input array +/// \param k subkey array +template +inline void SPECK_Encrypt(W c[2], const W p[2], const W k[R]) +{ + c[0]=p[0]; c[1]=p[1]; + + // Don't unroll this loop. Things slow down. + for (int i = 0; i < static_cast(R); ++i) + TF83(c[0], c[1], k[i]); +} + +/// \brief Reverse transformation +/// \tparam W word type +/// \tparam R number of rounds +/// \param p output array +/// \param c input array +/// \param k subkey array +template +inline void SPECK_Decrypt(W p[2], const W c[2], const W k[R]) +{ + p[0]=c[0]; p[1]=c[1]; + + // Don't unroll this loop. Things slow down. + for (int i = static_cast(R-1); i >= 0; --i) + TR83(p[0], p[1], k[i]); +} + +/// \brief Subkey generation function +/// \details Used when the user key consists of 2 words +/// \tparam W word type +/// \tparam R number of rounds +/// \param key empty subkey array +/// \param k user key array +template +inline void SPECK_ExpandKey_2W(W key[R], const W k[2]) +{ + CRYPTOPP_ASSERT(R==32); + W i=0, B=k[0], A=k[1]; + + while (i +inline void SPECK_ExpandKey_3W(W key[R], const W k[3]) +{ + CRYPTOPP_ASSERT(R==33 || R==26); + W i=0, C=k[0], B=k[1], A=k[2]; + + unsigned int blocks = R/2; + while (blocks--) + { + key[i+0]=A; TF83(B, A, i+0); + key[i+1]=A; TF83(C, A, i+1); + i+=2; + } + + // The constexpr residue should allow the optimizer to remove unneeded statements + if(R%2 == 1) + { + key[R-1]=A; + } +} + +/// \brief Subkey generation function +/// \details Used when the user key consists of 4 words +/// \tparam W word type +/// \tparam R number of rounds +/// \param key empty subkey array +/// \param k user key array +template +inline void SPECK_ExpandKey_4W(W key[R], const W k[4]) +{ + CRYPTOPP_ASSERT(R==34 || R==27); + W i=0, D=k[0], C=k[1], B=k[2], A=k[3]; + + unsigned int blocks = R/3; + while (blocks--) + { + key[i+0]=A; TF83(B, A, i+0); + key[i+1]=A; TF83(C, A, i+1); + key[i+2]=A; TF83(D, A, i+2); + i+=3; + } + + // The constexpr residue should allow the optimizer to remove unneeded statements + if(R%3 == 1) + { + key[R-1]=A; + } + else if(R%3 == 2) + { + key[R-2]=A; TF83(B, A, W(R-2)); + key[R-1]=A; + } +} + +ANONYMOUS_NAMESPACE_END + +/////////////////////////////////////////////////////////// + +NAMESPACE_BEGIN(CryptoPP) + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) +extern size_t SPECK128_Enc_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t SPECK128_Dec_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +#if (CRYPTOPP_SSE41_AVAILABLE) +extern size_t SPECK64_Enc_AdvancedProcessBlocks_SSE41(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t SPECK64_Dec_AdvancedProcessBlocks_SSE41(const word32* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +#if (CRYPTOPP_SSSE3_AVAILABLE) +extern size_t SPECK128_Enc_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t SPECK128_Dec_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) +extern size_t SPECK128_Enc_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); + +extern size_t SPECK128_Dec_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags); +#endif + +std::string SPECK64::Base::AlgorithmProvider() const +{ + return "C++"; +} + +unsigned int SPECK64::Base::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +void SPECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16); + CRYPTOPP_UNUSED(params); + + // Building the key schedule table requires {3,4} words workspace. + // Encrypting and decrypting requires 4 words workspace. + m_kwords = keyLength/sizeof(word32); + m_wspace.New(4U); + + // Do the endian gyrations from the paper and align pointers + typedef GetBlock KeyBlock; + KeyBlock kblk(userKey); + + switch (m_kwords) + { + case 3: + m_rkeys.New((m_rounds = 26)); + kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]); + SPECK_ExpandKey_3W(m_rkeys, m_wspace); + break; + case 4: + m_rkeys.New((m_rounds = 27)); + kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]); + SPECK_ExpandKey_4W(m_rkeys, m_wspace); + break; + default: + CRYPTOPP_ASSERT(0); + } +} + +void SPECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do the endian gyrations from the paper and align pointers + typedef GetBlock InBlock; + InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]); + + switch (m_rounds) + { + case 26: + SPECK_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 27: + SPECK_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + default: + CRYPTOPP_ASSERT(0); + } + + // Do the endian gyrations from the paper and align pointers + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]); +} + +void SPECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do the endian gyrations from the paper and align pointers + typedef GetBlock InBlock; + InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]); + + switch (m_rounds) + { + case 26: + SPECK_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 27: + SPECK_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + default: + CRYPTOPP_ASSERT(0); + } + + // Do the endian gyrations from the paper and align pointers + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]); +} + +/////////////////////////////////////////////////////////// + +std::string SPECK128::Base::AlgorithmProvider() const +{ +#if (CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS) +# if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return "SSSE3"; +# endif +# if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return "NEON"; +# endif +# if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return "Altivec"; +# endif +#endif + return "C++"; +} + +unsigned int SPECK128::Base::OptimalDataAlignment() const +{ +#if (CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS) +# if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return 16; // load __m128i +# endif +# if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return 8; // load uint64x2_t +# endif +# if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return 16; // load uint64x2_p +# endif +#endif + return GetAlignmentOf(); +} + +void SPECK128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32); + CRYPTOPP_UNUSED(params); + + // Building the key schedule table requires {2,3,4} words workspace. + // Encrypting and decrypting requires 4 words workspace. + m_kwords = keyLength/sizeof(word64); + m_wspace.New(4U); + + // Do the endian gyrations from the paper and align pointers + typedef GetBlock KeyBlock; + KeyBlock kblk(userKey); + + switch (m_kwords) + { + case 2: + m_rkeys.New((m_rounds = 32)); + kblk(m_wspace[1])(m_wspace[0]); + SPECK_ExpandKey_2W(m_rkeys, m_wspace); + break; + case 3: + m_rkeys.New((m_rounds = 33)); + kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]); + SPECK_ExpandKey_3W(m_rkeys, m_wspace); + break; + case 4: + m_rkeys.New((m_rounds = 34)); + kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]); + SPECK_ExpandKey_4W(m_rkeys, m_wspace); + break; + default: + CRYPTOPP_ASSERT(0); + } + +#if CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS + + // Pre-splat the round keys for Altivec forward transformation +#if CRYPTOPP_ALTIVEC_AVAILABLE + if (IsForwardTransformation() && HasAltivec()) + { + AlignedSecBlock presplat(m_rkeys.size()*2); + for (size_t i=0, j=0; i InBlock; + InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]); + + switch (m_rounds) + { + case 32: + SPECK_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 33: + SPECK_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 34: + SPECK_Encrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + default: + CRYPTOPP_ASSERT(0); + } + + // Do the endian gyrations from the paper and align pointers + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]); +} + +void SPECK128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Do the endian gyrations from the paper and align pointers + typedef GetBlock InBlock; + InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]); + + switch (m_rounds) + { + case 32: + SPECK_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 33: + SPECK_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + case 34: + SPECK_Decrypt(m_wspace+2, m_wspace+0, m_rkeys); + break; + default: + CRYPTOPP_ASSERT(0); + } + + // Do the endian gyrations from the paper and align pointers + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]); +} + +#if (CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS) +size_t SPECK128::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, + byte *outBlocks, size_t length, word32 flags) const +{ +#if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return SPECK128_Enc_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return SPECK128_Enc_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return SPECK128_Enc_AdvancedProcessBlocks_ALTIVEC(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t SPECK128::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, + byte *outBlocks, size_t length, word32 flags) const +{ +#if (CRYPTOPP_SSSE3_AVAILABLE) + if (HasSSSE3()) + return SPECK128_Dec_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + if (HasNEON()) + return SPECK128_Dec_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif +#if (CRYPTOPP_ALTIVEC_AVAILABLE) + if (HasAltivec()) + return SPECK128_Dec_AdvancedProcessBlocks_ALTIVEC(m_rkeys, (size_t)m_rounds, + inBlocks, xorBlocks, outBlocks, length, flags); +#endif + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/speck.h b/external/ours/library/crypto/src/shared/original/speck.h new file mode 100755 index 000000000..dbbdf2f66 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/speck128_simd.cpp b/external/ours/library/crypto/src/shared/original/speck128_simd.cpp new file mode 100755 index 000000000..a17ce38d4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/speck128_simd.cpp @@ -0,0 +1,754 @@ +// speck128_simd.cpp - written and placed in the public domain by Jeffrey Walton +// +// This source file uses intrinsics and built-ins to gain access to +// SSSE3, ARM NEON and ARMv8a, and Altivec instructions. A separate +// source file is needed because additional CXXFLAGS are required to enable +// the appropriate instructions sets in some build configurations. + +#include "pch.h" +#include "config.h" + +#include "speck.h" +#include "misc.h" + +// Uncomment for benchmarking C++ against SSE or NEON. +// Do so in both speck.cpp and speck_simd.cpp. +// #undef CRYPTOPP_SSSE3_AVAILABLE +// #undef CRYPTOPP_ARM_NEON_AVAILABLE + +#if (CRYPTOPP_SSSE3_AVAILABLE) +# include "adv_simd.h" +# include +# include +#endif + +#if defined(__XOP__) +# include +# if defined(__GNUC__) +# include +# endif +#endif + +#if (CRYPTOPP_ARM_NEON_HEADER) +# include "adv_simd.h" +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +#if defined(_M_ARM64) +# include "adv_simd.h" +#endif + +#if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +# include "adv_simd.h" +# include "ppc_simd.h" +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char SPECK128_SIMD_FNAME[] = __FILE__; + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::byte; +using CryptoPP::word32; +using CryptoPP::word64; + +// *************************** ARM NEON ************************** // + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) + +// Missing from Microsoft's ARM A-32 implementation +#if defined(_MSC_VER) && !defined(_M_ARM64) +inline uint64x2_t vld1q_dup_u64(const uint64_t* ptr) +{ + return vmovq_n_u64(*ptr); +} +#endif + +template +inline T UnpackHigh64(const T& a, const T& b) +{ + const uint64x1_t x(vget_high_u64((uint64x2_t)a)); + const uint64x1_t y(vget_high_u64((uint64x2_t)b)); + return (T)vcombine_u64(x, y); +} + +template +inline T UnpackLow64(const T& a, const T& b) +{ + const uint64x1_t x(vget_low_u64((uint64x2_t)a)); + const uint64x1_t y(vget_low_u64((uint64x2_t)b)); + return (T)vcombine_u64(x, y); +} + +template +inline uint64x2_t RotateLeft64(const uint64x2_t& val) +{ + const uint64x2_t a(vshlq_n_u64(val, R)); + const uint64x2_t b(vshrq_n_u64(val, 64 - R)); + return vorrq_u64(a, b); +} + +template +inline uint64x2_t RotateRight64(const uint64x2_t& val) +{ + const uint64x2_t a(vshlq_n_u64(val, 64 - R)); + const uint64x2_t b(vshrq_n_u64(val, R)); + return vorrq_u64(a, b); +} + +#if defined(__aarch32__) || defined(__aarch64__) +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +inline uint64x2_t RotateLeft64<8>(const uint64x2_t& val) +{ + const uint8_t maskb[16] = { 7,0,1,2, 3,4,5,6, 15,8,9,10, 11,12,13,14 }; + const uint8x16_t mask = vld1q_u8(maskb); + + return vreinterpretq_u64_u8( + vqtbl1q_u8(vreinterpretq_u8_u64(val), mask)); +} + +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +inline uint64x2_t RotateRight64<8>(const uint64x2_t& val) +{ + const uint8_t maskb[16] = { 1,2,3,4, 5,6,7,0, 9,10,11,12, 13,14,15,8 }; + const uint8x16_t mask = vld1q_u8(maskb); + + return vreinterpretq_u64_u8( + vqtbl1q_u8(vreinterpretq_u8_u64(val), mask)); +} +#endif + +inline void SPECK128_Enc_Block(uint64x2_t &block0, uint64x2_t &block1, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + uint64x2_t x1 = UnpackHigh64(block0, block1); + uint64x2_t y1 = UnpackLow64(block0, block1); + + for (size_t i=0; i < static_cast(rounds); ++i) + { + const uint64x2_t rk = vld1q_dup_u64(subkeys+i); + + x1 = RotateRight64<8>(x1); + x1 = vaddq_u64(x1, y1); + x1 = veorq_u64(x1, rk); + y1 = RotateLeft64<3>(y1); + y1 = veorq_u64(y1, x1); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = UnpackLow64(y1, x1); + block1 = UnpackHigh64(y1, x1); +} + +inline void SPECK128_Enc_6_Blocks(uint64x2_t &block0, uint64x2_t &block1, + uint64x2_t &block2, uint64x2_t &block3, uint64x2_t &block4, uint64x2_t &block5, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + uint64x2_t x1 = UnpackHigh64(block0, block1); + uint64x2_t y1 = UnpackLow64(block0, block1); + uint64x2_t x2 = UnpackHigh64(block2, block3); + uint64x2_t y2 = UnpackLow64(block2, block3); + uint64x2_t x3 = UnpackHigh64(block4, block5); + uint64x2_t y3 = UnpackLow64(block4, block5); + + for (size_t i=0; i < static_cast(rounds); ++i) + { + const uint64x2_t rk = vld1q_dup_u64(subkeys+i); + + x1 = RotateRight64<8>(x1); + x2 = RotateRight64<8>(x2); + x3 = RotateRight64<8>(x3); + x1 = vaddq_u64(x1, y1); + x2 = vaddq_u64(x2, y2); + x3 = vaddq_u64(x3, y3); + x1 = veorq_u64(x1, rk); + x2 = veorq_u64(x2, rk); + x3 = veorq_u64(x3, rk); + y1 = RotateLeft64<3>(y1); + y2 = RotateLeft64<3>(y2); + y3 = RotateLeft64<3>(y3); + y1 = veorq_u64(y1, x1); + y2 = veorq_u64(y2, x2); + y3 = veorq_u64(y3, x3); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = UnpackLow64(y1, x1); + block1 = UnpackHigh64(y1, x1); + block2 = UnpackLow64(y2, x2); + block3 = UnpackHigh64(y2, x2); + block4 = UnpackLow64(y3, x3); + block5 = UnpackHigh64(y3, x3); +} + +inline void SPECK128_Dec_Block(uint64x2_t &block0, uint64x2_t &block1, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + uint64x2_t x1 = UnpackHigh64(block0, block1); + uint64x2_t y1 = UnpackLow64(block0, block1); + + for (int i = static_cast(rounds-1); i >= 0; --i) + { + const uint64x2_t rk = vld1q_dup_u64(subkeys+i); + + y1 = veorq_u64(y1, x1); + y1 = RotateRight64<3>(y1); + x1 = veorq_u64(x1, rk); + x1 = vsubq_u64(x1, y1); + x1 = RotateLeft64<8>(x1); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = UnpackLow64(y1, x1); + block1 = UnpackHigh64(y1, x1); +} + +inline void SPECK128_Dec_6_Blocks(uint64x2_t &block0, uint64x2_t &block1, + uint64x2_t &block2, uint64x2_t &block3, uint64x2_t &block4, uint64x2_t &block5, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + uint64x2_t x1 = UnpackHigh64(block0, block1); + uint64x2_t y1 = UnpackLow64(block0, block1); + uint64x2_t x2 = UnpackHigh64(block2, block3); + uint64x2_t y2 = UnpackLow64(block2, block3); + uint64x2_t x3 = UnpackHigh64(block4, block5); + uint64x2_t y3 = UnpackLow64(block4, block5); + + for (int i = static_cast(rounds-1); i >= 0; --i) + { + const uint64x2_t rk = vld1q_dup_u64(subkeys+i); + + y1 = veorq_u64(y1, x1); + y2 = veorq_u64(y2, x2); + y3 = veorq_u64(y3, x3); + y1 = RotateRight64<3>(y1); + y2 = RotateRight64<3>(y2); + y3 = RotateRight64<3>(y3); + x1 = veorq_u64(x1, rk); + x2 = veorq_u64(x2, rk); + x3 = veorq_u64(x3, rk); + x1 = vsubq_u64(x1, y1); + x2 = vsubq_u64(x2, y2); + x3 = vsubq_u64(x3, y3); + x1 = RotateLeft64<8>(x1); + x2 = RotateLeft64<8>(x2); + x3 = RotateLeft64<8>(x3); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = UnpackLow64(y1, x1); + block1 = UnpackHigh64(y1, x1); + block2 = UnpackLow64(y2, x2); + block3 = UnpackHigh64(y2, x2); + block4 = UnpackLow64(y3, x3); + block5 = UnpackHigh64(y3, x3); +} + +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +// ***************************** IA-32 ***************************** // + +#if defined(CRYPTOPP_SSSE3_AVAILABLE) + +// GCC double casts, https://www.spinics.net/lists/gcchelp/msg47735.html +#ifndef DOUBLE_CAST +# define DOUBLE_CAST(x) ((double *)(void *)(x)) +#endif +#ifndef CONST_DOUBLE_CAST +# define CONST_DOUBLE_CAST(x) ((const double *)(const void *)(x)) +#endif + +template +inline __m128i RotateLeft64(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi64(val, R); +#else + return _mm_or_si128( + _mm_slli_epi64(val, R), _mm_srli_epi64(val, 64-R)); +#endif +} + +template +inline __m128i RotateRight64(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi64(val, 64-R); +#else + return _mm_or_si128( + _mm_slli_epi64(val, 64-R), _mm_srli_epi64(val, R)); +#endif +} + +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +__m128i RotateLeft64<8>(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi64(val, 8); +#else + const __m128i mask = _mm_set_epi8(14,13,12,11, 10,9,8,15, 6,5,4,3, 2,1,0,7); + return _mm_shuffle_epi8(val, mask); +#endif +} + +// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks. +template <> +__m128i RotateRight64<8>(const __m128i& val) +{ +#if defined(__XOP__) + return _mm_roti_epi64(val, 64-8); +#else + const __m128i mask = _mm_set_epi8(8,15,14,13, 12,11,10,9, 0,7,6,5, 4,3,2,1); + return _mm_shuffle_epi8(val, mask); +#endif +} + +inline void SPECK128_Enc_Block(__m128i &block0, __m128i &block1, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + __m128i x1 = _mm_unpackhi_epi64(block0, block1); + __m128i y1 = _mm_unpacklo_epi64(block0, block1); + + for (size_t i=0; i < static_cast(rounds); ++i) + { + // Round keys are pre-splated in forward direction + const __m128i rk = _mm_load_si128(CONST_M128_CAST(subkeys+i*2)); + + x1 = RotateRight64<8>(x1); + x1 = _mm_add_epi64(x1, y1); + x1 = _mm_xor_si128(x1, rk); + y1 = RotateLeft64<3>(y1); + y1 = _mm_xor_si128(y1, x1); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = _mm_unpacklo_epi64(y1, x1); + block1 = _mm_unpackhi_epi64(y1, x1); +} + +inline void SPECK128_Enc_6_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, __m128i &block4, __m128i &block5, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + __m128i x1 = _mm_unpackhi_epi64(block0, block1); + __m128i y1 = _mm_unpacklo_epi64(block0, block1); + __m128i x2 = _mm_unpackhi_epi64(block2, block3); + __m128i y2 = _mm_unpacklo_epi64(block2, block3); + __m128i x3 = _mm_unpackhi_epi64(block4, block5); + __m128i y3 = _mm_unpacklo_epi64(block4, block5); + + for (size_t i=0; i < static_cast(rounds); ++i) + { + // Round keys are pre-splated in forward direction + const __m128i rk = _mm_load_si128(CONST_M128_CAST(subkeys+i*2)); + + x1 = RotateRight64<8>(x1); + x2 = RotateRight64<8>(x2); + x3 = RotateRight64<8>(x3); + x1 = _mm_add_epi64(x1, y1); + x2 = _mm_add_epi64(x2, y2); + x3 = _mm_add_epi64(x3, y3); + x1 = _mm_xor_si128(x1, rk); + x2 = _mm_xor_si128(x2, rk); + x3 = _mm_xor_si128(x3, rk); + y1 = RotateLeft64<3>(y1); + y2 = RotateLeft64<3>(y2); + y3 = RotateLeft64<3>(y3); + y1 = _mm_xor_si128(y1, x1); + y2 = _mm_xor_si128(y2, x2); + y3 = _mm_xor_si128(y3, x3); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = _mm_unpacklo_epi64(y1, x1); + block1 = _mm_unpackhi_epi64(y1, x1); + block2 = _mm_unpacklo_epi64(y2, x2); + block3 = _mm_unpackhi_epi64(y2, x2); + block4 = _mm_unpacklo_epi64(y3, x3); + block5 = _mm_unpackhi_epi64(y3, x3); +} + +inline void SPECK128_Dec_Block(__m128i &block0, __m128i &block1, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + __m128i x1 = _mm_unpackhi_epi64(block0, block1); + __m128i y1 = _mm_unpacklo_epi64(block0, block1); + + for (int i = static_cast(rounds-1); i >= 0; --i) + { + const __m128i rk = _mm_castpd_si128( + _mm_loaddup_pd(CONST_DOUBLE_CAST(subkeys+i))); + + y1 = _mm_xor_si128(y1, x1); + y1 = RotateRight64<3>(y1); + x1 = _mm_xor_si128(x1, rk); + x1 = _mm_sub_epi64(x1, y1); + x1 = RotateLeft64<8>(x1); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = _mm_unpacklo_epi64(y1, x1); + block1 = _mm_unpackhi_epi64(y1, x1); +} + +inline void SPECK128_Dec_6_Blocks(__m128i &block0, __m128i &block1, + __m128i &block2, __m128i &block3, __m128i &block4, __m128i &block5, + const word64 *subkeys, unsigned int rounds) +{ + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + __m128i x1 = _mm_unpackhi_epi64(block0, block1); + __m128i y1 = _mm_unpacklo_epi64(block0, block1); + __m128i x2 = _mm_unpackhi_epi64(block2, block3); + __m128i y2 = _mm_unpacklo_epi64(block2, block3); + __m128i x3 = _mm_unpackhi_epi64(block4, block5); + __m128i y3 = _mm_unpacklo_epi64(block4, block5); + + for (int i = static_cast(rounds-1); i >= 0; --i) + { + const __m128i rk = _mm_castpd_si128( + _mm_loaddup_pd(CONST_DOUBLE_CAST(subkeys+i))); + + y1 = _mm_xor_si128(y1, x1); + y2 = _mm_xor_si128(y2, x2); + y3 = _mm_xor_si128(y3, x3); + y1 = RotateRight64<3>(y1); + y2 = RotateRight64<3>(y2); + y3 = RotateRight64<3>(y3); + x1 = _mm_xor_si128(x1, rk); + x2 = _mm_xor_si128(x2, rk); + x3 = _mm_xor_si128(x3, rk); + x1 = _mm_sub_epi64(x1, y1); + x2 = _mm_sub_epi64(x2, y2); + x3 = _mm_sub_epi64(x3, y3); + x1 = RotateLeft64<8>(x1); + x2 = RotateLeft64<8>(x2); + x3 = RotateLeft64<8>(x3); + } + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = _mm_unpacklo_epi64(y1, x1); + block1 = _mm_unpackhi_epi64(y1, x1); + block2 = _mm_unpacklo_epi64(y2, x2); + block3 = _mm_unpackhi_epi64(y2, x2); + block4 = _mm_unpacklo_epi64(y3, x3); + block5 = _mm_unpackhi_epi64(y3, x3); +} + +#endif // CRYPTOPP_SSSE3_AVAILABLE + +// ***************************** Altivec ***************************** // + +#if defined(CRYPTOPP_ALTIVEC_AVAILABLE) + +// Altivec uses native 64-bit types on 64-bit environments, or 32-bit types +// in 32-bit environments. Speck128 will use the appropriate type for the +// environment. Functions like VecAdd64 have two overloads, one for each +// environment. The 32-bit overload treats uint32x4_p like a 64-bit type, +// and does things like perform a add with carry or subtract with borrow. + +// Speck128 on Power8 performed as expected because of 64-bit environment. +// Performance sucked on old PowerPC machines because of 32-bit environments. +// At Crypto++ 8.3 we added an implementation that operated on 32-bit words. +// Native 64-bit Speck128 performance dropped from about 4.1 to 6.3 cpb, but +// 32-bit Speck128 improved from 66.5 cpb to 10.4 cpb. Overall it was a +// good win even though we lost some performance in 64-bit environments. + +using CryptoPP::uint8x16_p; +using CryptoPP::uint32x4_p; +#if defined(_ARCH_PWR8) +using CryptoPP::uint64x2_p; +#endif + +using CryptoPP::VecAdd64; +using CryptoPP::VecSub64; +using CryptoPP::VecAnd64; +using CryptoPP::VecOr64; +using CryptoPP::VecXor64; +using CryptoPP::VecSplatWord64; +using CryptoPP::VecRotateLeft64; +using CryptoPP::VecRotateRight64; +using CryptoPP::VecLoad; +using CryptoPP::VecLoadAligned; +using CryptoPP::VecPermute; + +#if defined(_ARCH_PWR8) +#define speck128_t uint64x2_p +#else +#define speck128_t uint32x4_p +#endif + +void SPECK128_Enc_Block(uint32x4_p &block, const word64 *subkeys, unsigned int rounds) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m1 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m2 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m1 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m2 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + speck128_t x1 = (speck128_t)VecPermute(block, block, m1); + speck128_t y1 = (speck128_t)VecPermute(block, block, m2); + + for (size_t i=0; i < static_cast(rounds); ++i) + { + // Round keys are pre-splated in forward direction + const word32* ptr = reinterpret_cast(subkeys+i*2); + const speck128_t rk = (speck128_t)VecLoadAligned(ptr); + + x1 = (speck128_t)VecRotateRight64<8>(x1); + x1 = (speck128_t)VecAdd64(x1, y1); + x1 = (speck128_t)VecXor64(x1, rk); + + y1 = (speck128_t)VecRotateLeft64<3>(y1); + y1 = (speck128_t)VecXor64(y1, x1); + } + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m3 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + //const uint8x16_p m4 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m3 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + //const uint8x16_p m4 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block = (uint32x4_p)VecPermute(x1, y1, m3); +} + +void SPECK128_Dec_Block(uint32x4_p &block, const word64 *subkeys, unsigned int rounds) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m1 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m2 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m1 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m2 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + speck128_t x1 = (speck128_t)VecPermute(block, block, m1); + speck128_t y1 = (speck128_t)VecPermute(block, block, m2); + + for (int i = static_cast(rounds-1); i >= 0; --i) + { + const speck128_t rk = (speck128_t)VecSplatWord64(subkeys[i]); + + y1 = (speck128_t)VecXor64(y1, x1); + y1 = (speck128_t)VecRotateRight64<3>(y1); + x1 = (speck128_t)VecXor64(x1, rk); + x1 = (speck128_t)VecSub64(x1, y1); + x1 = (speck128_t)VecRotateLeft64<8>(x1); + } + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m3 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + //const uint8x16_p m4 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m3 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + //const uint8x16_p m4 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block = (uint32x4_p)VecPermute(x1, y1, m3); +} + +void SPECK128_Enc_6_Blocks(uint32x4_p &block0, uint32x4_p &block1, + uint32x4_p &block2, uint32x4_p &block3, uint32x4_p &block4, + uint32x4_p &block5, const word64 *subkeys, unsigned int rounds) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m1 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m2 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m1 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m2 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + speck128_t x1 = (speck128_t)VecPermute(block0, block1, m1); + speck128_t y1 = (speck128_t)VecPermute(block0, block1, m2); + speck128_t x2 = (speck128_t)VecPermute(block2, block3, m1); + speck128_t y2 = (speck128_t)VecPermute(block2, block3, m2); + speck128_t x3 = (speck128_t)VecPermute(block4, block5, m1); + speck128_t y3 = (speck128_t)VecPermute(block4, block5, m2); + + for (size_t i=0; i < static_cast(rounds); ++i) + { + // Round keys are pre-splated in forward direction + const word32* ptr = reinterpret_cast(subkeys+i*2); + const speck128_t rk = (speck128_t)VecLoadAligned(ptr); + + x1 = (speck128_t)VecRotateRight64<8>(x1); + x2 = (speck128_t)VecRotateRight64<8>(x2); + x3 = (speck128_t)VecRotateRight64<8>(x3); + x1 = (speck128_t)VecAdd64(x1, y1); + x2 = (speck128_t)VecAdd64(x2, y2); + x3 = (speck128_t)VecAdd64(x3, y3); + x1 = (speck128_t)VecXor64(x1, rk); + x2 = (speck128_t)VecXor64(x2, rk); + x3 = (speck128_t)VecXor64(x3, rk); + + y1 = (speck128_t)VecRotateLeft64<3>(y1); + y2 = (speck128_t)VecRotateLeft64<3>(y2); + y3 = (speck128_t)VecRotateLeft64<3>(y3); + y1 = (speck128_t)VecXor64(y1, x1); + y2 = (speck128_t)VecXor64(y2, x2); + y3 = (speck128_t)VecXor64(y3, x3); + } + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m3 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m4 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m3 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m4 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = (uint32x4_p)VecPermute(x1, y1, m3); + block1 = (uint32x4_p)VecPermute(x1, y1, m4); + block2 = (uint32x4_p)VecPermute(x2, y2, m3); + block3 = (uint32x4_p)VecPermute(x2, y2, m4); + block4 = (uint32x4_p)VecPermute(x3, y3, m3); + block5 = (uint32x4_p)VecPermute(x3, y3, m4); +} + +void SPECK128_Dec_6_Blocks(uint32x4_p &block0, uint32x4_p &block1, + uint32x4_p &block2, uint32x4_p &block3, uint32x4_p &block4, + uint32x4_p &block5, const word64 *subkeys, unsigned int rounds) +{ +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m1 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m2 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m1 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m2 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 A2][B1 B2] ... => [A1 B1][A2 B2] ... + speck128_t x1 = (speck128_t)VecPermute(block0, block1, m1); + speck128_t y1 = (speck128_t)VecPermute(block0, block1, m2); + speck128_t x2 = (speck128_t)VecPermute(block2, block3, m1); + speck128_t y2 = (speck128_t)VecPermute(block2, block3, m2); + speck128_t x3 = (speck128_t)VecPermute(block4, block5, m1); + speck128_t y3 = (speck128_t)VecPermute(block4, block5, m2); + + for (int i = static_cast(rounds-1); i >= 0; --i) + { + const speck128_t rk = (speck128_t)VecSplatWord64(subkeys[i]); + + y1 = (speck128_t)VecXor64(y1, x1); + y2 = (speck128_t)VecXor64(y2, x2); + y3 = (speck128_t)VecXor64(y3, x3); + y1 = (speck128_t)VecRotateRight64<3>(y1); + y2 = (speck128_t)VecRotateRight64<3>(y2); + y3 = (speck128_t)VecRotateRight64<3>(y3); + + x1 = (speck128_t)VecXor64(x1, rk); + x2 = (speck128_t)VecXor64(x2, rk); + x3 = (speck128_t)VecXor64(x3, rk); + x1 = (speck128_t)VecSub64(x1, y1); + x2 = (speck128_t)VecSub64(x2, y2); + x3 = (speck128_t)VecSub64(x3, y3); + x1 = (speck128_t)VecRotateLeft64<8>(x1); + x2 = (speck128_t)VecRotateLeft64<8>(x2); + x3 = (speck128_t)VecRotateLeft64<8>(x3); + } + +#if (CRYPTOPP_BIG_ENDIAN) + const uint8x16_p m3 = {31,30,29,28,27,26,25,24, 15,14,13,12,11,10,9,8}; + const uint8x16_p m4 = {23,22,21,20,19,18,17,16, 7,6,5,4,3,2,1,0}; +#else + const uint8x16_p m3 = {7,6,5,4,3,2,1,0, 23,22,21,20,19,18,17,16}; + const uint8x16_p m4 = {15,14,13,12,11,10,9,8, 31,30,29,28,27,26,25,24}; +#endif + + // [A1 B1][A2 B2] ... => [A1 A2][B1 B2] ... + block0 = (uint32x4_p)VecPermute(x1, y1, m3); + block1 = (uint32x4_p)VecPermute(x1, y1, m4); + block2 = (uint32x4_p)VecPermute(x2, y2, m3); + block3 = (uint32x4_p)VecPermute(x2, y2, m4); + block4 = (uint32x4_p)VecPermute(x3, y3, m3); + block5 = (uint32x4_p)VecPermute(x3, y3, m4); +} + +#endif // CRYPTOPP_ALTIVEC_AVAILABLE + +ANONYMOUS_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////// + +NAMESPACE_BEGIN(CryptoPP) + +// *************************** ARM NEON **************************** // + +#if (CRYPTOPP_ARM_NEON_AVAILABLE) +size_t SPECK128_Enc_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x2_NEON(SPECK128_Enc_Block, SPECK128_Enc_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t SPECK128_Dec_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x2_NEON(SPECK128_Dec_Block, SPECK128_Dec_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_ARM_NEON_AVAILABLE + +// ***************************** IA-32 ***************************** // + +#if (CRYPTOPP_SSSE3_AVAILABLE) +size_t SPECK128_Enc_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x2_SSE(SPECK128_Enc_Block, SPECK128_Enc_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t SPECK128_Dec_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x2_SSE(SPECK128_Dec_Block, SPECK128_Dec_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_SSSE3_AVAILABLE + +// ***************************** Altivec ***************************** // + +#if (CRYPTOPP_ALTIVEC_AVAILABLE) +size_t SPECK128_Enc_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x1_ALTIVEC(SPECK128_Enc_Block, SPECK128_Enc_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} + +size_t SPECK128_Dec_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds, + const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) +{ + return AdvancedProcessBlocks128_6x1_ALTIVEC(SPECK128_Dec_Block, SPECK128_Dec_6_Blocks, + subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags); +} +#endif // CRYPTOPP_ALTIVEC_AVAILABLE + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/square.cpp b/external/ours/library/crypto/src/shared/original/square.cpp new file mode 100755 index 000000000..4065a7f33 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/square.cpp @@ -0,0 +1,187 @@ +// square.cpp - originally written and placed in the public domain by Wei Dai +// Based on Paulo S.L.M. Barreto's public domain implementation + +#include "pch.h" +#include "config.h" + +#include "square.h" +#include "misc.h" +#include "gf256.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4244) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wmissing-braces" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// apply theta to a roundkey +static void SquareTransform (word32 in[4], word32 out[4]) +{ + static const byte G[4][4] = + { + 0x02U, 0x01U, 0x01U, 0x03U, + 0x03U, 0x02U, 0x01U, 0x01U, + 0x01U, 0x03U, 0x02U, 0x01U, + 0x01U, 0x01U, 0x03U, 0x02U + }; + + GF256 gf256(0xf5); + + for (int i = 0; i < 4; i++) + { + word32 temp = 0; + for (unsigned int j = 0; j < 4; j++) + for (unsigned int k = 0; k < 4; k++) + temp ^= (word32)gf256.Multiply(GETBYTE(in[i], 3-k), G[k][j]) << ((3-j)*8); + out[i] = temp; + } +} + +#define roundkeys(i, j) m_roundkeys[(i)*4+(j)] +#define roundkeys4(i) (m_roundkeys+(i)*4) + +void Square::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + static const word32 offset[ROUNDS] = { + 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, + 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, + }; + + GetUserKey(BIG_ENDIAN_ORDER, m_roundkeys.data(), KEYLENGTH/4, userKey, KEYLENGTH); + + /* apply the key evolution function */ + for (int i = 1; i < ROUNDS+1; i++) + { + roundkeys(i, 0) = roundkeys(i-1, 0) ^ rotlConstant<8>(roundkeys(i-1, 3)) ^ offset[i-1]; + roundkeys(i, 1) = roundkeys(i-1, 1) ^ roundkeys(i, 0); + roundkeys(i, 2) = roundkeys(i-1, 2) ^ roundkeys(i, 1); + roundkeys(i, 3) = roundkeys(i-1, 3) ^ roundkeys(i, 2); + } + + /* produce the round keys */ + if (IsForwardTransformation()) + { + for (int i = 0; i < ROUNDS; i++) + SquareTransform (roundkeys4(i), roundkeys4(i)); + } + else + { + for (int i = 0; i < ROUNDS/2; i++) + for (int j = 0; j < 4; j++) + std::swap(roundkeys(i, j), roundkeys(ROUNDS-i, j)); + SquareTransform (roundkeys4(ROUNDS), roundkeys4(ROUNDS)); + } +} + +#define MSB(x) (((x) >> 24) & 0xffU) /* most significant byte */ +#define SSB(x) (((x) >> 16) & 0xffU) /* second in significance */ +#define TSB(x) (((x) >> 8) & 0xffU) /* third in significance */ +#define LSB(x) (((x) ) & 0xffU) /* least significant byte */ + +#define squareRound(text, temp, T0, T1, T2, T3, roundkey) \ +{ \ + temp[0] = T0[MSB (text[0])] \ + ^ T1[MSB (text[1])] \ + ^ T2[MSB (text[2])] \ + ^ T3[MSB (text[3])] \ + ^ roundkey[0]; \ + temp[1] = T0[SSB (text[0])] \ + ^ T1[SSB (text[1])] \ + ^ T2[SSB (text[2])] \ + ^ T3[SSB (text[3])] \ + ^ roundkey[1]; \ + temp[2] = T0[TSB (text[0])] \ + ^ T1[TSB (text[1])] \ + ^ T2[TSB (text[2])] \ + ^ T3[TSB (text[3])] \ + ^ roundkey[2]; \ + temp[3] = T0[LSB (text[0])] \ + ^ T1[LSB (text[1])] \ + ^ T2[LSB (text[2])] \ + ^ T3[LSB (text[3])] \ + ^ roundkey[3]; \ +} /* squareRound */ + +#define squareFinal(text, temp, S, roundkey) \ +{ \ + text[0] = ((word32) (S[MSB (temp[0])]) << 24) \ + ^ ((word32) (S[MSB (temp[1])]) << 16) \ + ^ ((word32) (S[MSB (temp[2])]) << 8) \ + ^ (word32) (S[MSB (temp[3])]) \ + ^ roundkey[0]; \ + text[1] = ((word32) (S[SSB (temp[0])]) << 24) \ + ^ ((word32) (S[SSB (temp[1])]) << 16) \ + ^ ((word32) (S[SSB (temp[2])]) << 8) \ + ^ (word32) (S[SSB (temp[3])]) \ + ^ roundkey[1]; \ + text[2] = ((word32) (S[TSB (temp[0])]) << 24) \ + ^ ((word32) (S[TSB (temp[1])]) << 16) \ + ^ ((word32) (S[TSB (temp[2])]) << 8) \ + ^ (word32) (S[TSB (temp[3])]) \ + ^ roundkey[2]; \ + text[3] = ((word32) (S[LSB (temp[0])]) << 24) \ + ^ ((word32) (S[LSB (temp[1])]) << 16) \ + ^ ((word32) (S[LSB (temp[2])]) << 8) \ + ^ (word32) (S[LSB (temp[3])]) \ + ^ roundkey[3]; \ +} /* squareFinal */ + +typedef BlockGetAndPut Block; + +void Square::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 text[4], temp[4]; + Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]); + + /* initial key addition */ + text[0] ^= roundkeys(0, 0); + text[1] ^= roundkeys(0, 1); + text[2] ^= roundkeys(0, 2); + text[3] ^= roundkeys(0, 3); + + /* ROUNDS - 1 full rounds */ + for (int i=1; i+1, 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/external/ours/library/crypto/src/shared/original/squaretb.cpp b/external/ours/library/crypto/src/shared/original/squaretb.cpp new file mode 100755 index 000000000..e806f610d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/squaretb.cpp @@ -0,0 +1,582 @@ +#include "pch.h" +#include "square.h" + +NAMESPACE_BEGIN(CryptoPP) + +const byte Square::Enc::Se[256] = { +177, 206, 195, 149, 90, 173, 231, 2, 77, 68, 251, 145, 12, 135, 161, 80, +203, 103, 84, 221, 70, 143, 225, 78, 240, 253, 252, 235, 249, 196, 26, 110, + 94, 245, 204, 141, 28, 86, 67, 254, 7, 97, 248, 117, 89, 255, 3, 34, +138, 209, 19, 238, 136, 0, 14, 52, 21, 128, 148, 227, 237, 181, 83, 35, + 75, 71, 23, 167, 144, 53, 171, 216, 184, 223, 79, 87, 154, 146, 219, 27, + 60, 200, 153, 4, 142, 224, 215, 125, 133, 187, 64, 44, 58, 69, 241, 66, +101, 32, 65, 24, 114, 37, 147, 112, 54, 5, 242, 11, 163, 121, 236, 8, + 39, 49, 50, 182, 124, 176, 10, 115, 91, 123, 183, 129, 210, 13, 106, 38, +158, 88, 156, 131, 116, 179, 172, 48, 122, 105, 119, 15, 174, 33, 222, 208, + 46, 151, 16, 164, 152, 168, 212, 104, 45, 98, 41, 109, 22, 73, 118, 199, +232, 193, 150, 55, 229, 202, 244, 233, 99, 18, 194, 166, 20, 188, 211, 40, +175, 47, 230, 36, 82, 198, 160, 9, 189, 140, 207, 93, 17, 95, 1, 197, +159, 61, 162, 155, 201, 59, 190, 81, 25, 31, 63, 92, 178, 239, 74, 205, +191, 186, 111, 100, 217, 243, 62, 180, 170, 220, 213, 6, 192, 126, 246, 102, +108, 132, 113, 56, 185, 29, 127, 157, 72, 139, 42, 218, 165, 51, 130, 57, +214, 120, 134, 250, 228, 43, 169, 30, 137, 96, 107, 234, 85, 76, 247, 226, +}; + +const byte Square::Dec::Sd[256] = { + 53, 190, 7, 46, 83, 105, 219, 40, 111, 183, 118, 107, 12, 125, 54, 139, +146, 188, 169, 50, 172, 56, 156, 66, 99, 200, 30, 79, 36, 229, 247, 201, + 97, 141, 47, 63, 179, 101, 127, 112, 175, 154, 234, 245, 91, 152, 144, 177, +135, 113, 114, 237, 55, 69, 104, 163, 227, 239, 92, 197, 80, 193, 214, 202, + 90, 98, 95, 38, 9, 93, 20, 65, 232, 157, 206, 64, 253, 8, 23, 74, + 15, 199, 180, 62, 18, 252, 37, 75, 129, 44, 4, 120, 203, 187, 32, 189, +249, 41, 153, 168, 211, 96, 223, 17, 151, 137, 126, 250, 224, 155, 31, 210, +103, 226, 100, 119, 132, 43, 158, 138, 241, 109, 136, 121, 116, 87, 221, 230, + 57, 123, 238, 131, 225, 88, 242, 13, 52, 248, 48, 233, 185, 35, 84, 21, + 68, 11, 77, 102, 58, 3, 162, 145, 148, 82, 76, 195, 130, 231, 128, 192, +182, 14, 194, 108, 147, 236, 171, 67, 149, 246, 216, 70, 134, 5, 140, 176, +117, 0, 204, 133, 215, 61, 115, 122, 72, 228, 209, 89, 173, 184, 198, 208, +220, 161, 170, 2, 29, 191, 181, 159, 81, 196, 165, 16, 34, 207, 1, 186, +143, 49, 124, 174, 150, 218, 240, 86, 71, 212, 235, 78, 217, 19, 142, 73, + 85, 22, 255, 59, 244, 164, 178, 6, 160, 167, 251, 27, 110, 60, 51, 205, + 24, 94, 106, 213, 166, 33, 222, 254, 42, 28, 243, 10, 26, 25, 39, 45, +}; + +const word32 Square::Enc::Te[4][256] = { +{ +0x97b1b126UL, 0x69cecea7UL, 0x73c3c3b0UL, 0xdf95954aUL, +0xb45a5aeeUL, 0xafadad02UL, 0x3be7e7dcUL, 0x04020206UL, +0x9a4d4dd7UL, 0x884444ccUL, 0x03fbfbf8UL, 0xd7919146UL, +0x180c0c14UL, 0xfb87877cUL, 0xb7a1a116UL, 0xa05050f0UL, +0x63cbcba8UL, 0xce6767a9UL, 0xa85454fcUL, 0x4fdddd92UL, +0x8c4646caUL, 0xeb8f8f64UL, 0x37e1e1d6UL, 0x9c4e4ed2UL, +0x15f0f0e5UL, 0x0ffdfdf2UL, 0x0dfcfcf1UL, 0x23ebebc8UL, +0x07f9f9feUL, 0x7dc4c4b9UL, 0x341a1a2eUL, 0xdc6e6eb2UL, +0xbc5e5ee2UL, 0x1ff5f5eaUL, 0x6dcccca1UL, 0xef8d8d62UL, +0x381c1c24UL, 0xac5656faUL, 0x864343c5UL, 0x09fefef7UL, +0x0e070709UL, 0xc26161a3UL, 0x05f8f8fdUL, 0xea75759fUL, +0xb25959ebUL, 0x0bfffff4UL, 0x06030305UL, 0x44222266UL, +0xe18a8a6bUL, 0x57d1d186UL, 0x26131335UL, 0x29eeeec7UL, +0xe588886dUL, 0x00000000UL, 0x1c0e0e12UL, 0x6834345cUL, +0x2a15153fUL, 0xf5808075UL, 0xdd949449UL, 0x33e3e3d0UL, +0x2fededc2UL, 0x9fb5b52aUL, 0xa65353f5UL, 0x46232365UL, +0x964b4bddUL, 0x8e4747c9UL, 0x2e171739UL, 0xbba7a71cUL, +0xd5909045UL, 0x6a35355fUL, 0xa3abab08UL, 0x45d8d89dUL, +0x85b8b83dUL, 0x4bdfdf94UL, 0x9e4f4fd1UL, 0xae5757f9UL, +0xc19a9a5bUL, 0xd1929243UL, 0x43dbdb98UL, 0x361b1b2dUL, +0x783c3c44UL, 0x65c8c8adUL, 0xc799995eUL, 0x0804040cUL, +0xe98e8e67UL, 0x35e0e0d5UL, 0x5bd7d78cUL, 0xfa7d7d87UL, +0xff85857aUL, 0x83bbbb38UL, 0x804040c0UL, 0x582c2c74UL, +0x743a3a4eUL, 0x8a4545cfUL, 0x17f1f1e6UL, 0x844242c6UL, +0xca6565afUL, 0x40202060UL, 0x824141c3UL, 0x30181828UL, +0xe4727296UL, 0x4a25256fUL, 0xd3939340UL, 0xe0707090UL, +0x6c36365aUL, 0x0a05050fUL, 0x11f2f2e3UL, 0x160b0b1dUL, +0xb3a3a310UL, 0xf279798bUL, 0x2dececc1UL, 0x10080818UL, +0x4e272769UL, 0x62313153UL, 0x64323256UL, 0x99b6b62fUL, +0xf87c7c84UL, 0x95b0b025UL, 0x140a0a1eUL, 0xe6737395UL, +0xb65b5bedUL, 0xf67b7b8dUL, 0x9bb7b72cUL, 0xf7818176UL, +0x51d2d283UL, 0x1a0d0d17UL, 0xd46a6abeUL, 0x4c26266aUL, +0xc99e9e57UL, 0xb05858e8UL, 0xcd9c9c51UL, 0xf3838370UL, +0xe874749cUL, 0x93b3b320UL, 0xadacac01UL, 0x60303050UL, +0xf47a7a8eUL, 0xd26969bbUL, 0xee777799UL, 0x1e0f0f11UL, +0xa9aeae07UL, 0x42212163UL, 0x49dede97UL, 0x55d0d085UL, +0x5c2e2e72UL, 0xdb97974cUL, 0x20101030UL, 0xbda4a419UL, +0xc598985dUL, 0xa5a8a80dUL, 0x5dd4d489UL, 0xd06868b8UL, +0x5a2d2d77UL, 0xc46262a6UL, 0x5229297bUL, 0xda6d6db7UL, +0x2c16163aUL, 0x924949dbUL, 0xec76769aUL, 0x7bc7c7bcUL, +0x25e8e8cdUL, 0x77c1c1b6UL, 0xd996964fUL, 0x6e373759UL, +0x3fe5e5daUL, 0x61cacaabUL, 0x1df4f4e9UL, 0x27e9e9ceUL, +0xc66363a5UL, 0x24121236UL, 0x71c2c2b3UL, 0xb9a6a61fUL, +0x2814143cUL, 0x8dbcbc31UL, 0x53d3d380UL, 0x50282878UL, +0xabafaf04UL, 0x5e2f2f71UL, 0x39e6e6dfUL, 0x4824246cUL, +0xa45252f6UL, 0x79c6c6bfUL, 0xb5a0a015UL, 0x1209091bUL, +0x8fbdbd32UL, 0xed8c8c61UL, 0x6bcfcfa4UL, 0xba5d5de7UL, +0x22111133UL, 0xbe5f5fe1UL, 0x02010103UL, 0x7fc5c5baUL, +0xcb9f9f54UL, 0x7a3d3d47UL, 0xb1a2a213UL, 0xc39b9b58UL, +0x67c9c9aeUL, 0x763b3b4dUL, 0x89bebe37UL, 0xa25151f3UL, +0x3219192bUL, 0x3e1f1f21UL, 0x7e3f3f41UL, 0xb85c5ce4UL, +0x91b2b223UL, 0x2befefc4UL, 0x944a4adeUL, 0x6fcdcda2UL, +0x8bbfbf34UL, 0x81baba3bUL, 0xde6f6fb1UL, 0xc86464acUL, +0x47d9d99eUL, 0x13f3f3e0UL, 0x7c3e3e42UL, 0x9db4b429UL, +0xa1aaaa0bUL, 0x4ddcdc91UL, 0x5fd5d58aUL, 0x0c06060aUL, +0x75c0c0b5UL, 0xfc7e7e82UL, 0x19f6f6efUL, 0xcc6666aaUL, +0xd86c6cb4UL, 0xfd848479UL, 0xe2717193UL, 0x70383848UL, +0x87b9b93eUL, 0x3a1d1d27UL, 0xfe7f7f81UL, 0xcf9d9d52UL, +0x904848d8UL, 0xe38b8b68UL, 0x542a2a7eUL, 0x41dada9bUL, +0xbfa5a51aUL, 0x66333355UL, 0xf1828273UL, 0x7239394bUL, +0x59d6d68fUL, 0xf0787888UL, 0xf986867fUL, 0x01fafafbUL, +0x3de4e4d9UL, 0x562b2b7dUL, 0xa7a9a90eUL, 0x3c1e1e22UL, +0xe789896eUL, 0xc06060a0UL, 0xd66b6bbdUL, 0x21eaeacbUL, +0xaa5555ffUL, 0x984c4cd4UL, 0x1bf7f7ecUL, 0x31e2e2d3UL, +}, + +{ +0x2697b1b1UL, 0xa769ceceUL, 0xb073c3c3UL, 0x4adf9595UL, +0xeeb45a5aUL, 0x02afadadUL, 0xdc3be7e7UL, 0x06040202UL, +0xd79a4d4dUL, 0xcc884444UL, 0xf803fbfbUL, 0x46d79191UL, +0x14180c0cUL, 0x7cfb8787UL, 0x16b7a1a1UL, 0xf0a05050UL, +0xa863cbcbUL, 0xa9ce6767UL, 0xfca85454UL, 0x924fddddUL, +0xca8c4646UL, 0x64eb8f8fUL, 0xd637e1e1UL, 0xd29c4e4eUL, +0xe515f0f0UL, 0xf20ffdfdUL, 0xf10dfcfcUL, 0xc823ebebUL, +0xfe07f9f9UL, 0xb97dc4c4UL, 0x2e341a1aUL, 0xb2dc6e6eUL, +0xe2bc5e5eUL, 0xea1ff5f5UL, 0xa16dccccUL, 0x62ef8d8dUL, +0x24381c1cUL, 0xfaac5656UL, 0xc5864343UL, 0xf709fefeUL, +0x090e0707UL, 0xa3c26161UL, 0xfd05f8f8UL, 0x9fea7575UL, +0xebb25959UL, 0xf40bffffUL, 0x05060303UL, 0x66442222UL, +0x6be18a8aUL, 0x8657d1d1UL, 0x35261313UL, 0xc729eeeeUL, +0x6de58888UL, 0x00000000UL, 0x121c0e0eUL, 0x5c683434UL, +0x3f2a1515UL, 0x75f58080UL, 0x49dd9494UL, 0xd033e3e3UL, +0xc22fededUL, 0x2a9fb5b5UL, 0xf5a65353UL, 0x65462323UL, +0xdd964b4bUL, 0xc98e4747UL, 0x392e1717UL, 0x1cbba7a7UL, +0x45d59090UL, 0x5f6a3535UL, 0x08a3ababUL, 0x9d45d8d8UL, +0x3d85b8b8UL, 0x944bdfdfUL, 0xd19e4f4fUL, 0xf9ae5757UL, +0x5bc19a9aUL, 0x43d19292UL, 0x9843dbdbUL, 0x2d361b1bUL, +0x44783c3cUL, 0xad65c8c8UL, 0x5ec79999UL, 0x0c080404UL, +0x67e98e8eUL, 0xd535e0e0UL, 0x8c5bd7d7UL, 0x87fa7d7dUL, +0x7aff8585UL, 0x3883bbbbUL, 0xc0804040UL, 0x74582c2cUL, +0x4e743a3aUL, 0xcf8a4545UL, 0xe617f1f1UL, 0xc6844242UL, +0xafca6565UL, 0x60402020UL, 0xc3824141UL, 0x28301818UL, +0x96e47272UL, 0x6f4a2525UL, 0x40d39393UL, 0x90e07070UL, +0x5a6c3636UL, 0x0f0a0505UL, 0xe311f2f2UL, 0x1d160b0bUL, +0x10b3a3a3UL, 0x8bf27979UL, 0xc12dececUL, 0x18100808UL, +0x694e2727UL, 0x53623131UL, 0x56643232UL, 0x2f99b6b6UL, +0x84f87c7cUL, 0x2595b0b0UL, 0x1e140a0aUL, 0x95e67373UL, +0xedb65b5bUL, 0x8df67b7bUL, 0x2c9bb7b7UL, 0x76f78181UL, +0x8351d2d2UL, 0x171a0d0dUL, 0xbed46a6aUL, 0x6a4c2626UL, +0x57c99e9eUL, 0xe8b05858UL, 0x51cd9c9cUL, 0x70f38383UL, +0x9ce87474UL, 0x2093b3b3UL, 0x01adacacUL, 0x50603030UL, +0x8ef47a7aUL, 0xbbd26969UL, 0x99ee7777UL, 0x111e0f0fUL, +0x07a9aeaeUL, 0x63422121UL, 0x9749dedeUL, 0x8555d0d0UL, +0x725c2e2eUL, 0x4cdb9797UL, 0x30201010UL, 0x19bda4a4UL, +0x5dc59898UL, 0x0da5a8a8UL, 0x895dd4d4UL, 0xb8d06868UL, +0x775a2d2dUL, 0xa6c46262UL, 0x7b522929UL, 0xb7da6d6dUL, +0x3a2c1616UL, 0xdb924949UL, 0x9aec7676UL, 0xbc7bc7c7UL, +0xcd25e8e8UL, 0xb677c1c1UL, 0x4fd99696UL, 0x596e3737UL, +0xda3fe5e5UL, 0xab61cacaUL, 0xe91df4f4UL, 0xce27e9e9UL, +0xa5c66363UL, 0x36241212UL, 0xb371c2c2UL, 0x1fb9a6a6UL, +0x3c281414UL, 0x318dbcbcUL, 0x8053d3d3UL, 0x78502828UL, +0x04abafafUL, 0x715e2f2fUL, 0xdf39e6e6UL, 0x6c482424UL, +0xf6a45252UL, 0xbf79c6c6UL, 0x15b5a0a0UL, 0x1b120909UL, +0x328fbdbdUL, 0x61ed8c8cUL, 0xa46bcfcfUL, 0xe7ba5d5dUL, +0x33221111UL, 0xe1be5f5fUL, 0x03020101UL, 0xba7fc5c5UL, +0x54cb9f9fUL, 0x477a3d3dUL, 0x13b1a2a2UL, 0x58c39b9bUL, +0xae67c9c9UL, 0x4d763b3bUL, 0x3789bebeUL, 0xf3a25151UL, +0x2b321919UL, 0x213e1f1fUL, 0x417e3f3fUL, 0xe4b85c5cUL, +0x2391b2b2UL, 0xc42befefUL, 0xde944a4aUL, 0xa26fcdcdUL, +0x348bbfbfUL, 0x3b81babaUL, 0xb1de6f6fUL, 0xacc86464UL, +0x9e47d9d9UL, 0xe013f3f3UL, 0x427c3e3eUL, 0x299db4b4UL, +0x0ba1aaaaUL, 0x914ddcdcUL, 0x8a5fd5d5UL, 0x0a0c0606UL, +0xb575c0c0UL, 0x82fc7e7eUL, 0xef19f6f6UL, 0xaacc6666UL, +0xb4d86c6cUL, 0x79fd8484UL, 0x93e27171UL, 0x48703838UL, +0x3e87b9b9UL, 0x273a1d1dUL, 0x81fe7f7fUL, 0x52cf9d9dUL, +0xd8904848UL, 0x68e38b8bUL, 0x7e542a2aUL, 0x9b41dadaUL, +0x1abfa5a5UL, 0x55663333UL, 0x73f18282UL, 0x4b723939UL, +0x8f59d6d6UL, 0x88f07878UL, 0x7ff98686UL, 0xfb01fafaUL, +0xd93de4e4UL, 0x7d562b2bUL, 0x0ea7a9a9UL, 0x223c1e1eUL, +0x6ee78989UL, 0xa0c06060UL, 0xbdd66b6bUL, 0xcb21eaeaUL, +0xffaa5555UL, 0xd4984c4cUL, 0xec1bf7f7UL, 0xd331e2e2UL, +}, + +{ +0xb12697b1UL, 0xcea769ceUL, 0xc3b073c3UL, 0x954adf95UL, +0x5aeeb45aUL, 0xad02afadUL, 0xe7dc3be7UL, 0x02060402UL, +0x4dd79a4dUL, 0x44cc8844UL, 0xfbf803fbUL, 0x9146d791UL, +0x0c14180cUL, 0x877cfb87UL, 0xa116b7a1UL, 0x50f0a050UL, +0xcba863cbUL, 0x67a9ce67UL, 0x54fca854UL, 0xdd924fddUL, +0x46ca8c46UL, 0x8f64eb8fUL, 0xe1d637e1UL, 0x4ed29c4eUL, +0xf0e515f0UL, 0xfdf20ffdUL, 0xfcf10dfcUL, 0xebc823ebUL, +0xf9fe07f9UL, 0xc4b97dc4UL, 0x1a2e341aUL, 0x6eb2dc6eUL, +0x5ee2bc5eUL, 0xf5ea1ff5UL, 0xcca16dccUL, 0x8d62ef8dUL, +0x1c24381cUL, 0x56faac56UL, 0x43c58643UL, 0xfef709feUL, +0x07090e07UL, 0x61a3c261UL, 0xf8fd05f8UL, 0x759fea75UL, +0x59ebb259UL, 0xfff40bffUL, 0x03050603UL, 0x22664422UL, +0x8a6be18aUL, 0xd18657d1UL, 0x13352613UL, 0xeec729eeUL, +0x886de588UL, 0x00000000UL, 0x0e121c0eUL, 0x345c6834UL, +0x153f2a15UL, 0x8075f580UL, 0x9449dd94UL, 0xe3d033e3UL, +0xedc22fedUL, 0xb52a9fb5UL, 0x53f5a653UL, 0x23654623UL, +0x4bdd964bUL, 0x47c98e47UL, 0x17392e17UL, 0xa71cbba7UL, +0x9045d590UL, 0x355f6a35UL, 0xab08a3abUL, 0xd89d45d8UL, +0xb83d85b8UL, 0xdf944bdfUL, 0x4fd19e4fUL, 0x57f9ae57UL, +0x9a5bc19aUL, 0x9243d192UL, 0xdb9843dbUL, 0x1b2d361bUL, +0x3c44783cUL, 0xc8ad65c8UL, 0x995ec799UL, 0x040c0804UL, +0x8e67e98eUL, 0xe0d535e0UL, 0xd78c5bd7UL, 0x7d87fa7dUL, +0x857aff85UL, 0xbb3883bbUL, 0x40c08040UL, 0x2c74582cUL, +0x3a4e743aUL, 0x45cf8a45UL, 0xf1e617f1UL, 0x42c68442UL, +0x65afca65UL, 0x20604020UL, 0x41c38241UL, 0x18283018UL, +0x7296e472UL, 0x256f4a25UL, 0x9340d393UL, 0x7090e070UL, +0x365a6c36UL, 0x050f0a05UL, 0xf2e311f2UL, 0x0b1d160bUL, +0xa310b3a3UL, 0x798bf279UL, 0xecc12decUL, 0x08181008UL, +0x27694e27UL, 0x31536231UL, 0x32566432UL, 0xb62f99b6UL, +0x7c84f87cUL, 0xb02595b0UL, 0x0a1e140aUL, 0x7395e673UL, +0x5bedb65bUL, 0x7b8df67bUL, 0xb72c9bb7UL, 0x8176f781UL, +0xd28351d2UL, 0x0d171a0dUL, 0x6abed46aUL, 0x266a4c26UL, +0x9e57c99eUL, 0x58e8b058UL, 0x9c51cd9cUL, 0x8370f383UL, +0x749ce874UL, 0xb32093b3UL, 0xac01adacUL, 0x30506030UL, +0x7a8ef47aUL, 0x69bbd269UL, 0x7799ee77UL, 0x0f111e0fUL, +0xae07a9aeUL, 0x21634221UL, 0xde9749deUL, 0xd08555d0UL, +0x2e725c2eUL, 0x974cdb97UL, 0x10302010UL, 0xa419bda4UL, +0x985dc598UL, 0xa80da5a8UL, 0xd4895dd4UL, 0x68b8d068UL, +0x2d775a2dUL, 0x62a6c462UL, 0x297b5229UL, 0x6db7da6dUL, +0x163a2c16UL, 0x49db9249UL, 0x769aec76UL, 0xc7bc7bc7UL, +0xe8cd25e8UL, 0xc1b677c1UL, 0x964fd996UL, 0x37596e37UL, +0xe5da3fe5UL, 0xcaab61caUL, 0xf4e91df4UL, 0xe9ce27e9UL, +0x63a5c663UL, 0x12362412UL, 0xc2b371c2UL, 0xa61fb9a6UL, +0x143c2814UL, 0xbc318dbcUL, 0xd38053d3UL, 0x28785028UL, +0xaf04abafUL, 0x2f715e2fUL, 0xe6df39e6UL, 0x246c4824UL, +0x52f6a452UL, 0xc6bf79c6UL, 0xa015b5a0UL, 0x091b1209UL, +0xbd328fbdUL, 0x8c61ed8cUL, 0xcfa46bcfUL, 0x5de7ba5dUL, +0x11332211UL, 0x5fe1be5fUL, 0x01030201UL, 0xc5ba7fc5UL, +0x9f54cb9fUL, 0x3d477a3dUL, 0xa213b1a2UL, 0x9b58c39bUL, +0xc9ae67c9UL, 0x3b4d763bUL, 0xbe3789beUL, 0x51f3a251UL, +0x192b3219UL, 0x1f213e1fUL, 0x3f417e3fUL, 0x5ce4b85cUL, +0xb22391b2UL, 0xefc42befUL, 0x4ade944aUL, 0xcda26fcdUL, +0xbf348bbfUL, 0xba3b81baUL, 0x6fb1de6fUL, 0x64acc864UL, +0xd99e47d9UL, 0xf3e013f3UL, 0x3e427c3eUL, 0xb4299db4UL, +0xaa0ba1aaUL, 0xdc914ddcUL, 0xd58a5fd5UL, 0x060a0c06UL, +0xc0b575c0UL, 0x7e82fc7eUL, 0xf6ef19f6UL, 0x66aacc66UL, +0x6cb4d86cUL, 0x8479fd84UL, 0x7193e271UL, 0x38487038UL, +0xb93e87b9UL, 0x1d273a1dUL, 0x7f81fe7fUL, 0x9d52cf9dUL, +0x48d89048UL, 0x8b68e38bUL, 0x2a7e542aUL, 0xda9b41daUL, +0xa51abfa5UL, 0x33556633UL, 0x8273f182UL, 0x394b7239UL, +0xd68f59d6UL, 0x7888f078UL, 0x867ff986UL, 0xfafb01faUL, +0xe4d93de4UL, 0x2b7d562bUL, 0xa90ea7a9UL, 0x1e223c1eUL, +0x896ee789UL, 0x60a0c060UL, 0x6bbdd66bUL, 0xeacb21eaUL, +0x55ffaa55UL, 0x4cd4984cUL, 0xf7ec1bf7UL, 0xe2d331e2UL, +}, + +{ +0xb1b12697UL, 0xcecea769UL, 0xc3c3b073UL, 0x95954adfUL, +0x5a5aeeb4UL, 0xadad02afUL, 0xe7e7dc3bUL, 0x02020604UL, +0x4d4dd79aUL, 0x4444cc88UL, 0xfbfbf803UL, 0x919146d7UL, +0x0c0c1418UL, 0x87877cfbUL, 0xa1a116b7UL, 0x5050f0a0UL, +0xcbcba863UL, 0x6767a9ceUL, 0x5454fca8UL, 0xdddd924fUL, +0x4646ca8cUL, 0x8f8f64ebUL, 0xe1e1d637UL, 0x4e4ed29cUL, +0xf0f0e515UL, 0xfdfdf20fUL, 0xfcfcf10dUL, 0xebebc823UL, +0xf9f9fe07UL, 0xc4c4b97dUL, 0x1a1a2e34UL, 0x6e6eb2dcUL, +0x5e5ee2bcUL, 0xf5f5ea1fUL, 0xcccca16dUL, 0x8d8d62efUL, +0x1c1c2438UL, 0x5656faacUL, 0x4343c586UL, 0xfefef709UL, +0x0707090eUL, 0x6161a3c2UL, 0xf8f8fd05UL, 0x75759feaUL, +0x5959ebb2UL, 0xfffff40bUL, 0x03030506UL, 0x22226644UL, +0x8a8a6be1UL, 0xd1d18657UL, 0x13133526UL, 0xeeeec729UL, +0x88886de5UL, 0x00000000UL, 0x0e0e121cUL, 0x34345c68UL, +0x15153f2aUL, 0x808075f5UL, 0x949449ddUL, 0xe3e3d033UL, +0xededc22fUL, 0xb5b52a9fUL, 0x5353f5a6UL, 0x23236546UL, +0x4b4bdd96UL, 0x4747c98eUL, 0x1717392eUL, 0xa7a71cbbUL, +0x909045d5UL, 0x35355f6aUL, 0xabab08a3UL, 0xd8d89d45UL, +0xb8b83d85UL, 0xdfdf944bUL, 0x4f4fd19eUL, 0x5757f9aeUL, +0x9a9a5bc1UL, 0x929243d1UL, 0xdbdb9843UL, 0x1b1b2d36UL, +0x3c3c4478UL, 0xc8c8ad65UL, 0x99995ec7UL, 0x04040c08UL, +0x8e8e67e9UL, 0xe0e0d535UL, 0xd7d78c5bUL, 0x7d7d87faUL, +0x85857affUL, 0xbbbb3883UL, 0x4040c080UL, 0x2c2c7458UL, +0x3a3a4e74UL, 0x4545cf8aUL, 0xf1f1e617UL, 0x4242c684UL, +0x6565afcaUL, 0x20206040UL, 0x4141c382UL, 0x18182830UL, +0x727296e4UL, 0x25256f4aUL, 0x939340d3UL, 0x707090e0UL, +0x36365a6cUL, 0x05050f0aUL, 0xf2f2e311UL, 0x0b0b1d16UL, +0xa3a310b3UL, 0x79798bf2UL, 0xececc12dUL, 0x08081810UL, +0x2727694eUL, 0x31315362UL, 0x32325664UL, 0xb6b62f99UL, +0x7c7c84f8UL, 0xb0b02595UL, 0x0a0a1e14UL, 0x737395e6UL, +0x5b5bedb6UL, 0x7b7b8df6UL, 0xb7b72c9bUL, 0x818176f7UL, +0xd2d28351UL, 0x0d0d171aUL, 0x6a6abed4UL, 0x26266a4cUL, +0x9e9e57c9UL, 0x5858e8b0UL, 0x9c9c51cdUL, 0x838370f3UL, +0x74749ce8UL, 0xb3b32093UL, 0xacac01adUL, 0x30305060UL, +0x7a7a8ef4UL, 0x6969bbd2UL, 0x777799eeUL, 0x0f0f111eUL, +0xaeae07a9UL, 0x21216342UL, 0xdede9749UL, 0xd0d08555UL, +0x2e2e725cUL, 0x97974cdbUL, 0x10103020UL, 0xa4a419bdUL, +0x98985dc5UL, 0xa8a80da5UL, 0xd4d4895dUL, 0x6868b8d0UL, +0x2d2d775aUL, 0x6262a6c4UL, 0x29297b52UL, 0x6d6db7daUL, +0x16163a2cUL, 0x4949db92UL, 0x76769aecUL, 0xc7c7bc7bUL, +0xe8e8cd25UL, 0xc1c1b677UL, 0x96964fd9UL, 0x3737596eUL, +0xe5e5da3fUL, 0xcacaab61UL, 0xf4f4e91dUL, 0xe9e9ce27UL, +0x6363a5c6UL, 0x12123624UL, 0xc2c2b371UL, 0xa6a61fb9UL, +0x14143c28UL, 0xbcbc318dUL, 0xd3d38053UL, 0x28287850UL, +0xafaf04abUL, 0x2f2f715eUL, 0xe6e6df39UL, 0x24246c48UL, +0x5252f6a4UL, 0xc6c6bf79UL, 0xa0a015b5UL, 0x09091b12UL, +0xbdbd328fUL, 0x8c8c61edUL, 0xcfcfa46bUL, 0x5d5de7baUL, +0x11113322UL, 0x5f5fe1beUL, 0x01010302UL, 0xc5c5ba7fUL, +0x9f9f54cbUL, 0x3d3d477aUL, 0xa2a213b1UL, 0x9b9b58c3UL, +0xc9c9ae67UL, 0x3b3b4d76UL, 0xbebe3789UL, 0x5151f3a2UL, +0x19192b32UL, 0x1f1f213eUL, 0x3f3f417eUL, 0x5c5ce4b8UL, +0xb2b22391UL, 0xefefc42bUL, 0x4a4ade94UL, 0xcdcda26fUL, +0xbfbf348bUL, 0xbaba3b81UL, 0x6f6fb1deUL, 0x6464acc8UL, +0xd9d99e47UL, 0xf3f3e013UL, 0x3e3e427cUL, 0xb4b4299dUL, +0xaaaa0ba1UL, 0xdcdc914dUL, 0xd5d58a5fUL, 0x06060a0cUL, +0xc0c0b575UL, 0x7e7e82fcUL, 0xf6f6ef19UL, 0x6666aaccUL, +0x6c6cb4d8UL, 0x848479fdUL, 0x717193e2UL, 0x38384870UL, +0xb9b93e87UL, 0x1d1d273aUL, 0x7f7f81feUL, 0x9d9d52cfUL, +0x4848d890UL, 0x8b8b68e3UL, 0x2a2a7e54UL, 0xdada9b41UL, +0xa5a51abfUL, 0x33335566UL, 0x828273f1UL, 0x39394b72UL, +0xd6d68f59UL, 0x787888f0UL, 0x86867ff9UL, 0xfafafb01UL, +0xe4e4d93dUL, 0x2b2b7d56UL, 0xa9a90ea7UL, 0x1e1e223cUL, +0x89896ee7UL, 0x6060a0c0UL, 0x6b6bbdd6UL, 0xeaeacb21UL, +0x5555ffaaUL, 0x4c4cd498UL, 0xf7f7ec1bUL, 0xe2e2d331UL, +}}; + +const word32 Square::Dec::Td[4][256] = { +{ +0xe368bc02UL, 0x5585620cUL, 0x2a3f2331UL, 0x61ab13f7UL, +0x98d46d72UL, 0x21cb9a19UL, 0x3c22a461UL, 0x459d3dcdUL, +0x05fdb423UL, 0x2bc4075fUL, 0x9b2c01c0UL, 0x3dd9800fUL, +0x486c5c74UL, 0xf97f7e85UL, 0xf173ab1fUL, 0xb6edde0eUL, +0x283c6bedUL, 0x4997781aUL, 0x9f2a918dUL, 0xc9579f33UL, +0xa907a8aaUL, 0xa50ded7dUL, 0x7c422d8fUL, 0x764db0c9UL, +0x4d91e857UL, 0xcea963ccUL, 0xb4ee96d2UL, 0x3028e1b6UL, +0x0df161b9UL, 0xbd196726UL, 0x419bad80UL, 0xc0a06ec7UL, +0x5183f241UL, 0x92dbf034UL, 0x6fa21efcUL, 0x8f32ce4cUL, +0x13e03373UL, 0x69a7c66dUL, 0xe56d6493UL, 0xbf1a2ffaUL, +0xbb1cbfb7UL, 0x587403b5UL, 0xe76e2c4fUL, 0x5d89b796UL, +0xe89c052aUL, 0x446619a3UL, 0x342e71fbUL, 0x0ff22965UL, +0xfe81827aUL, 0xb11322f1UL, 0xa30835ecUL, 0xcd510f7eUL, +0xff7aa614UL, 0x5c7293f8UL, 0x2fc29712UL, 0xf370e3c3UL, +0x992f491cUL, 0xd1431568UL, 0xc2a3261bUL, 0x88cc32b3UL, +0x8acf7a6fUL, 0xb0e8069fUL, 0x7a47f51eUL, 0xd2bb79daUL, +0xe6950821UL, 0x4398e55cUL, 0xd0b83106UL, 0x11e37bafUL, +0x7e416553UL, 0xccaa2b10UL, 0xd8b4e49cUL, 0x6456a7d4UL, +0xfb7c3659UL, 0x724b2084UL, 0xea9f4df6UL, 0x6a5faadfUL, +0x2dc1dfceUL, 0x70486858UL, 0xcaaff381UL, 0x0605d891UL, +0x5a774b69UL, 0x94de28a5UL, 0x39df1042UL, 0x813bc347UL, +0xfc82caa6UL, 0x23c8d2c5UL, 0x03f86cb2UL, 0x080cd59aUL, +0xdab7ac40UL, 0x7db909e1UL, 0x3824342cUL, 0xcf5247a2UL, +0xdcb274d1UL, 0x63a85b2bUL, 0x35d55595UL, 0x479e7511UL, +0x15e5ebe2UL, 0x4b9430c6UL, 0x4a6f14a8UL, 0x91239c86UL, +0x4c6acc39UL, 0x5f8aff4aUL, 0x0406904dUL, 0xee99ddbbUL, +0x1e1152caUL, 0xaaffc418UL, 0xeb646998UL, 0x07fefcffUL, +0x8b345e01UL, 0x567d0ebeUL, 0xbae79bd9UL, 0x4263c132UL, +0x75b5dc7bUL, 0x97264417UL, 0x67aecb66UL, 0x95250ccbUL, +0xec9a9567UL, 0x57862ad0UL, 0x60503799UL, 0xb8e4d305UL, +0x65ad83baUL, 0x19efae35UL, 0xa4f6c913UL, 0xc15b4aa9UL, +0x873e1bd6UL, 0xa0f0595eUL, 0x18148a5bUL, 0xaf02703bUL, +0xab04e076UL, 0xdd4950bfUL, 0xdf4a1863UL, 0xc6a5b656UL, +0x853d530aUL, 0xfa871237UL, 0x77b694a7UL, 0x4665517fUL, +0xed61b109UL, 0x1bece6e9UL, 0xd5458525UL, 0xf5753b52UL, +0x7fba413dUL, 0x27ce4288UL, 0xb2eb4e43UL, 0xd6bde997UL, +0x527b9ef3UL, 0x62537f45UL, 0x2c3afba0UL, 0x7bbcd170UL, +0xb91ff76bUL, 0x121b171dUL, 0xfd79eec8UL, 0x3a277cf0UL, +0x0c0a45d7UL, 0x96dd6079UL, 0x2233f6abUL, 0xacfa1c89UL, +0xc8acbb5dUL, 0xa10b7d30UL, 0xd4bea14bUL, 0xbee10b94UL, +0x25cd0a54UL, 0x547e4662UL, 0xa2f31182UL, 0x17e6a33eUL, +0x263566e6UL, 0xc3580275UL, 0x83388b9bUL, 0x7844bdc2UL, +0x020348dcUL, 0x4f92a08bUL, 0x2e39b37cUL, 0x4e6984e5UL, +0xf0888f71UL, 0x362d3927UL, 0x9cd2fd3fUL, 0x01fb246eUL, +0x893716ddUL, 0x00000000UL, 0xf68d57e0UL, 0xe293986cUL, +0x744ef815UL, 0x9320d45aUL, 0xad0138e7UL, 0xd3405db4UL, +0x1a17c287UL, 0xb3106a2dUL, 0x5078d62fUL, 0xf48e1f3cUL, +0xa70ea5a1UL, 0x71b34c36UL, 0x9ad725aeUL, 0x5e71db24UL, +0x161d8750UL, 0xef62f9d5UL, 0x8d318690UL, 0x1c121a16UL, +0xa6f581cfUL, 0x5b8c6f07UL, 0x37d61d49UL, 0x6e593a92UL, +0x84c67764UL, 0x86c53fb8UL, 0xd746cdf9UL, 0xe090d0b0UL, +0x29c74f83UL, 0xe49640fdUL, 0x0e090d0bUL, 0x6da15620UL, +0x8ec9ea22UL, 0xdb4c882eUL, 0xf776738eUL, 0xb515b2bcUL, +0x10185fc1UL, 0x322ba96aUL, 0x6ba48eb1UL, 0xaef95455UL, +0x406089eeUL, 0x6655ef08UL, 0xe9672144UL, 0x3e21ecbdUL, +0x2030be77UL, 0xf28bc7adUL, 0x80c0e729UL, 0x141ecf8cUL, +0xbce24348UL, 0xc4a6fe8aUL, 0x31d3c5d8UL, 0xb716fa60UL, +0x5380ba9dUL, 0xd94fc0f2UL, 0x1de93e78UL, 0x24362e3aUL, +0xe16bf4deUL, 0xcb54d7efUL, 0x09f7f1f4UL, 0x82c3aff5UL, +0x0bf4b928UL, 0x9d29d951UL, 0xc75e9238UL, 0xf8845aebUL, +0x90d8b8e8UL, 0xdeb13c0dUL, 0x33d08d04UL, 0x685ce203UL, +0xc55ddae4UL, 0x3bdc589eUL, 0x0a0f9d46UL, 0x3fdac8d3UL, +0x598f27dbUL, 0xa8fc8cc4UL, 0x79bf99acUL, 0x6c5a724eUL, +0x8ccaa2feUL, 0x9ed1b5e3UL, 0x1fea76a4UL, 0x73b004eaUL, +}, + +{ +0x02e368bcUL, 0x0c558562UL, 0x312a3f23UL, 0xf761ab13UL, +0x7298d46dUL, 0x1921cb9aUL, 0x613c22a4UL, 0xcd459d3dUL, +0x2305fdb4UL, 0x5f2bc407UL, 0xc09b2c01UL, 0x0f3dd980UL, +0x74486c5cUL, 0x85f97f7eUL, 0x1ff173abUL, 0x0eb6eddeUL, +0xed283c6bUL, 0x1a499778UL, 0x8d9f2a91UL, 0x33c9579fUL, +0xaaa907a8UL, 0x7da50dedUL, 0x8f7c422dUL, 0xc9764db0UL, +0x574d91e8UL, 0xcccea963UL, 0xd2b4ee96UL, 0xb63028e1UL, +0xb90df161UL, 0x26bd1967UL, 0x80419badUL, 0xc7c0a06eUL, +0x415183f2UL, 0x3492dbf0UL, 0xfc6fa21eUL, 0x4c8f32ceUL, +0x7313e033UL, 0x6d69a7c6UL, 0x93e56d64UL, 0xfabf1a2fUL, +0xb7bb1cbfUL, 0xb5587403UL, 0x4fe76e2cUL, 0x965d89b7UL, +0x2ae89c05UL, 0xa3446619UL, 0xfb342e71UL, 0x650ff229UL, +0x7afe8182UL, 0xf1b11322UL, 0xeca30835UL, 0x7ecd510fUL, +0x14ff7aa6UL, 0xf85c7293UL, 0x122fc297UL, 0xc3f370e3UL, +0x1c992f49UL, 0x68d14315UL, 0x1bc2a326UL, 0xb388cc32UL, +0x6f8acf7aUL, 0x9fb0e806UL, 0x1e7a47f5UL, 0xdad2bb79UL, +0x21e69508UL, 0x5c4398e5UL, 0x06d0b831UL, 0xaf11e37bUL, +0x537e4165UL, 0x10ccaa2bUL, 0x9cd8b4e4UL, 0xd46456a7UL, +0x59fb7c36UL, 0x84724b20UL, 0xf6ea9f4dUL, 0xdf6a5faaUL, +0xce2dc1dfUL, 0x58704868UL, 0x81caaff3UL, 0x910605d8UL, +0x695a774bUL, 0xa594de28UL, 0x4239df10UL, 0x47813bc3UL, +0xa6fc82caUL, 0xc523c8d2UL, 0xb203f86cUL, 0x9a080cd5UL, +0x40dab7acUL, 0xe17db909UL, 0x2c382434UL, 0xa2cf5247UL, +0xd1dcb274UL, 0x2b63a85bUL, 0x9535d555UL, 0x11479e75UL, +0xe215e5ebUL, 0xc64b9430UL, 0xa84a6f14UL, 0x8691239cUL, +0x394c6accUL, 0x4a5f8affUL, 0x4d040690UL, 0xbbee99ddUL, +0xca1e1152UL, 0x18aaffc4UL, 0x98eb6469UL, 0xff07fefcUL, +0x018b345eUL, 0xbe567d0eUL, 0xd9bae79bUL, 0x324263c1UL, +0x7b75b5dcUL, 0x17972644UL, 0x6667aecbUL, 0xcb95250cUL, +0x67ec9a95UL, 0xd057862aUL, 0x99605037UL, 0x05b8e4d3UL, +0xba65ad83UL, 0x3519efaeUL, 0x13a4f6c9UL, 0xa9c15b4aUL, +0xd6873e1bUL, 0x5ea0f059UL, 0x5b18148aUL, 0x3baf0270UL, +0x76ab04e0UL, 0xbfdd4950UL, 0x63df4a18UL, 0x56c6a5b6UL, +0x0a853d53UL, 0x37fa8712UL, 0xa777b694UL, 0x7f466551UL, +0x09ed61b1UL, 0xe91bece6UL, 0x25d54585UL, 0x52f5753bUL, +0x3d7fba41UL, 0x8827ce42UL, 0x43b2eb4eUL, 0x97d6bde9UL, +0xf3527b9eUL, 0x4562537fUL, 0xa02c3afbUL, 0x707bbcd1UL, +0x6bb91ff7UL, 0x1d121b17UL, 0xc8fd79eeUL, 0xf03a277cUL, +0xd70c0a45UL, 0x7996dd60UL, 0xab2233f6UL, 0x89acfa1cUL, +0x5dc8acbbUL, 0x30a10b7dUL, 0x4bd4bea1UL, 0x94bee10bUL, +0x5425cd0aUL, 0x62547e46UL, 0x82a2f311UL, 0x3e17e6a3UL, +0xe6263566UL, 0x75c35802UL, 0x9b83388bUL, 0xc27844bdUL, +0xdc020348UL, 0x8b4f92a0UL, 0x7c2e39b3UL, 0xe54e6984UL, +0x71f0888fUL, 0x27362d39UL, 0x3f9cd2fdUL, 0x6e01fb24UL, +0xdd893716UL, 0x00000000UL, 0xe0f68d57UL, 0x6ce29398UL, +0x15744ef8UL, 0x5a9320d4UL, 0xe7ad0138UL, 0xb4d3405dUL, +0x871a17c2UL, 0x2db3106aUL, 0x2f5078d6UL, 0x3cf48e1fUL, +0xa1a70ea5UL, 0x3671b34cUL, 0xae9ad725UL, 0x245e71dbUL, +0x50161d87UL, 0xd5ef62f9UL, 0x908d3186UL, 0x161c121aUL, +0xcfa6f581UL, 0x075b8c6fUL, 0x4937d61dUL, 0x926e593aUL, +0x6484c677UL, 0xb886c53fUL, 0xf9d746cdUL, 0xb0e090d0UL, +0x8329c74fUL, 0xfde49640UL, 0x0b0e090dUL, 0x206da156UL, +0x228ec9eaUL, 0x2edb4c88UL, 0x8ef77673UL, 0xbcb515b2UL, +0xc110185fUL, 0x6a322ba9UL, 0xb16ba48eUL, 0x55aef954UL, +0xee406089UL, 0x086655efUL, 0x44e96721UL, 0xbd3e21ecUL, +0x772030beUL, 0xadf28bc7UL, 0x2980c0e7UL, 0x8c141ecfUL, +0x48bce243UL, 0x8ac4a6feUL, 0xd831d3c5UL, 0x60b716faUL, +0x9d5380baUL, 0xf2d94fc0UL, 0x781de93eUL, 0x3a24362eUL, +0xdee16bf4UL, 0xefcb54d7UL, 0xf409f7f1UL, 0xf582c3afUL, +0x280bf4b9UL, 0x519d29d9UL, 0x38c75e92UL, 0xebf8845aUL, +0xe890d8b8UL, 0x0ddeb13cUL, 0x0433d08dUL, 0x03685ce2UL, +0xe4c55ddaUL, 0x9e3bdc58UL, 0x460a0f9dUL, 0xd33fdac8UL, +0xdb598f27UL, 0xc4a8fc8cUL, 0xac79bf99UL, 0x4e6c5a72UL, +0xfe8ccaa2UL, 0xe39ed1b5UL, 0xa41fea76UL, 0xea73b004UL, +}, + +{ +0xbc02e368UL, 0x620c5585UL, 0x23312a3fUL, 0x13f761abUL, +0x6d7298d4UL, 0x9a1921cbUL, 0xa4613c22UL, 0x3dcd459dUL, +0xb42305fdUL, 0x075f2bc4UL, 0x01c09b2cUL, 0x800f3dd9UL, +0x5c74486cUL, 0x7e85f97fUL, 0xab1ff173UL, 0xde0eb6edUL, +0x6bed283cUL, 0x781a4997UL, 0x918d9f2aUL, 0x9f33c957UL, +0xa8aaa907UL, 0xed7da50dUL, 0x2d8f7c42UL, 0xb0c9764dUL, +0xe8574d91UL, 0x63cccea9UL, 0x96d2b4eeUL, 0xe1b63028UL, +0x61b90df1UL, 0x6726bd19UL, 0xad80419bUL, 0x6ec7c0a0UL, +0xf2415183UL, 0xf03492dbUL, 0x1efc6fa2UL, 0xce4c8f32UL, +0x337313e0UL, 0xc66d69a7UL, 0x6493e56dUL, 0x2ffabf1aUL, +0xbfb7bb1cUL, 0x03b55874UL, 0x2c4fe76eUL, 0xb7965d89UL, +0x052ae89cUL, 0x19a34466UL, 0x71fb342eUL, 0x29650ff2UL, +0x827afe81UL, 0x22f1b113UL, 0x35eca308UL, 0x0f7ecd51UL, +0xa614ff7aUL, 0x93f85c72UL, 0x97122fc2UL, 0xe3c3f370UL, +0x491c992fUL, 0x1568d143UL, 0x261bc2a3UL, 0x32b388ccUL, +0x7a6f8acfUL, 0x069fb0e8UL, 0xf51e7a47UL, 0x79dad2bbUL, +0x0821e695UL, 0xe55c4398UL, 0x3106d0b8UL, 0x7baf11e3UL, +0x65537e41UL, 0x2b10ccaaUL, 0xe49cd8b4UL, 0xa7d46456UL, +0x3659fb7cUL, 0x2084724bUL, 0x4df6ea9fUL, 0xaadf6a5fUL, +0xdfce2dc1UL, 0x68587048UL, 0xf381caafUL, 0xd8910605UL, +0x4b695a77UL, 0x28a594deUL, 0x104239dfUL, 0xc347813bUL, +0xcaa6fc82UL, 0xd2c523c8UL, 0x6cb203f8UL, 0xd59a080cUL, +0xac40dab7UL, 0x09e17db9UL, 0x342c3824UL, 0x47a2cf52UL, +0x74d1dcb2UL, 0x5b2b63a8UL, 0x559535d5UL, 0x7511479eUL, +0xebe215e5UL, 0x30c64b94UL, 0x14a84a6fUL, 0x9c869123UL, +0xcc394c6aUL, 0xff4a5f8aUL, 0x904d0406UL, 0xddbbee99UL, +0x52ca1e11UL, 0xc418aaffUL, 0x6998eb64UL, 0xfcff07feUL, +0x5e018b34UL, 0x0ebe567dUL, 0x9bd9bae7UL, 0xc1324263UL, +0xdc7b75b5UL, 0x44179726UL, 0xcb6667aeUL, 0x0ccb9525UL, +0x9567ec9aUL, 0x2ad05786UL, 0x37996050UL, 0xd305b8e4UL, +0x83ba65adUL, 0xae3519efUL, 0xc913a4f6UL, 0x4aa9c15bUL, +0x1bd6873eUL, 0x595ea0f0UL, 0x8a5b1814UL, 0x703baf02UL, +0xe076ab04UL, 0x50bfdd49UL, 0x1863df4aUL, 0xb656c6a5UL, +0x530a853dUL, 0x1237fa87UL, 0x94a777b6UL, 0x517f4665UL, +0xb109ed61UL, 0xe6e91becUL, 0x8525d545UL, 0x3b52f575UL, +0x413d7fbaUL, 0x428827ceUL, 0x4e43b2ebUL, 0xe997d6bdUL, +0x9ef3527bUL, 0x7f456253UL, 0xfba02c3aUL, 0xd1707bbcUL, +0xf76bb91fUL, 0x171d121bUL, 0xeec8fd79UL, 0x7cf03a27UL, +0x45d70c0aUL, 0x607996ddUL, 0xf6ab2233UL, 0x1c89acfaUL, +0xbb5dc8acUL, 0x7d30a10bUL, 0xa14bd4beUL, 0x0b94bee1UL, +0x0a5425cdUL, 0x4662547eUL, 0x1182a2f3UL, 0xa33e17e6UL, +0x66e62635UL, 0x0275c358UL, 0x8b9b8338UL, 0xbdc27844UL, +0x48dc0203UL, 0xa08b4f92UL, 0xb37c2e39UL, 0x84e54e69UL, +0x8f71f088UL, 0x3927362dUL, 0xfd3f9cd2UL, 0x246e01fbUL, +0x16dd8937UL, 0x00000000UL, 0x57e0f68dUL, 0x986ce293UL, +0xf815744eUL, 0xd45a9320UL, 0x38e7ad01UL, 0x5db4d340UL, +0xc2871a17UL, 0x6a2db310UL, 0xd62f5078UL, 0x1f3cf48eUL, +0xa5a1a70eUL, 0x4c3671b3UL, 0x25ae9ad7UL, 0xdb245e71UL, +0x8750161dUL, 0xf9d5ef62UL, 0x86908d31UL, 0x1a161c12UL, +0x81cfa6f5UL, 0x6f075b8cUL, 0x1d4937d6UL, 0x3a926e59UL, +0x776484c6UL, 0x3fb886c5UL, 0xcdf9d746UL, 0xd0b0e090UL, +0x4f8329c7UL, 0x40fde496UL, 0x0d0b0e09UL, 0x56206da1UL, +0xea228ec9UL, 0x882edb4cUL, 0x738ef776UL, 0xb2bcb515UL, +0x5fc11018UL, 0xa96a322bUL, 0x8eb16ba4UL, 0x5455aef9UL, +0x89ee4060UL, 0xef086655UL, 0x2144e967UL, 0xecbd3e21UL, +0xbe772030UL, 0xc7adf28bUL, 0xe72980c0UL, 0xcf8c141eUL, +0x4348bce2UL, 0xfe8ac4a6UL, 0xc5d831d3UL, 0xfa60b716UL, +0xba9d5380UL, 0xc0f2d94fUL, 0x3e781de9UL, 0x2e3a2436UL, +0xf4dee16bUL, 0xd7efcb54UL, 0xf1f409f7UL, 0xaff582c3UL, +0xb9280bf4UL, 0xd9519d29UL, 0x9238c75eUL, 0x5aebf884UL, +0xb8e890d8UL, 0x3c0ddeb1UL, 0x8d0433d0UL, 0xe203685cUL, +0xdae4c55dUL, 0x589e3bdcUL, 0x9d460a0fUL, 0xc8d33fdaUL, +0x27db598fUL, 0x8cc4a8fcUL, 0x99ac79bfUL, 0x724e6c5aUL, +0xa2fe8ccaUL, 0xb5e39ed1UL, 0x76a41feaUL, 0x04ea73b0UL, +}, + +{ +0x68bc02e3UL, 0x85620c55UL, 0x3f23312aUL, 0xab13f761UL, +0xd46d7298UL, 0xcb9a1921UL, 0x22a4613cUL, 0x9d3dcd45UL, +0xfdb42305UL, 0xc4075f2bUL, 0x2c01c09bUL, 0xd9800f3dUL, +0x6c5c7448UL, 0x7f7e85f9UL, 0x73ab1ff1UL, 0xedde0eb6UL, +0x3c6bed28UL, 0x97781a49UL, 0x2a918d9fUL, 0x579f33c9UL, +0x07a8aaa9UL, 0x0ded7da5UL, 0x422d8f7cUL, 0x4db0c976UL, +0x91e8574dUL, 0xa963ccceUL, 0xee96d2b4UL, 0x28e1b630UL, +0xf161b90dUL, 0x196726bdUL, 0x9bad8041UL, 0xa06ec7c0UL, +0x83f24151UL, 0xdbf03492UL, 0xa21efc6fUL, 0x32ce4c8fUL, +0xe0337313UL, 0xa7c66d69UL, 0x6d6493e5UL, 0x1a2ffabfUL, +0x1cbfb7bbUL, 0x7403b558UL, 0x6e2c4fe7UL, 0x89b7965dUL, +0x9c052ae8UL, 0x6619a344UL, 0x2e71fb34UL, 0xf229650fUL, +0x81827afeUL, 0x1322f1b1UL, 0x0835eca3UL, 0x510f7ecdUL, +0x7aa614ffUL, 0x7293f85cUL, 0xc297122fUL, 0x70e3c3f3UL, +0x2f491c99UL, 0x431568d1UL, 0xa3261bc2UL, 0xcc32b388UL, +0xcf7a6f8aUL, 0xe8069fb0UL, 0x47f51e7aUL, 0xbb79dad2UL, +0x950821e6UL, 0x98e55c43UL, 0xb83106d0UL, 0xe37baf11UL, +0x4165537eUL, 0xaa2b10ccUL, 0xb4e49cd8UL, 0x56a7d464UL, +0x7c3659fbUL, 0x4b208472UL, 0x9f4df6eaUL, 0x5faadf6aUL, +0xc1dfce2dUL, 0x48685870UL, 0xaff381caUL, 0x05d89106UL, +0x774b695aUL, 0xde28a594UL, 0xdf104239UL, 0x3bc34781UL, +0x82caa6fcUL, 0xc8d2c523UL, 0xf86cb203UL, 0x0cd59a08UL, +0xb7ac40daUL, 0xb909e17dUL, 0x24342c38UL, 0x5247a2cfUL, +0xb274d1dcUL, 0xa85b2b63UL, 0xd5559535UL, 0x9e751147UL, +0xe5ebe215UL, 0x9430c64bUL, 0x6f14a84aUL, 0x239c8691UL, +0x6acc394cUL, 0x8aff4a5fUL, 0x06904d04UL, 0x99ddbbeeUL, +0x1152ca1eUL, 0xffc418aaUL, 0x646998ebUL, 0xfefcff07UL, +0x345e018bUL, 0x7d0ebe56UL, 0xe79bd9baUL, 0x63c13242UL, +0xb5dc7b75UL, 0x26441797UL, 0xaecb6667UL, 0x250ccb95UL, +0x9a9567ecUL, 0x862ad057UL, 0x50379960UL, 0xe4d305b8UL, +0xad83ba65UL, 0xefae3519UL, 0xf6c913a4UL, 0x5b4aa9c1UL, +0x3e1bd687UL, 0xf0595ea0UL, 0x148a5b18UL, 0x02703bafUL, +0x04e076abUL, 0x4950bfddUL, 0x4a1863dfUL, 0xa5b656c6UL, +0x3d530a85UL, 0x871237faUL, 0xb694a777UL, 0x65517f46UL, +0x61b109edUL, 0xece6e91bUL, 0x458525d5UL, 0x753b52f5UL, +0xba413d7fUL, 0xce428827UL, 0xeb4e43b2UL, 0xbde997d6UL, +0x7b9ef352UL, 0x537f4562UL, 0x3afba02cUL, 0xbcd1707bUL, +0x1ff76bb9UL, 0x1b171d12UL, 0x79eec8fdUL, 0x277cf03aUL, +0x0a45d70cUL, 0xdd607996UL, 0x33f6ab22UL, 0xfa1c89acUL, +0xacbb5dc8UL, 0x0b7d30a1UL, 0xbea14bd4UL, 0xe10b94beUL, +0xcd0a5425UL, 0x7e466254UL, 0xf31182a2UL, 0xe6a33e17UL, +0x3566e626UL, 0x580275c3UL, 0x388b9b83UL, 0x44bdc278UL, +0x0348dc02UL, 0x92a08b4fUL, 0x39b37c2eUL, 0x6984e54eUL, +0x888f71f0UL, 0x2d392736UL, 0xd2fd3f9cUL, 0xfb246e01UL, +0x3716dd89UL, 0x00000000UL, 0x8d57e0f6UL, 0x93986ce2UL, +0x4ef81574UL, 0x20d45a93UL, 0x0138e7adUL, 0x405db4d3UL, +0x17c2871aUL, 0x106a2db3UL, 0x78d62f50UL, 0x8e1f3cf4UL, +0x0ea5a1a7UL, 0xb34c3671UL, 0xd725ae9aUL, 0x71db245eUL, +0x1d875016UL, 0x62f9d5efUL, 0x3186908dUL, 0x121a161cUL, +0xf581cfa6UL, 0x8c6f075bUL, 0xd61d4937UL, 0x593a926eUL, +0xc6776484UL, 0xc53fb886UL, 0x46cdf9d7UL, 0x90d0b0e0UL, +0xc74f8329UL, 0x9640fde4UL, 0x090d0b0eUL, 0xa156206dUL, +0xc9ea228eUL, 0x4c882edbUL, 0x76738ef7UL, 0x15b2bcb5UL, +0x185fc110UL, 0x2ba96a32UL, 0xa48eb16bUL, 0xf95455aeUL, +0x6089ee40UL, 0x55ef0866UL, 0x672144e9UL, 0x21ecbd3eUL, +0x30be7720UL, 0x8bc7adf2UL, 0xc0e72980UL, 0x1ecf8c14UL, +0xe24348bcUL, 0xa6fe8ac4UL, 0xd3c5d831UL, 0x16fa60b7UL, +0x80ba9d53UL, 0x4fc0f2d9UL, 0xe93e781dUL, 0x362e3a24UL, +0x6bf4dee1UL, 0x54d7efcbUL, 0xf7f1f409UL, 0xc3aff582UL, +0xf4b9280bUL, 0x29d9519dUL, 0x5e9238c7UL, 0x845aebf8UL, +0xd8b8e890UL, 0xb13c0ddeUL, 0xd08d0433UL, 0x5ce20368UL, +0x5ddae4c5UL, 0xdc589e3bUL, 0x0f9d460aUL, 0xdac8d33fUL, +0x8f27db59UL, 0xfc8cc4a8UL, 0xbf99ac79UL, 0x5a724e6cUL, +0xcaa2fe8cUL, 0xd1b5e39eUL, 0xea76a41fUL, 0xb004ea73UL, +}}; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/sse_simd.cpp b/external/ours/library/crypto/src/shared/original/sse_simd.cpp new file mode 100755 index 000000000..96c80a270 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/sse_simd.cpp @@ -0,0 +1,115 @@ +// sse_simd.cpp - written and placed in the public domain by +// Jeffrey Walton, Uri Blumenthal and Marcel Raad. +// +// This source file uses intrinsics to gain access to SSE for CPU +// feature testing. A separate source file is needed because additional +// CXXFLAGS are required to enable the appropriate instructions set in +// some build configurations. + +#include "pch.h" +#include "config.h" +#include "cpu.h" + +// Needed by MIPS for definition of NULL +#include "stdcpp.h" + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +# include +# include +#endif + +#ifndef EXCEPTION_EXECUTE_HANDLER +# define EXCEPTION_EXECUTE_HANDLER 1 +#endif + +// Needed by SunCC and MSVC +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +# if !defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) && !CRYPTOPP_SSE2_ASM_AVAILABLE && CRYPTOPP_SSE2_INTRIN_AVAILABLE +# include +# endif +#endif + +// Squash MS LNK4221 and libtool warnings +extern const char SSE_SIMD_FNAME[] = __FILE__; + +NAMESPACE_BEGIN(CryptoPP) + +#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY +extern "C" { + typedef void (*SigHandler)(int); +} + +extern "C" +{ + static jmp_buf s_jmpNoSSE2; + static void SigIllHandler(int) + { + longjmp(s_jmpNoSSE2, 1); + } +} +#endif // CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY + +bool CPU_ProbeSSE2() +{ + // Apple switched to Intel desktops in 2005/2006 using + // Core2 Duo's, which provides SSE2 and above. +#if CRYPTOPP_BOOL_X64 || defined(__APPLE__) + return true; +#elif defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) + return false; +#elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) + __try + { +# if CRYPTOPP_SSE2_ASM_AVAILABLE + AS2(por xmm0, xmm0) // executing SSE2 instruction +# elif CRYPTOPP_SSE2_INTRIN_AVAILABLE + __m128i x = _mm_setzero_si128(); + return _mm_cvtsi128_si32(x) == 0; +# endif + } + // GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + return true; +#else + // longjmp and clobber warnings. Volatile is required. + // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 + volatile bool result = true; + + volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + +# ifndef __MINGW32__ + volatile sigset_t oldMask; + if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) + { + signal(SIGILL, oldHandler); + return false; + } +# endif + + if (setjmp(s_jmpNoSSE2)) + result = false; + else + { +# if CRYPTOPP_SSE2_ASM_AVAILABLE + __asm __volatile ("por %xmm0, %xmm0"); +# elif CRYPTOPP_SSE2_INTRIN_AVAILABLE + __m128i x = _mm_setzero_si128(); + result = _mm_cvtsi128_si32(x) == 0; +# endif + } + +# ifndef __MINGW32__ + sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); +# endif + + signal(SIGILL, oldHandler); + return result; +#endif +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/stdcpp.h b/external/ours/library/crypto/src/shared/original/stdcpp.h new file mode 100755 index 000000000..8bda29049 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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 _MSC_VER >= 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(_MSC_VER) && (_MSC_VER < 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 _MSC_VER >= 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 _MSC_VER +# include +#endif + +// uintptr_t and ptrdiff_t +#if defined(__SUNPRO_CC) +# if (__SUNPRO_CC >= 0x5100) +# include +# endif +#elif defined(_MSC_VER) +# if (_MSC_VER >= 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/external/ours/library/crypto/src/shared/original/strciphr.cpp b/external/ours/library/crypto/src/shared/original/strciphr.cpp new file mode 100755 index 000000000..f73a05e10 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/strciphr.cpp @@ -0,0 +1,328 @@ +// strciphr.cpp - originally written and placed in the public domain by Wei Dai + +// TODO: Figure out what is happening in ProcessData. The issue surfaced for +// CFB_CipherTemplate::ProcessData when we cut-in Cryptogams +// AES ARMv7 asm. Then again in AdditiveCipherTemplate::ProcessData +// for CTR mode with HIGHT, which is a 64-bit block cipher. In both cases, +// inString == outString leads to incorrect results. We think it relates to +// aliasing violations because inString == outString. +// +// Also see https://github.com/weidai11/cryptopp/issues/683 and +// https://github.com/weidai11/cryptopp/issues/1010. + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "strciphr.h" + +// Squash MS LNK4221 and libtool warnings +#ifndef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +extern const char STRCIPHER_FNAME[] = __FILE__; +#endif + +NAMESPACE_BEGIN(CryptoPP) + +template +void AdditiveCipherTemplate::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + PolicyInterface &policy = this->AccessPolicy(); + policy.CipherSetKey(params, key, length); + m_leftOver = 0; + unsigned int bufferByteSize = policy.CanOperateKeystream() ? GetBufferByteSize(policy) : RoundUpToMultipleOf(1024U, GetBufferByteSize(policy)); + m_buffer.New(bufferByteSize); + + if (this->IsResynchronizable()) + { + size_t ivLength; + const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength); + policy.CipherResynchronize(m_buffer, iv, ivLength); + } +} + +template +void AdditiveCipherTemplate::GenerateBlock(byte *outString, size_t length) +{ + if (m_leftOver > 0) + { + const size_t len = STDMIN(m_leftOver, length); + std::memcpy(outString, PtrSub(KeystreamBufferEnd(), m_leftOver), len); + + length -= len; m_leftOver -= len; + outString = PtrAdd(outString, len); + if (!length) {return;} + } + + PolicyInterface &policy = this->AccessPolicy(); + unsigned int bytesPerIteration = policy.GetBytesPerIteration(); + + if (length >= bytesPerIteration) + { + const size_t iterations = length / bytesPerIteration; + policy.WriteKeystream(outString, iterations); + length -= iterations * bytesPerIteration; + outString = PtrAdd(outString, iterations * bytesPerIteration); + } + + if (length > 0) + { + size_t bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration); + size_t bufferIterations = bufferByteSize / bytesPerIteration; + + policy.WriteKeystream(PtrSub(KeystreamBufferEnd(), bufferByteSize), bufferIterations); + std::memcpy(outString, PtrSub(KeystreamBufferEnd(), bufferByteSize), length); + m_leftOver = bufferByteSize - length; + } +} + +template +void AdditiveCipherTemplate::ProcessData(byte *outString, const byte *inString, size_t length) +{ + CRYPTOPP_ASSERT(outString); CRYPTOPP_ASSERT(inString); + CRYPTOPP_ASSERT(length % this->MandatoryBlockSize() == 0); + + PolicyInterface &policy = this->AccessPolicy(); + unsigned int bytesPerIteration = policy.GetBytesPerIteration(); + + // GCC and Clang do not like this for CTR mode and 64-bit ciphers like HIGHT. + // The incorrect result is a partial string of 0's instead of plaintext or + // ciphertext. Recovered plaintext is partially garbage. + // + // It almost feels as if the compiler does not see the string is transformed + // in-place so it short-circuits the transform. In this case, if we use a + // stand-alone reproducer with the same data then the issue is present. + + byte* savedOutString = outString; + size_t savedLength = length; + bool copyOut = false; + + if (inString == outString) + { + // No need to copy inString to outString. + // Just allocate the space. + m_tempOutString.New(length); + m_tempOutString.SetMark(0); + outString = m_tempOutString.BytePtr(); + copyOut = true; + } + + if (m_leftOver > 0) + { + const size_t len = STDMIN(m_leftOver, length); + xorbuf(outString, inString, PtrSub(KeystreamBufferEnd(), m_leftOver), len); + + inString = PtrAdd(inString, len); + outString = PtrAdd(outString, len); + length -= len; m_leftOver -= len; + } + + if (!length) { + if (copyOut) + std::memcpy(savedOutString, m_tempOutString.BytePtr(), savedLength); + return; + } + + const unsigned int alignment = policy.GetAlignment(); + const bool inAligned = IsAlignedOn(inString, alignment); + const bool outAligned = IsAlignedOn(outString, alignment); + CRYPTOPP_UNUSED(inAligned); CRYPTOPP_UNUSED(outAligned); + + if (policy.CanOperateKeystream() && length >= bytesPerIteration) + { + const size_t iterations = length / bytesPerIteration; + KeystreamOperationFlags flags = static_cast( + (inAligned ? EnumToInt(INPUT_ALIGNED) : 0) | (outAligned ? EnumToInt(OUTPUT_ALIGNED) : 0)); + KeystreamOperation operation = KeystreamOperation(flags); + policy.OperateKeystream(operation, outString, inString, iterations); + + inString = PtrAdd(inString, iterations * bytesPerIteration); + outString = PtrAdd(outString, iterations * bytesPerIteration); + length -= iterations * bytesPerIteration; + } + + size_t bufferByteSize = m_buffer.size(); + size_t bufferIterations = bufferByteSize / bytesPerIteration; + + while (length >= bufferByteSize) + { + policy.WriteKeystream(m_buffer, bufferIterations); + xorbuf(outString, inString, KeystreamBufferBegin(), bufferByteSize); + + inString = PtrAdd(inString, bufferByteSize); + outString = PtrAdd(outString, bufferByteSize); + length -= bufferByteSize; + } + + if (length > 0) + { + bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration); + bufferIterations = bufferByteSize / bytesPerIteration; + + policy.WriteKeystream(PtrSub(KeystreamBufferEnd(), bufferByteSize), bufferIterations); + xorbuf(outString, inString, PtrSub(KeystreamBufferEnd(), bufferByteSize), length); + + m_leftOver = bufferByteSize - length; + } + + if (copyOut) + std::memcpy(savedOutString, m_tempOutString.BytePtr(), savedLength); +} + +template +void AdditiveCipherTemplate::Resynchronize(const byte *iv, int length) +{ + PolicyInterface &policy = this->AccessPolicy(); + m_leftOver = 0; + m_buffer.New(GetBufferByteSize(policy)); + policy.CipherResynchronize(m_buffer, iv, this->ThrowIfInvalidIVLength(length)); +} + +template +void AdditiveCipherTemplate::Seek(lword position) +{ + PolicyInterface &policy = this->AccessPolicy(); + unsigned int bytesPerIteration = policy.GetBytesPerIteration(); + + policy.SeekToIteration(position / bytesPerIteration); + position %= bytesPerIteration; + + if (position > 0) + { + policy.WriteKeystream(PtrSub(KeystreamBufferEnd(), bytesPerIteration), 1); + m_leftOver = bytesPerIteration - static_cast(position); + } + else + m_leftOver = 0; +} + +template +void CFB_CipherTemplate::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + PolicyInterface &policy = this->AccessPolicy(); + policy.CipherSetKey(params, key, length); + + if (this->IsResynchronizable()) + { + size_t ivLength; + const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength); + policy.CipherResynchronize(iv, ivLength); + } + + m_leftOver = policy.GetBytesPerIteration(); +} + +template +void CFB_CipherTemplate::Resynchronize(const byte *iv, int length) +{ + PolicyInterface &policy = this->AccessPolicy(); + policy.CipherResynchronize(iv, this->ThrowIfInvalidIVLength(length)); + m_leftOver = policy.GetBytesPerIteration(); +} + +template +void CFB_CipherTemplate::ProcessData(byte *outString, const byte *inString, size_t length) +{ + CRYPTOPP_ASSERT(outString); CRYPTOPP_ASSERT(inString); + CRYPTOPP_ASSERT(length % this->MandatoryBlockSize() == 0); + + PolicyInterface &policy = this->AccessPolicy(); + unsigned int bytesPerIteration = policy.GetBytesPerIteration(); + byte *reg = policy.GetRegisterBegin(); + + // GCC and Clang do not like this on ARM when inString == outString. The incorrect + // result is a string of 0's instead of plaintext or ciphertext. The 0's trace back + // to the allocation for the std::string in datatest.cpp. Elements in the string + // are initialized to their default value, which is 0. + // + // It almost feels as if the compiler does not see the string is transformed + // in-place so it short-circuits the transform. However, if we use a stand-alone + // reproducer with the same data then the issue is _not_ present. + + byte* savedOutString = outString; + size_t savedLength = length; + bool copyOut = false; + + if (inString == outString) + { + // No need to copy inString to outString. + // Just allocate the space. + m_tempOutString.New(length); + m_tempOutString.SetMark(0); + outString = m_tempOutString.BytePtr(); + copyOut = true; + } + + if (m_leftOver) + { + const size_t len = STDMIN(m_leftOver, length); + CombineMessageAndShiftRegister(outString, PtrAdd(reg, bytesPerIteration - m_leftOver), inString, len); + + inString = PtrAdd(inString, len); + outString = PtrAdd(outString, len); + m_leftOver -= len; length -= len; + } + + if (!length) { + if (copyOut) + std::memcpy(savedOutString, m_tempOutString.BytePtr(), savedLength); + return; + } + + const unsigned int alignment = policy.GetAlignment(); + const bool inAligned = IsAlignedOn(inString, alignment); + const bool outAligned = IsAlignedOn(outString, alignment); + CRYPTOPP_UNUSED(inAligned); CRYPTOPP_UNUSED(outAligned); + + if (policy.CanIterate() && length >= bytesPerIteration && outAligned) + { + CipherDir cipherDir = GetCipherDir(*this); + policy.Iterate(outString, inString, cipherDir, length / bytesPerIteration); + + const size_t remainder = length % bytesPerIteration; + inString = PtrAdd(inString, length - remainder); + outString = PtrAdd(outString, length - remainder); + length = remainder; + } + + while (length >= bytesPerIteration) + { + policy.TransformRegister(); + CombineMessageAndShiftRegister(outString, reg, inString, bytesPerIteration); + + inString = PtrAdd(inString, bytesPerIteration); + outString = PtrAdd(outString, bytesPerIteration); + length -= bytesPerIteration; + } + + if (length > 0) + { + policy.TransformRegister(); + CombineMessageAndShiftRegister(outString, reg, inString, length); + m_leftOver = bytesPerIteration - length; + } + + if (copyOut) + std::memcpy(savedOutString, m_tempOutString.BytePtr(), savedLength); +} + +template +void CFB_EncryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) +{ + xorbuf(reg, message, length); + std::memcpy(output, reg, length); +} + +template +void CFB_DecryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) +{ + for (size_t i=0; i +/// 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 Wirte the keystream to the output buffer, input is NULL + WRITE_KEYSTREAM = INPUT_NULL, + /// \brief Wirte 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);
+	/// 
+ 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()));} + + // m_tempOutString added due to GH #1010 + AlignedSecByteBlock m_buffer, m_tempOutString; + size_t m_leftOver; +}; + +/// \brief Policy object for feeback 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);
+	/// 
+ 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); + + // m_tempOutString added due to GH #1010 + AlignedSecByteBlock m_tempOutString; + 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/external/ours/library/crypto/src/shared/original/tea.cpp b/external/ours/library/crypto/src/shared/original/tea.cpp new file mode 100755 index 000000000..32708c935 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/tea.cpp @@ -0,0 +1,165 @@ +// tea.cpp - modified by Wei Dai from code in the original paper + +#include "pch.h" +#include "tea.h" +#include "misc.h" + +// http://github.com/weidai11/cryptopp/issues/503 +#if defined(__xlC__) || defined(__SUNPRO_CC) +# define MAYBE_VOLATILE(x) (*const_cast(&x)) +#else +# define MAYBE_VOLATILE(x) (x) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +static const word32 DELTA = 0x9e3779b9; +typedef BlockGetAndPut Block; + +#define UINT32_CAST(x) ((word32*)(void*)(x)) +#define CONST_UINT32_CAST(x) ((const word32*)(const void*)(x)) + +void TEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms) +{ + AssertValidKeyLength(length); + + GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, userKey, KEYLENGTH); + m_limit = GetRoundsAndThrowIfInvalid(params, this) * DELTA; +} + +void TEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 y, z, sum = 0; + Block::Get(inBlock)(y)(z); + + // http://github.com/weidai11/cryptopp/issues/503 + while (MAYBE_VOLATILE(sum) != m_limit) + { + sum += DELTA; + y += ((z << 4) + m_k[0]) ^ (z + sum) ^ ((z >> 5) + m_k[1]); + z += ((y << 4) + m_k[2]) ^ (y + sum) ^ ((y >> 5) + m_k[3]); + } + + Block::Put(xorBlock, outBlock)(y)(z); +} + +void TEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 y, z, sum = m_limit; + Block::Get(inBlock)(y)(z); + + // http://github.com/weidai11/cryptopp/issues/503 + while (MAYBE_VOLATILE(sum) != 0) + { + z -= ((y << 4) + m_k[2]) ^ (y + sum) ^ ((y >> 5) + m_k[3]); + y -= ((z << 4) + m_k[0]) ^ (z + sum) ^ ((z >> 5) + m_k[1]); + sum -= DELTA; + } + + Block::Put(xorBlock, outBlock)(y)(z); +} + +void XTEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms) +{ + AssertValidKeyLength(length); + + GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, userKey, KEYLENGTH); + m_limit = GetRoundsAndThrowIfInvalid(params, this) * DELTA; +} + +void XTEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 y, z, sum = 0; + Block::Get(inBlock)(y)(z); + + // http://github.com/weidai11/cryptopp/issues/503 + while (MAYBE_VOLATILE(sum) != m_limit) + { + y += ((z<<4 ^ z>>5) + z) ^ (sum + m_k[sum&3]); + sum += DELTA; + z += ((y<<4 ^ y>>5) + y) ^ (sum + m_k[sum>>11 & 3]); + } + + Block::Put(xorBlock, outBlock)(y)(z); +} + +void XTEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 y, z, sum = m_limit; + Block::Get(inBlock)(y)(z); + + // http://github.com/weidai11/cryptopp/issues/503 + while (MAYBE_VOLATILE(sum) != 0) + { + z -= ((y<<4 ^ y>>5) + y) ^ (sum + m_k[sum>>11 & 3]); + sum -= DELTA; + y -= ((z<<4 ^ z>>5) + z) ^ (sum + m_k[sum&3]); + } + + Block::Put(xorBlock, outBlock)(y)(z); +} + +#define MX ((z>>5^y<<2)+(y>>3^z<<4))^((sum^y)+(m_k[(p&3)^e]^z)) + +void BTEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + CRYPTOPP_UNUSED(xorBlock); + CRYPTOPP_ASSERT(IsAlignedOn(inBlock,GetAlignmentOf())); + CRYPTOPP_ASSERT(IsAlignedOn(outBlock,GetAlignmentOf())); + + unsigned int n = m_blockSize / 4; + word32 *v = UINT32_CAST(outBlock); + ConditionalByteReverse(BIG_ENDIAN_ORDER, v, CONST_UINT32_CAST(inBlock), m_blockSize); + + word32 y, z = v[n-1], e; + word32 p, q = 6+52/n; + word32 sum = 0; + + while (q-- > 0) + { + sum += DELTA; + e = sum>>2 & 3; + for (p = 0; p < n-1; p++) + { + y = v[p+1]; + z = v[p] += MX; + } + y = v[0]; + z = v[n-1] += MX; + } + + ConditionalByteReverse(BIG_ENDIAN_ORDER, v, v, m_blockSize); +} + +void BTEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + CRYPTOPP_UNUSED(xorBlock); + CRYPTOPP_ASSERT(IsAlignedOn(inBlock,GetAlignmentOf())); + CRYPTOPP_ASSERT(IsAlignedOn(outBlock,GetAlignmentOf())); + + unsigned int n = m_blockSize / 4; + word32 *v = UINT32_CAST(outBlock); + ConditionalByteReverse(BIG_ENDIAN_ORDER, v, CONST_UINT32_CAST(inBlock), m_blockSize); + + word32 y = v[0], z, e; + word32 p, q = 6+52/n; + word32 sum = q * DELTA; + + while (sum != 0) + { + e = sum>>2 & 3; + for (p = n-1; p > 0; p--) + { + z = v[p-1]; + y = v[p] -= MX; + } + + z = v[n-1]; + y = v[0] -= MX; + sum -= DELTA; + } + + ConditionalByteReverse(BIG_ENDIAN_ORDER, v, v, m_blockSize); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/tea.h b/external/ours/library/crypto/src/shared/original/tea.h new file mode 100755 index 000000000..ef671dac8 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/test.cpp b/external/ours/library/crypto/src/shared/original/test.cpp new file mode 100755 index 000000000..3665dc094 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/test.cpp @@ -0,0 +1,1095 @@ +// test.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017 +// scoped_main added to CryptoPP::Test namespace by JW in July 2017 +// Also see http://github.com/weidai11/cryptopp/issues/447 + +#define CRYPTOPP_DEFAULT_NO_DLL +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "dll.h" +#include "cryptlib.h" +#include "aes.h" +#include "filters.h" +#include "md5.h" +#include "ripemd.h" +#include "rng.h" +#include "gzip.h" +#include "default.h" +#include "randpool.h" +#include "ida.h" +#include "base64.h" +#include "factory.h" +#include "whrlpool.h" +#include "tiger.h" +#include "smartptr.h" +#include "pkcspad.h" +#include "stdcpp.h" +#include "osrng.h" +#include "ossig.h" +#include "trap.h" + +#include "validate.h" +#include "bench.h" + +#include +#include +#include +#include +#include + +#ifdef CRYPTOPP_WIN32_AVAILABLE +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_BSD_AVAILABLE) +#include +#include +#include +#define UNIX_PATH_FAMILY 1 +#endif + +#if defined(CRYPTOPP_OSX_AVAILABLE) +#include +#include +#include +#include +#define UNIX_PATH_FAMILY 1 +#endif + +#if (_MSC_VER >= 1000) +#include // for the debug heap +#endif + +#if defined(__MWERKS__) && defined(macintosh) +#include +#endif + +#ifdef _OPENMP +# include +#endif + +#ifdef __BORLANDC__ +#pragma comment(lib, "cryptlib_bds.lib") +#endif + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +// If CRYPTOPP_USE_AES_GENERATOR is 1 then AES/OFB based is used. +// Otherwise the OS random number generator is used. +#define CRYPTOPP_USE_AES_GENERATOR 1 + +// Global namespace, provided by other source files +void FIPS140_SampleApplication(); +void RegisterFactories(CryptoPP::Test::TestClass suites); +int (*AdhocTest)(int argc, char *argv[]) = NULLPTR; + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +const int MAX_PHRASE_LENGTH = 250; +const int GLOBAL_SEED_LENGTH = 16; +std::string g_argvPathHint=""; + +void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed); +std::string RSAEncryptString(const char *pubFilename, const char *seed, const char *message); +std::string RSADecryptString(const char *privFilename, const char *ciphertext); +void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename); +bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename); + +void DigestFile(const char *file); +void HmacFile(const char *hexKey, const char *file); + +void AES_CTR_Encrypt(const char *hexKey, const char *hexIV, const char *infile, const char *outfile); + +std::string EncryptString(const char *plaintext, const char *passPhrase); +std::string DecryptString(const char *ciphertext, const char *passPhrase); + +void EncryptFile(const char *in, const char *out, const char *passPhrase); +void DecryptFile(const char *in, const char *out, const char *passPhrase); + +void SecretShareFile(int threshold, int nShares, const char *filename, const char *seed); +void SecretRecoverFile(int threshold, const char *outFilename, char *const *inFilenames); + +void InformationDisperseFile(int threshold, int nShares, const char *filename); +void InformationRecoverFile(int threshold, const char *outFilename, char *const *inFilenames); + +void GzipFile(const char *in, const char *out, int deflate_level); +void GunzipFile(const char *in, const char *out); + +void Base64Encode(const char *infile, const char *outfile); +void Base64Decode(const char *infile, const char *outfile); +void HexEncode(const char *infile, const char *outfile); +void HexDecode(const char *infile, const char *outfile); + +void FIPS140_GenerateRandomFiles(); + +bool Validate(int, bool); +bool SetGlobalSeed(int argc, char* argv[], std::string& seed); +void SetArgvPathHint(const char* argv0, std::string& pathHint); + +ANONYMOUS_NAMESPACE_BEGIN +#if (CRYPTOPP_USE_AES_GENERATOR) +OFB_Mode::Encryption s_globalRNG; +#else +NonblockingRng s_globalRNG; +#endif +NAMESPACE_END + +RandomNumberGenerator & GlobalRNG() +{ + return dynamic_cast(s_globalRNG); +} + +// Global seed used for the self tests +std::string s_globalSeed; +void PrintSeedAndThreads(); + +// See misc.h and trap.h for comments and usage +#if defined(CRYPTOPP_DEBUG) && defined(UNIX_SIGNALS_AVAILABLE) +static const SignalHandler s_dummyHandler; +// static const DebugTrapHandler s_dummyHandler; +#endif + +int scoped_main(int argc, char *argv[]) +{ +#ifdef _CRTDBG_LEAK_CHECK_DF + // Turn on leak-checking + int tempflag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); + tempflag |= _CRTDBG_LEAK_CHECK_DF; + _CrtSetDbgFlag( tempflag ); +#endif + +#ifdef _SUNPRO_CC + // No need for thread safety for the test program + cout.set_safe_flag(stream_MT::unsafe_object); + cin.set_safe_flag(stream_MT::unsafe_object); +#endif + + try + { + RegisterFactories(All); + + // A hint to help locate TestData/ and TestVectors/ after install. + SetArgvPathHint(argv[0], g_argvPathHint); + + // Set a seed for reproducible results. If the seed is too short then + // it is padded with spaces. If the seed is missing then time() is used. + // For example: + // ./cryptest.exe v seed=abcdefg + SetGlobalSeed(argc, argv, s_globalSeed); + +#if (CRYPTOPP_USE_AES_GENERATOR) + // Fetch the SymmetricCipher interface, not the RandomNumberGenerator + // interface, to key the underlying cipher. If CRYPTOPP_USE_AES_GENERATOR is 1 + // then AES/OFB based is used. Otherwise the OS random number generator is used. + SymmetricCipher& cipher = dynamic_cast(GlobalRNG()); + cipher.SetKeyWithIV((byte *)s_globalSeed.data(), s_globalSeed.size(), (byte *)s_globalSeed.data()); +#endif + + std::string command, executableName, macFilename; + + if (argc < 2) + command = 'h'; + else + command = argv[1]; + + if (command == "g") + { + char thisSeed[1024], privFilename[128], pubFilename[128]; + unsigned int keyLength; + + std::cout << "Key length in bits: "; + std::cin >> keyLength; + + std::cout << "\nSave private key to file: "; + std::cin >> privFilename; + + std::cout << "\nSave public key to file: "; + std::cin >> pubFilename; + + std::cout << "\nRandom Seed: "; + std::ws(std::cin); + std::cin.getline(thisSeed, 1024); + + GenerateRSAKey(keyLength, privFilename, pubFilename, thisSeed); + } + else if (command == "rs") + RSASignFile(argv[2], argv[3], argv[4]); + else if (command == "rv") + { + bool verified = RSAVerifyFile(argv[2], argv[3], argv[4]); + std::cout << (verified ? "valid signature" : "invalid signature") << std::endl; + } + else if (command == "r") + { + char privFilename[128], pubFilename[128]; + char thisSeed[1024], message[1024]; + + std::cout << "Private key file: "; + std::cin >> privFilename; + + std::cout << "\nPublic key file: "; + std::cin >> pubFilename; + + std::cout << "\nRandom Seed: "; + std::ws(std::cin); + std::cin.getline(thisSeed, 1024); + + std::cout << "\nMessage: "; + std::cin.getline(message, 1024); + + std::string ciphertext = RSAEncryptString(pubFilename, thisSeed, message); + std::cout << "\nCiphertext: " << ciphertext << std::endl; + + std::string decrypted = RSADecryptString(privFilename, ciphertext.c_str()); + std::cout << "\nDecrypted: " << decrypted << std::endl; + } + else if (command == "mt") + { + MaurerRandomnessTest mt; + FileStore fs(argv[2]); + fs.TransferAllTo(mt); + std::cout << "Maurer Test Value: " << mt.GetTestValue() << std::endl; + } + else if (command == "mac_dll") + { + std::string fname(argv[2] ? argv[2] : ""); + + // sanity check on file size + std::fstream dllFile(fname.c_str(), std::ios::in | std::ios::out | std::ios::binary); + if (!dllFile.good()) + { + std::cerr << "Failed to open file \"" << fname << "\"\n"; + return 1; + } + + std::ifstream::pos_type fileEnd = dllFile.seekg(0, std::ios_base::end).tellg(); + if (fileEnd > 20*1000*1000) + { + std::cerr << "Input file " << fname << " is too large"; + std::cerr << "(size is " << fileEnd << ").\n"; + return 1; + } + + // read file into memory + unsigned int fileSize = (unsigned int)fileEnd; + SecByteBlock buf(fileSize); + dllFile.seekg(0, std::ios_base::beg); + dllFile.read((char *)buf.begin(), fileSize); + + // find positions of relevant sections in the file, based on version 8 of documentation from http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx + word32 coffPos = *(word16 *)(void *)(buf+0x3c); + word32 optionalHeaderPos = coffPos + 24; + word16 optionalHeaderMagic = *(word16 *)(void *)(buf+optionalHeaderPos); + if (optionalHeaderMagic != 0x10b && optionalHeaderMagic != 0x20b) + { + std::cerr << "Target file is not a PE32 or PE32+ image.\n"; + return 3; + } + word32 checksumPos = optionalHeaderPos + 64; + word32 certificateTableDirectoryPos = optionalHeaderPos + (optionalHeaderMagic == 0x10b ? 128 : 144); + word32 certificateTablePos = *(word32 *)(void *)(buf+certificateTableDirectoryPos); + word32 certificateTableSize = *(word32 *)(void *)(buf+certificateTableDirectoryPos+4); + if (certificateTableSize != 0) + std::cerr << "Warning: certificate table (IMAGE_DIRECTORY_ENTRY_SECURITY) of target image is not empty.\n"; + + // find where to place computed MAC + byte mac[] = CRYPTOPP_DUMMY_DLL_MAC; + byte *found = std::search(buf.begin(), buf.end(), mac+0, mac+sizeof(mac)); + if (found == buf.end()) + { + std::cerr << "MAC placeholder not found. The MAC may already be placed.\n"; + return 2; + } + word32 macPos = (unsigned int)(found-buf.begin()); + + // compute MAC + member_ptr pMac(NewIntegrityCheckingMAC()); + CRYPTOPP_ASSERT(pMac->DigestSize() == sizeof(mac)); + MeterFilter f(new HashFilter(*pMac, new ArraySink(mac, sizeof(mac)))); + f.AddRangeToSkip(0, checksumPos, 4); + f.AddRangeToSkip(0, certificateTableDirectoryPos, 8); + f.AddRangeToSkip(0, macPos, sizeof(mac)); + f.AddRangeToSkip(0, certificateTablePos, certificateTableSize); + f.PutMessageEnd(buf.begin(), buf.size()); + + // Encode MAC + std::string hexMac; + HexEncoder encoder; + encoder.Put(mac, sizeof(mac)), encoder.MessageEnd(); + hexMac.resize(static_cast(encoder.MaxRetrievable())); + encoder.Get(reinterpret_cast(&hexMac[0]), hexMac.size()); + + // Report MAC and location + std::cout << "Placing MAC " << hexMac << " in " << fname << " at file offset " << macPos; + std::cout << " (0x" << std::hex << macPos << std::dec << ").\n"; + + // place MAC + dllFile.seekg(macPos, std::ios_base::beg); + dllFile.write((char *)mac, sizeof(mac)); + } + else if (command == "m") + DigestFile(argv[2]); + else if (command == "tv") + { + // TestDataFile() adds CRYPTOPP_DATA_DIR as required + std::string fname = (argv[2] ? argv[2] : "all"); + if (fname.find(".txt") == std::string::npos) + fname += ".txt"; + if (fname.find("TestVectors") == std::string::npos) + fname = "TestVectors/" + fname; + + PrintSeedAndThreads(); + return !RunTestDataFile(fname.c_str()); + } + else if (command == "t") + { + // VC60 workaround: use char array instead of std::string to workaround MSVC's getline bug + char passPhrase[MAX_PHRASE_LENGTH], plaintext[1024]; + + std::cout << "Passphrase: "; + std::cin.getline(passPhrase, MAX_PHRASE_LENGTH); + + std::cout << "\nPlaintext: "; + std::cin.getline(plaintext, sizeof(plaintext)); + + std::string ciphertext = EncryptString(plaintext, passPhrase); + std::cout << "\nCiphertext: " << ciphertext << std::endl; + + std::string decrypted = DecryptString(ciphertext.c_str(), passPhrase); + std::cout << "\nDecrypted: " << decrypted << std::endl; + + return 0; + } + else if (command == "e64") + Base64Encode(argv[2], argv[3]); + else if (command == "d64") + Base64Decode(argv[2], argv[3]); + else if (command == "e16") + HexEncode(argv[2], argv[3]); + else if (command == "d16") + HexDecode(argv[2], argv[3]); + else if (command == "e" || command == "d") + { + char passPhrase[MAX_PHRASE_LENGTH]; + std::cout << "Passphrase: "; + std::cin.getline(passPhrase, MAX_PHRASE_LENGTH); + if (command == "e") + EncryptFile(argv[2], argv[3], passPhrase); + else + DecryptFile(argv[2], argv[3], passPhrase); + } + else if (command == "ss") + { + char thisSeed[1024]; + std::cout << "\nRandom Seed: "; + std::ws(std::cin); + std::cin.getline(thisSeed, sizeof(thisSeed)); + SecretShareFile(StringToValue(argv[2]), StringToValue(argv[3]), argv[4], thisSeed); + } + else if (command == "sr") + SecretRecoverFile(argc-3, argv[2], argv+3); + else if (command == "id") + InformationDisperseFile(StringToValue(argv[2]), StringToValue(argv[3]), argv[4]); + else if (command == "ir") + InformationRecoverFile(argc-3, argv[2], argv+3); + else if (command == "v" || command == "vv") + return !Validate(argc>2 ? StringToValue(argv[2]) : 0, argv[1][1] == 'v'); + else if (command.substr(0,1) == "b") // "b", "b1", "b2", ... + BenchmarkWithCommand(argc, argv); + else if (command == "z") + GzipFile(argv[3], argv[4], argv[2][0]-'0'); + else if (command == "u") + GunzipFile(argv[2], argv[3]); + else if (command == "fips") + FIPS140_SampleApplication(); + else if (command == "fips-rand") + FIPS140_GenerateRandomFiles(); + else if (command == "a") + { + if (AdhocTest) + return (*AdhocTest)(argc, argv); + else + { + std::cerr << "AdhocTest not defined.\n"; + return 1; + } + } + else if (command == "hmac") + HmacFile(argv[2], argv[3]); + else if (command == "ae") + AES_CTR_Encrypt(argv[2], argv[3], argv[4], argv[5]); + else if (command == "h") + { + FileSource usage(DataDir("TestData/usage.dat").c_str(), true, new FileSink(std::cout)); + return 1; + } + else if (command == "V") + { + std::cout << CRYPTOPP_VERSION / 100 << '.' << (CRYPTOPP_VERSION % 100) / 10 << '.' << CRYPTOPP_VERSION % 10 << std::endl; + } + else + { + std::cerr << "Unrecognized command. Run \"cryptest h\" to obtain usage information.\n"; + return 1; + } + return 0; + } + catch(const Exception &e) + { + std::cout << "\nException caught: " << e.what() << std::endl; + return -1; + } + catch(const std::exception &e) + { + std::cout << "\nstd::exception caught: " << e.what() << std::endl; + return -2; + } +} // main() + +bool SetGlobalSeed(int argc, char* argv[], std::string& seed) +{ + bool ret = false; + + for (int i=0; i::Signer priv(privFile); + FileSource f(messageFilename, true, new SignerFilter(GlobalRNG(), priv, new HexEncoder(new FileSink(signatureFilename)))); +} + +bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename) +{ + FileSource pubFile(pubFilename, true, new HexDecoder); + RSASS::Verifier pub(pubFile); + + FileSource signatureFile(signatureFilename, true, new HexDecoder); + if (signatureFile.MaxRetrievable() != pub.SignatureLength()) + return false; + SecByteBlock signature(pub.SignatureLength()); + signatureFile.Get(signature, signature.size()); + + SignatureVerificationFilter *verifierFilter = new SignatureVerificationFilter(pub); + verifierFilter->Put(signature, pub.SignatureLength()); + FileSource f(messageFilename, true, verifierFilter); + + return verifierFilter->GetLastResult(); +} + +void DigestFile(const char *filename) +{ + SHA1 sha; + RIPEMD160 ripemd; + SHA256 sha256; + Tiger tiger; + SHA512 sha512; + Whirlpool whirlpool; + + vector_member_ptrs filters(6); + filters[0].reset(new HashFilter(sha)); + filters[1].reset(new HashFilter(ripemd)); + filters[2].reset(new HashFilter(tiger)); + filters[3].reset(new HashFilter(sha256)); + filters[4].reset(new HashFilter(sha512)); + filters[5].reset(new HashFilter(whirlpool)); + + member_ptr channelSwitch(new ChannelSwitch); + size_t i; + for (i=0; iAddDefaultRoute(*filters[i]); + FileSource(filename, true, channelSwitch.release()); + + HexEncoder encoder(new FileSink(std::cout), false); + for (i=0; iAlgorithmName() << ": "; + filters[i]->TransferTo(encoder); + std::cout << "\n"; + } +} + +void HmacFile(const char *hexKey, const char *file) +{ + member_ptr mac; + if (strcmp(hexKey, "selftest") == 0) + { + std::cerr << "Computing HMAC/SHA1 value for self test.\n"; + mac.reset(NewIntegrityCheckingMAC()); + } + else + { + std::string decodedKey; + StringSource(hexKey, true, new HexDecoder(new StringSink(decodedKey))); + mac.reset(new HMAC((const byte *)decodedKey.data(), decodedKey.size())); + } + FileSource(file, true, new HashFilter(*mac, new HexEncoder(new FileSink(std::cout)))); +} + +void AES_CTR_Encrypt(const char *hexKey, const char *hexIV, const char *infile, const char *outfile) +{ + SecByteBlock key = HexDecodeString(hexKey); + SecByteBlock iv = HexDecodeString(hexIV); + CTR_Mode::Encryption aes(key, key.size(), iv); + FileSource(infile, true, new StreamTransformationFilter(aes, new FileSink(outfile))); +} + +std::string EncryptString(const char *instr, const char *passPhrase) +{ + std::string outstr; + + DefaultEncryptorWithMAC encryptor(passPhrase, new HexEncoder(new StringSink(outstr))); + encryptor.Put((byte *)instr, strlen(instr)); + encryptor.MessageEnd(); + + return outstr; +} + +std::string DecryptString(const char *instr, const char *passPhrase) +{ + std::string outstr; + + HexDecoder decryptor(new DefaultDecryptorWithMAC(passPhrase, new StringSink(outstr))); + decryptor.Put((byte *)instr, strlen(instr)); + decryptor.MessageEnd(); + + return outstr; +} + +void EncryptFile(const char *in, const char *out, const char *passPhrase) +{ + FileSource f(in, true, new DefaultEncryptorWithMAC(passPhrase, new FileSink(out))); +} + +void DecryptFile(const char *in, const char *out, const char *passPhrase) +{ + FileSource f(in, true, new DefaultDecryptorWithMAC(passPhrase, new FileSink(out))); +} + +void SecretShareFile(int threshold, int nShares, const char *filename, const char *seed) +{ + CRYPTOPP_ASSERT(nShares >= 1 && nShares<=1000); + if (nShares < 1 || nShares > 1000) + throw InvalidArgument("SecretShareFile: " + IntToString(nShares) + " is not in range [1, 1000]"); + + RandomPool rng; + rng.IncorporateEntropy((byte *)seed, strlen(seed)); + + ChannelSwitch *channelSwitch = NULLPTR; + FileSource source(filename, false, new SecretSharing(rng, threshold, nShares, channelSwitch = new ChannelSwitch)); + + // Be careful of the type of Sink used. An ArraySink will stop writing data once the array + // is full. Also see http://groups.google.com/forum/#!topic/cryptopp-users/XEKKLCEFH3Y. + vector_member_ptrs fileSinks(nShares); + std::string channel; + for (int i=0; i(i); + fileSinks[i]->Put((const byte *)channel.data(), 4); + channelSwitch->AddRoute(channel, *fileSinks[i], DEFAULT_CHANNEL); + } + + source.PumpAll(); +} + +void SecretRecoverFile(int threshold, const char *outFilename, char *const *inFilenames) +{ + CRYPTOPP_ASSERT(threshold >= 1 && threshold <=1000); + if (threshold < 1 || threshold > 1000) + throw InvalidArgument("SecretRecoverFile: " + IntToString(threshold) + " is not in range [1, 1000]"); + + SecretRecovery recovery(threshold, new FileSink(outFilename)); + + vector_member_ptrs fileSources(threshold); + SecByteBlock channel(4); + int i; + for (i=0; iPump(4); + fileSources[i]->Get(channel, 4); + fileSources[i]->Attach(new ChannelSwitch(recovery, std::string((char *)channel.begin(), 4))); + } + + while (fileSources[0]->Pump(256)) + for (i=1; iPump(256); + + for (i=0; iPumpAll(); +} + +void InformationDisperseFile(int threshold, int nShares, const char *filename) +{ + CRYPTOPP_ASSERT(threshold >= 1 && threshold <=1000); + if (threshold < 1 || threshold > 1000) + throw InvalidArgument("InformationDisperseFile: " + IntToString(nShares) + " is not in range [1, 1000]"); + + ChannelSwitch *channelSwitch = NULLPTR; + FileSource source(filename, false, new InformationDispersal(threshold, nShares, channelSwitch = new ChannelSwitch)); + + // Be careful of the type of Sink used. An ArraySink will stop writing data once the array + // is full. Also see http://groups.google.com/forum/#!topic/cryptopp-users/XEKKLCEFH3Y. + vector_member_ptrs fileSinks(nShares); + std::string channel; + for (int i=0; i(i); + fileSinks[i]->Put((const byte *)channel.data(), 4); + channelSwitch->AddRoute(channel, *fileSinks[i], DEFAULT_CHANNEL); + } + + source.PumpAll(); +} + +void InformationRecoverFile(int threshold, const char *outFilename, char *const *inFilenames) +{ + CRYPTOPP_ASSERT(threshold<=1000); + if (threshold < 1 || threshold > 1000) + throw InvalidArgument("InformationRecoverFile: " + IntToString(threshold) + " is not in range [1, 1000]"); + + InformationRecovery recovery(threshold, new FileSink(outFilename)); + + vector_member_ptrs fileSources(threshold); + SecByteBlock channel(4); + int i; + for (i=0; iPump(4); + fileSources[i]->Get(channel, 4); + fileSources[i]->Attach(new ChannelSwitch(recovery, std::string((char *)channel.begin(), 4))); + } + + while (fileSources[0]->Pump(256)) + for (i=1; iPump(256); + + for (i=0; iPumpAll(); +} + +void GzipFile(const char *in, const char *out, int deflate_level) +{ +// FileSource(in, true, new Gzip(new FileSink(out), deflate_level)); + + // use a filter graph to compare decompressed data with original + // + // Source ----> Gzip ------> Sink + // \ | + // \ Gunzip + // \ | + // \ v + // > ComparisonFilter + + EqualityComparisonFilter comparison; + + Gunzip gunzip(new ChannelSwitch(comparison, "0")); + gunzip.SetAutoSignalPropagation(0); + + FileSink sink(out); + + ChannelSwitch *cs; + Gzip gzip(cs = new ChannelSwitch(sink), deflate_level); + cs->AddDefaultRoute(gunzip); + + cs = new ChannelSwitch(gzip); + cs->AddDefaultRoute(comparison, "1"); + FileSource source(in, true, cs); + + comparison.ChannelMessageSeriesEnd("0"); + comparison.ChannelMessageSeriesEnd("1"); +} + +void GunzipFile(const char *in, const char *out) +{ + FileSource(in, true, new Gunzip(new FileSink(out))); +} + +void Base64Encode(const char *in, const char *out) +{ + FileSource(in, true, new Base64Encoder(new FileSink(out))); +} + +void Base64Decode(const char *in, const char *out) +{ + FileSource(in, true, new Base64Decoder(new FileSink(out))); +} + +void HexEncode(const char *in, const char *out) +{ + FileSource(in, true, new HexEncoder(new FileSink(out))); +} + +void HexDecode(const char *in, const char *out) +{ + FileSource(in, true, new HexDecoder(new FileSink(out))); +} + +bool Validate(int alg, bool thorough) +{ + bool result; + + g_testBegin = ::time(NULLPTR); + PrintSeedAndThreads(); + + // TODO: we need to group these tests like benchmarks... + switch (alg) + { + case 0: result = ValidateAll(thorough); break; + case 1: result = TestSettings(); break; + case 2: result = TestOS_RNG(); break; +// case 3: result = TestSecRandom(); break; + case 4: result = ValidateMD5(); break; + case 5: result = ValidateSHA(); break; + case 6: result = ValidateDES(); break; + case 7: result = ValidateIDEA(); break; + case 8: result = ValidateARC4(); break; + case 9: result = ValidateRC5(); break; + case 10: result = ValidateBlowfish(); break; +// case 11: result = ValidateDiamond2(); break; + case 12: result = ValidateThreeWay(); break; + case 13: result = ValidateBBS(); break; + case 14: result = ValidateDH(); break; + case 15: result = ValidateX25519(); break; + case 16: result = ValidateRSA(); break; + case 17: result = ValidateElGamal(); break; + case 18: result = ValidateDSA(thorough); break; +// case 18: result = ValidateHAVAL(); break; + case 19: result = ValidateSAFER(); break; + case 20: result = ValidateLUC(); break; + case 21: result = ValidateRabin(); break; +// case 22: result = ValidateBlumGoldwasser(); break; + case 23: result = ValidateECP(); break; + case 24: result = ValidateEC2N(); break; +// case 25: result = ValidateMD5MAC(); break; + case 26: result = ValidateGOST(); break; + case 27: result = ValidateTiger(); break; + case 28: result = ValidateRIPEMD(); break; + case 29: result = ValidateHMAC(); break; +// case 30: result = ValidateXMACC(); break; + case 31: result = ValidateSHARK(); break; + case 32: result = ValidateLUC_DH(); break; + case 33: result = ValidateLUC_DL(); break; + case 34: result = ValidateSEAL(); break; + case 35: result = ValidateCAST(); break; + case 36: result = ValidateSquare(); break; + case 37: result = ValidateRC2(); break; + case 38: result = ValidateRC6(); break; + case 39: result = ValidateMARS(); break; + case 40: result = ValidateRW(); break; + case 41: result = ValidateMD2(); break; + case 42: result = ValidateNR(); break; + case 43: result = ValidateMQV(); break; + case 44: result = ValidateRijndael(); break; + case 45: result = ValidateTwofish(); break; + case 46: result = ValidateSerpent(); break; + case 47: result = ValidateCipherModes(); break; + case 48: result = ValidateCRC32(); break; + case 49: result = ValidateCRC32C(); break; + case 50: result = ValidateECDSA(); break; + case 51: result = ValidateECGDSA(thorough); break; + case 52: result = ValidateXTR_DH(); break; + case 53: result = ValidateSKIPJACK(); break; + case 54: result = ValidateSHA2(); break; + case 55: result = ValidatePanama(); break; + case 56: result = ValidateAdler32(); break; + case 57: result = ValidateMD4(); break; + case 58: result = ValidatePBKDF(); break; + case 59: result = ValidateHKDF(); break; + case 60: result = ValidateScrypt(); break; + case 61: result = ValidateESIGN(); break; + case 62: result = ValidateDLIES(); break; + case 63: result = ValidateBaseCode(); break; + case 64: result = ValidateSHACAL2(); break; + case 65: result = ValidateARIA(); break; + case 66: result = ValidateCamellia(); break; + case 67: result = ValidateWhirlpool(); break; + case 68: result = ValidateLSH(); break; + case 69: result = ValidateTTMAC(); break; + case 70: result = ValidateSalsa(); break; + case 71: result = ValidateChaCha(); break; + case 72: result = ValidateChaChaTLS(); break; + case 73: result = ValidateSosemanuk(); break; + case 74: result = ValidateRabbit(); break; + case 75: result = ValidateHC128(); break; + case 76: result = ValidateHC256(); break; + case 80: result = ValidateVMAC(); break; + case 81: result = ValidateCCM(); break; + case 82: result = ValidateGCM(); break; + case 83: result = ValidateXTS(); break; + case 84: result = ValidateCMAC(); break; + case 85: result = ValidateSM3(); break; + case 86: result = ValidateBLAKE2s(); break; + case 87: result = ValidateBLAKE2b(); break; + case 88: result = ValidatePoly1305(); break; + case 89: result = ValidateSipHash(); break; + case 90: result = ValidateHashDRBG(); break; + case 91: result = ValidateHmacDRBG(); break; + case 92: result = ValidateNaCl(); break; + + case 100: result = ValidateCHAM(); break; + case 101: result = ValidateSIMECK(); break; + case 102: result = ValidateSIMON(); break; + case 103: result = ValidateSPECK(); break; + + case 110: result = ValidateSHA3(); break; + case 111: result = ValidateSHAKE(); break; + case 112: result = ValidateSHAKE_XOF(); break; + + case 120: result = ValidateMQV(); break; + case 121: result = ValidateHMQV(); break; + case 122: result = ValidateFHMQV(); break; + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) + // http://github.com/weidai11/cryptopp/issues/92 + case 9999: result = TestSecBlock(); break; + // http://github.com/weidai11/cryptopp/issues/64 + case 9998: result = TestPolynomialMod2(); break; + // http://github.com/weidai11/cryptopp/issues/336 + case 9997: result = TestIntegerBitops(); break; + // http://github.com/weidai11/cryptopp/issues/602 + case 9996: result = TestIntegerOps(); break; + // http://github.com/weidai11/cryptopp/issues/360 + case 9995: result = TestRounding(); break; + // http://github.com/weidai11/cryptopp/issues/242 + case 9994: result = TestHuffmanCodes(); break; + // http://github.com/weidai11/cryptopp/issues/346 + case 9993: result = TestASN1Parse(); break; + case 9992: result = TestASN1Functions(); break; + // http://github.com/weidai11/cryptopp/issues/242 + case 9991: result = TestX25519(); break; + // http://github.com/weidai11/cryptopp/issues/346 + case 9990: result = TestEd25519(); break; +# if defined(CRYPTOPP_ALTIVEC_AVAILABLE) + case 9989: result = TestAltivecOps(); break; +# endif +#endif + + default: return false; + } + + g_testEnd = ::time(NULLPTR); + + std::cout << "\nSeed used was " << s_globalSeed; + std::cout << "\nTest started at " << TimeToString(g_testBegin); + std::cout << "\nTest ended at " << TimeToString(g_testEnd) << std::endl; + + return result; +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP + +// Microsoft puts a byte in global namespace. Combined with +// a 'using namespace CryptoPP', it causes compile failures. +// Also see http://github.com/weidai11/cryptopp/issues/442 +// and http://github.com/weidai11/cryptopp/issues/447. +int CRYPTOPP_API main(int argc, char *argv[]) +{ + return CryptoPP::Test::scoped_main(argc, argv); +} diff --git a/external/ours/library/crypto/src/shared/original/tftables.cpp b/external/ours/library/crypto/src/shared/original/tftables.cpp index 22fde97c5..00bb6bac8 100755 --- a/external/ours/library/crypto/src/shared/original/tftables.cpp +++ b/external/ours/library/crypto/src/shared/original/tftables.cpp @@ -1,317 +1,323 @@ -// Twofish tables - -#include "FirstCrypto.h" -#include "twofish.h" - -NAMESPACE_BEGIN(CryptoPP) - -const byte Twofish::q[2][256] = { - 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, - 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, - 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, - 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, - 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, - 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, - 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, - 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, - 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, - 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, - 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, - 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, - 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, - 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, - 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, - 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, - 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, - 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, - 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, - 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, - 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, - 0x4A, 0x5E, 0xC1, 0xE0, - - 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, - 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, - 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, - 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, - 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, - 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, - 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, - 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, - 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, - 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, - 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, - 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, - 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, - 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, - 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, - 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, - 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, - 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, - 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, - 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, - 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, - 0x55, 0x09, 0xBE, 0x91 -}; - -const word32 Twofish::mds[4][256] = { - 0xbcbc3275, 0xecec21f3, 0x202043c6, 0xb3b3c9f4, - 0xdada03db, 0x02028b7b, 0xe2e22bfb, 0x9e9efac8, - 0xc9c9ec4a, 0xd4d409d3, 0x18186be6, 0x1e1e9f6b, - 0x98980e45, 0xb2b2387d, 0xa6a6d2e8, 0x2626b74b, - 0x3c3c57d6, 0x93938a32, 0x8282eed8, 0x525298fd, - 0x7b7bd437, 0xbbbb3771, 0x5b5b97f1, 0x474783e1, - 0x24243c30, 0x5151e20f, 0xbabac6f8, 0x4a4af31b, - 0xbfbf4887, 0x0d0d70fa, 0xb0b0b306, 0x7575de3f, - 0xd2d2fd5e, 0x7d7d20ba, 0x666631ae, 0x3a3aa35b, - 0x59591c8a, 0x00000000, 0xcdcd93bc, 0x1a1ae09d, - 0xaeae2c6d, 0x7f7fabc1, 0x2b2bc7b1, 0xbebeb90e, - 0xe0e0a080, 0x8a8a105d, 0x3b3b52d2, 0x6464bad5, - 0xd8d888a0, 0xe7e7a584, 0x5f5fe807, 0x1b1b1114, - 0x2c2cc2b5, 0xfcfcb490, 0x3131272c, 0x808065a3, - 0x73732ab2, 0x0c0c8173, 0x79795f4c, 0x6b6b4154, - 0x4b4b0292, 0x53536974, 0x94948f36, 0x83831f51, - 0x2a2a3638, 0xc4c49cb0, 0x2222c8bd, 0xd5d5f85a, - 0xbdbdc3fc, 0x48487860, 0xffffce62, 0x4c4c0796, - 0x4141776c, 0xc7c7e642, 0xebeb24f7, 0x1c1c1410, - 0x5d5d637c, 0x36362228, 0x6767c027, 0xe9e9af8c, - 0x4444f913, 0x1414ea95, 0xf5f5bb9c, 0xcfcf18c7, - 0x3f3f2d24, 0xc0c0e346, 0x7272db3b, 0x54546c70, - 0x29294cca, 0xf0f035e3, 0x0808fe85, 0xc6c617cb, - 0xf3f34f11, 0x8c8ce4d0, 0xa4a45993, 0xcaca96b8, - 0x68683ba6, 0xb8b84d83, 0x38382820, 0xe5e52eff, - 0xadad569f, 0x0b0b8477, 0xc8c81dc3, 0x9999ffcc, - 0x5858ed03, 0x19199a6f, 0x0e0e0a08, 0x95957ebf, - 0x70705040, 0xf7f730e7, 0x6e6ecf2b, 0x1f1f6ee2, - 0xb5b53d79, 0x09090f0c, 0x616134aa, 0x57571682, - 0x9f9f0b41, 0x9d9d803a, 0x111164ea, 0x2525cdb9, - 0xafafdde4, 0x4545089a, 0xdfdf8da4, 0xa3a35c97, - 0xeaead57e, 0x353558da, 0xededd07a, 0x4343fc17, - 0xf8f8cb66, 0xfbfbb194, 0x3737d3a1, 0xfafa401d, - 0xc2c2683d, 0xb4b4ccf0, 0x32325dde, 0x9c9c71b3, - 0x5656e70b, 0xe3e3da72, 0x878760a7, 0x15151b1c, - 0xf9f93aef, 0x6363bfd1, 0x3434a953, 0x9a9a853e, - 0xb1b1428f, 0x7c7cd133, 0x88889b26, 0x3d3da65f, - 0xa1a1d7ec, 0xe4e4df76, 0x8181942a, 0x91910149, - 0x0f0ffb81, 0xeeeeaa88, 0x161661ee, 0xd7d77321, - 0x9797f5c4, 0xa5a5a81a, 0xfefe3feb, 0x6d6db5d9, - 0x7878aec5, 0xc5c56d39, 0x1d1de599, 0x7676a4cd, - 0x3e3edcad, 0xcbcb6731, 0xb6b6478b, 0xefef5b01, - 0x12121e18, 0x6060c523, 0x6a6ab0dd, 0x4d4df61f, - 0xcecee94e, 0xdede7c2d, 0x55559df9, 0x7e7e5a48, - 0x2121b24f, 0x03037af2, 0xa0a02665, 0x5e5e198e, - 0x5a5a6678, 0x65654b5c, 0x62624e58, 0xfdfd4519, - 0x0606f48d, 0x404086e5, 0xf2f2be98, 0x3333ac57, - 0x17179067, 0x05058e7f, 0xe8e85e05, 0x4f4f7d64, - 0x89896aaf, 0x10109563, 0x74742fb6, 0x0a0a75fe, - 0x5c5c92f5, 0x9b9b74b7, 0x2d2d333c, 0x3030d6a5, - 0x2e2e49ce, 0x494989e9, 0x46467268, 0x77775544, - 0xa8a8d8e0, 0x9696044d, 0x2828bd43, 0xa9a92969, - 0xd9d97929, 0x8686912e, 0xd1d187ac, 0xf4f44a15, - 0x8d8d1559, 0xd6d682a8, 0xb9b9bc0a, 0x42420d9e, - 0xf6f6c16e, 0x2f2fb847, 0xdddd06df, 0x23233934, - 0xcccc6235, 0xf1f1c46a, 0xc1c112cf, 0x8585ebdc, - 0x8f8f9e22, 0x7171a1c9, 0x9090f0c0, 0xaaaa539b, - 0x0101f189, 0x8b8be1d4, 0x4e4e8ced, 0x8e8e6fab, - 0xababa212, 0x6f6f3ea2, 0xe6e6540d, 0xdbdbf252, - 0x92927bbb, 0xb7b7b602, 0x6969ca2f, 0x3939d9a9, - 0xd3d30cd7, 0xa7a72361, 0xa2a2ad1e, 0xc3c399b4, - 0x6c6c4450, 0x07070504, 0x04047ff6, 0x272746c2, - 0xacaca716, 0xd0d07625, 0x50501386, 0xdcdcf756, - 0x84841a55, 0xe1e15109, 0x7a7a25be, 0x1313ef91, - - 0xa9d93939, 0x67901717, 0xb3719c9c, 0xe8d2a6a6, - 0x04050707, 0xfd985252, 0xa3658080, 0x76dfe4e4, - 0x9a084545, 0x92024b4b, 0x80a0e0e0, 0x78665a5a, - 0xe4ddafaf, 0xddb06a6a, 0xd1bf6363, 0x38362a2a, - 0x0d54e6e6, 0xc6432020, 0x3562cccc, 0x98bef2f2, - 0x181e1212, 0xf724ebeb, 0xecd7a1a1, 0x6c774141, - 0x43bd2828, 0x7532bcbc, 0x37d47b7b, 0x269b8888, - 0xfa700d0d, 0x13f94444, 0x94b1fbfb, 0x485a7e7e, - 0xf27a0303, 0xd0e48c8c, 0x8b47b6b6, 0x303c2424, - 0x84a5e7e7, 0x54416b6b, 0xdf06dddd, 0x23c56060, - 0x1945fdfd, 0x5ba33a3a, 0x3d68c2c2, 0x59158d8d, - 0xf321ecec, 0xae316666, 0xa23e6f6f, 0x82165757, - 0x63951010, 0x015befef, 0x834db8b8, 0x2e918686, - 0xd9b56d6d, 0x511f8383, 0x9b53aaaa, 0x7c635d5d, - 0xa63b6868, 0xeb3ffefe, 0xa5d63030, 0xbe257a7a, - 0x16a7acac, 0x0c0f0909, 0xe335f0f0, 0x6123a7a7, - 0xc0f09090, 0x8cafe9e9, 0x3a809d9d, 0xf5925c5c, - 0x73810c0c, 0x2c273131, 0x2576d0d0, 0x0be75656, - 0xbb7b9292, 0x4ee9cece, 0x89f10101, 0x6b9f1e1e, - 0x53a93434, 0x6ac4f1f1, 0xb499c3c3, 0xf1975b5b, - 0xe1834747, 0xe66b1818, 0xbdc82222, 0x450e9898, - 0xe26e1f1f, 0xf4c9b3b3, 0xb62f7474, 0x66cbf8f8, - 0xccff9999, 0x95ea1414, 0x03ed5858, 0x56f7dcdc, - 0xd4e18b8b, 0x1c1b1515, 0x1eada2a2, 0xd70cd3d3, - 0xfb2be2e2, 0xc31dc8c8, 0x8e195e5e, 0xb5c22c2c, - 0xe9894949, 0xcf12c1c1, 0xbf7e9595, 0xba207d7d, - 0xea641111, 0x77840b0b, 0x396dc5c5, 0xaf6a8989, - 0x33d17c7c, 0xc9a17171, 0x62ceffff, 0x7137bbbb, - 0x81fb0f0f, 0x793db5b5, 0x0951e1e1, 0xaddc3e3e, - 0x242d3f3f, 0xcda47676, 0xf99d5555, 0xd8ee8282, - 0xe5864040, 0xc5ae7878, 0xb9cd2525, 0x4d049696, - 0x44557777, 0x080a0e0e, 0x86135050, 0xe730f7f7, - 0xa1d33737, 0x1d40fafa, 0xaa346161, 0xed8c4e4e, - 0x06b3b0b0, 0x706c5454, 0xb22a7373, 0xd2523b3b, - 0x410b9f9f, 0x7b8b0202, 0xa088d8d8, 0x114ff3f3, - 0x3167cbcb, 0xc2462727, 0x27c06767, 0x90b4fcfc, - 0x20283838, 0xf67f0404, 0x60784848, 0xff2ee5e5, - 0x96074c4c, 0x5c4b6565, 0xb1c72b2b, 0xab6f8e8e, - 0x9e0d4242, 0x9cbbf5f5, 0x52f2dbdb, 0x1bf34a4a, - 0x5fa63d3d, 0x9359a4a4, 0x0abcb9b9, 0xef3af9f9, - 0x91ef1313, 0x85fe0808, 0x49019191, 0xee611616, - 0x2d7cdede, 0x4fb22121, 0x8f42b1b1, 0x3bdb7272, - 0x47b82f2f, 0x8748bfbf, 0x6d2caeae, 0x46e3c0c0, - 0xd6573c3c, 0x3e859a9a, 0x6929a9a9, 0x647d4f4f, - 0x2a948181, 0xce492e2e, 0xcb17c6c6, 0x2fca6969, - 0xfcc3bdbd, 0x975ca3a3, 0x055ee8e8, 0x7ad0eded, - 0xac87d1d1, 0x7f8e0505, 0xd5ba6464, 0x1aa8a5a5, - 0x4bb72626, 0x0eb9bebe, 0xa7608787, 0x5af8d5d5, - 0x28223636, 0x14111b1b, 0x3fde7575, 0x2979d9d9, - 0x88aaeeee, 0x3c332d2d, 0x4c5f7979, 0x02b6b7b7, - 0xb896caca, 0xda583535, 0xb09cc4c4, 0x17fc4343, - 0x551a8484, 0x1ff64d4d, 0x8a1c5959, 0x7d38b2b2, - 0x57ac3333, 0xc718cfcf, 0x8df40606, 0x74695353, - 0xb7749b9b, 0xc4f59797, 0x9f56adad, 0x72dae3e3, - 0x7ed5eaea, 0x154af4f4, 0x229e8f8f, 0x12a2abab, - 0x584e6262, 0x07e85f5f, 0x99e51d1d, 0x34392323, - 0x6ec1f6f6, 0x50446c6c, 0xde5d3232, 0x68724646, - 0x6526a0a0, 0xbc93cdcd, 0xdb03dada, 0xf8c6baba, - 0xc8fa9e9e, 0xa882d6d6, 0x2bcf6e6e, 0x40507070, - 0xdceb8585, 0xfe750a0a, 0x328a9393, 0xa48ddfdf, - 0xca4c2929, 0x10141c1c, 0x2173d7d7, 0xf0ccb4b4, - 0xd309d4d4, 0x5d108a8a, 0x0fe25151, 0x00000000, - 0x6f9a1919, 0x9de01a1a, 0x368f9494, 0x42e6c7c7, - 0x4aecc9c9, 0x5efdd2d2, 0xc1ab7f7f, 0xe0d8a8a8, - - 0xbc75bc32, 0xecf3ec21, 0x20c62043, 0xb3f4b3c9, - 0xdadbda03, 0x027b028b, 0xe2fbe22b, 0x9ec89efa, - 0xc94ac9ec, 0xd4d3d409, 0x18e6186b, 0x1e6b1e9f, - 0x9845980e, 0xb27db238, 0xa6e8a6d2, 0x264b26b7, - 0x3cd63c57, 0x9332938a, 0x82d882ee, 0x52fd5298, - 0x7b377bd4, 0xbb71bb37, 0x5bf15b97, 0x47e14783, - 0x2430243c, 0x510f51e2, 0xbaf8bac6, 0x4a1b4af3, - 0xbf87bf48, 0x0dfa0d70, 0xb006b0b3, 0x753f75de, - 0xd25ed2fd, 0x7dba7d20, 0x66ae6631, 0x3a5b3aa3, - 0x598a591c, 0x00000000, 0xcdbccd93, 0x1a9d1ae0, - 0xae6dae2c, 0x7fc17fab, 0x2bb12bc7, 0xbe0ebeb9, - 0xe080e0a0, 0x8a5d8a10, 0x3bd23b52, 0x64d564ba, - 0xd8a0d888, 0xe784e7a5, 0x5f075fe8, 0x1b141b11, - 0x2cb52cc2, 0xfc90fcb4, 0x312c3127, 0x80a38065, - 0x73b2732a, 0x0c730c81, 0x794c795f, 0x6b546b41, - 0x4b924b02, 0x53745369, 0x9436948f, 0x8351831f, - 0x2a382a36, 0xc4b0c49c, 0x22bd22c8, 0xd55ad5f8, - 0xbdfcbdc3, 0x48604878, 0xff62ffce, 0x4c964c07, - 0x416c4177, 0xc742c7e6, 0xebf7eb24, 0x1c101c14, - 0x5d7c5d63, 0x36283622, 0x672767c0, 0xe98ce9af, - 0x441344f9, 0x149514ea, 0xf59cf5bb, 0xcfc7cf18, - 0x3f243f2d, 0xc046c0e3, 0x723b72db, 0x5470546c, - 0x29ca294c, 0xf0e3f035, 0x088508fe, 0xc6cbc617, - 0xf311f34f, 0x8cd08ce4, 0xa493a459, 0xcab8ca96, - 0x68a6683b, 0xb883b84d, 0x38203828, 0xe5ffe52e, - 0xad9fad56, 0x0b770b84, 0xc8c3c81d, 0x99cc99ff, - 0x580358ed, 0x196f199a, 0x0e080e0a, 0x95bf957e, - 0x70407050, 0xf7e7f730, 0x6e2b6ecf, 0x1fe21f6e, - 0xb579b53d, 0x090c090f, 0x61aa6134, 0x57825716, - 0x9f419f0b, 0x9d3a9d80, 0x11ea1164, 0x25b925cd, - 0xafe4afdd, 0x459a4508, 0xdfa4df8d, 0xa397a35c, - 0xea7eead5, 0x35da3558, 0xed7aedd0, 0x431743fc, - 0xf866f8cb, 0xfb94fbb1, 0x37a137d3, 0xfa1dfa40, - 0xc23dc268, 0xb4f0b4cc, 0x32de325d, 0x9cb39c71, - 0x560b56e7, 0xe372e3da, 0x87a78760, 0x151c151b, - 0xf9eff93a, 0x63d163bf, 0x345334a9, 0x9a3e9a85, - 0xb18fb142, 0x7c337cd1, 0x8826889b, 0x3d5f3da6, - 0xa1eca1d7, 0xe476e4df, 0x812a8194, 0x91499101, - 0x0f810ffb, 0xee88eeaa, 0x16ee1661, 0xd721d773, - 0x97c497f5, 0xa51aa5a8, 0xfeebfe3f, 0x6dd96db5, - 0x78c578ae, 0xc539c56d, 0x1d991de5, 0x76cd76a4, - 0x3ead3edc, 0xcb31cb67, 0xb68bb647, 0xef01ef5b, - 0x1218121e, 0x602360c5, 0x6add6ab0, 0x4d1f4df6, - 0xce4ecee9, 0xde2dde7c, 0x55f9559d, 0x7e487e5a, - 0x214f21b2, 0x03f2037a, 0xa065a026, 0x5e8e5e19, - 0x5a785a66, 0x655c654b, 0x6258624e, 0xfd19fd45, - 0x068d06f4, 0x40e54086, 0xf298f2be, 0x335733ac, - 0x17671790, 0x057f058e, 0xe805e85e, 0x4f644f7d, - 0x89af896a, 0x10631095, 0x74b6742f, 0x0afe0a75, - 0x5cf55c92, 0x9bb79b74, 0x2d3c2d33, 0x30a530d6, - 0x2ece2e49, 0x49e94989, 0x46684672, 0x77447755, - 0xa8e0a8d8, 0x964d9604, 0x284328bd, 0xa969a929, - 0xd929d979, 0x862e8691, 0xd1acd187, 0xf415f44a, - 0x8d598d15, 0xd6a8d682, 0xb90ab9bc, 0x429e420d, - 0xf66ef6c1, 0x2f472fb8, 0xdddfdd06, 0x23342339, - 0xcc35cc62, 0xf16af1c4, 0xc1cfc112, 0x85dc85eb, - 0x8f228f9e, 0x71c971a1, 0x90c090f0, 0xaa9baa53, - 0x018901f1, 0x8bd48be1, 0x4eed4e8c, 0x8eab8e6f, - 0xab12aba2, 0x6fa26f3e, 0xe60de654, 0xdb52dbf2, - 0x92bb927b, 0xb702b7b6, 0x692f69ca, 0x39a939d9, - 0xd3d7d30c, 0xa761a723, 0xa21ea2ad, 0xc3b4c399, - 0x6c506c44, 0x07040705, 0x04f6047f, 0x27c22746, - 0xac16aca7, 0xd025d076, 0x50865013, 0xdc56dcf7, - 0x8455841a, 0xe109e151, 0x7abe7a25, 0x139113ef, - - 0xd939a9d9, 0x90176790, 0x719cb371, 0xd2a6e8d2, - 0x05070405, 0x9852fd98, 0x6580a365, 0xdfe476df, - 0x08459a08, 0x024b9202, 0xa0e080a0, 0x665a7866, - 0xddafe4dd, 0xb06addb0, 0xbf63d1bf, 0x362a3836, - 0x54e60d54, 0x4320c643, 0x62cc3562, 0xbef298be, - 0x1e12181e, 0x24ebf724, 0xd7a1ecd7, 0x77416c77, - 0xbd2843bd, 0x32bc7532, 0xd47b37d4, 0x9b88269b, - 0x700dfa70, 0xf94413f9, 0xb1fb94b1, 0x5a7e485a, - 0x7a03f27a, 0xe48cd0e4, 0x47b68b47, 0x3c24303c, - 0xa5e784a5, 0x416b5441, 0x06dddf06, 0xc56023c5, - 0x45fd1945, 0xa33a5ba3, 0x68c23d68, 0x158d5915, - 0x21ecf321, 0x3166ae31, 0x3e6fa23e, 0x16578216, - 0x95106395, 0x5bef015b, 0x4db8834d, 0x91862e91, - 0xb56dd9b5, 0x1f83511f, 0x53aa9b53, 0x635d7c63, - 0x3b68a63b, 0x3ffeeb3f, 0xd630a5d6, 0x257abe25, - 0xa7ac16a7, 0x0f090c0f, 0x35f0e335, 0x23a76123, - 0xf090c0f0, 0xafe98caf, 0x809d3a80, 0x925cf592, - 0x810c7381, 0x27312c27, 0x76d02576, 0xe7560be7, - 0x7b92bb7b, 0xe9ce4ee9, 0xf10189f1, 0x9f1e6b9f, - 0xa93453a9, 0xc4f16ac4, 0x99c3b499, 0x975bf197, - 0x8347e183, 0x6b18e66b, 0xc822bdc8, 0x0e98450e, - 0x6e1fe26e, 0xc9b3f4c9, 0x2f74b62f, 0xcbf866cb, - 0xff99ccff, 0xea1495ea, 0xed5803ed, 0xf7dc56f7, - 0xe18bd4e1, 0x1b151c1b, 0xada21ead, 0x0cd3d70c, - 0x2be2fb2b, 0x1dc8c31d, 0x195e8e19, 0xc22cb5c2, - 0x8949e989, 0x12c1cf12, 0x7e95bf7e, 0x207dba20, - 0x6411ea64, 0x840b7784, 0x6dc5396d, 0x6a89af6a, - 0xd17c33d1, 0xa171c9a1, 0xceff62ce, 0x37bb7137, - 0xfb0f81fb, 0x3db5793d, 0x51e10951, 0xdc3eaddc, - 0x2d3f242d, 0xa476cda4, 0x9d55f99d, 0xee82d8ee, - 0x8640e586, 0xae78c5ae, 0xcd25b9cd, 0x04964d04, - 0x55774455, 0x0a0e080a, 0x13508613, 0x30f7e730, - 0xd337a1d3, 0x40fa1d40, 0x3461aa34, 0x8c4eed8c, - 0xb3b006b3, 0x6c54706c, 0x2a73b22a, 0x523bd252, - 0x0b9f410b, 0x8b027b8b, 0x88d8a088, 0x4ff3114f, - 0x67cb3167, 0x4627c246, 0xc06727c0, 0xb4fc90b4, - 0x28382028, 0x7f04f67f, 0x78486078, 0x2ee5ff2e, - 0x074c9607, 0x4b655c4b, 0xc72bb1c7, 0x6f8eab6f, - 0x0d429e0d, 0xbbf59cbb, 0xf2db52f2, 0xf34a1bf3, - 0xa63d5fa6, 0x59a49359, 0xbcb90abc, 0x3af9ef3a, - 0xef1391ef, 0xfe0885fe, 0x01914901, 0x6116ee61, - 0x7cde2d7c, 0xb2214fb2, 0x42b18f42, 0xdb723bdb, - 0xb82f47b8, 0x48bf8748, 0x2cae6d2c, 0xe3c046e3, - 0x573cd657, 0x859a3e85, 0x29a96929, 0x7d4f647d, - 0x94812a94, 0x492ece49, 0x17c6cb17, 0xca692fca, - 0xc3bdfcc3, 0x5ca3975c, 0x5ee8055e, 0xd0ed7ad0, - 0x87d1ac87, 0x8e057f8e, 0xba64d5ba, 0xa8a51aa8, - 0xb7264bb7, 0xb9be0eb9, 0x6087a760, 0xf8d55af8, - 0x22362822, 0x111b1411, 0xde753fde, 0x79d92979, - 0xaaee88aa, 0x332d3c33, 0x5f794c5f, 0xb6b702b6, - 0x96cab896, 0x5835da58, 0x9cc4b09c, 0xfc4317fc, - 0x1a84551a, 0xf64d1ff6, 0x1c598a1c, 0x38b27d38, - 0xac3357ac, 0x18cfc718, 0xf4068df4, 0x69537469, - 0x749bb774, 0xf597c4f5, 0x56ad9f56, 0xdae372da, - 0xd5ea7ed5, 0x4af4154a, 0x9e8f229e, 0xa2ab12a2, - 0x4e62584e, 0xe85f07e8, 0xe51d99e5, 0x39233439, - 0xc1f66ec1, 0x446c5044, 0x5d32de5d, 0x72466872, - 0x26a06526, 0x93cdbc93, 0x03dadb03, 0xc6baf8c6, - 0xfa9ec8fa, 0x82d6a882, 0xcf6e2bcf, 0x50704050, - 0xeb85dceb, 0x750afe75, 0x8a93328a, 0x8ddfa48d, - 0x4c29ca4c, 0x141c1014, 0x73d72173, 0xccb4f0cc, - 0x09d4d309, 0x108a5d10, 0xe2510fe2, 0x00000000, - 0x9a196f9a, 0xe01a9de0, 0x8f94368f, 0xe6c742e6, - 0xecc94aec, 0xfdd25efd, 0xab7fc1ab, 0xd8a8e0d8}; - -NAMESPACE_END +// Twofish tables + +#include "pch.h" +#include "config.h" + +#include "twofish.h" + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wmissing-braces" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +const byte Twofish::Base::q[2][256] = { + 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, + 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, + 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, + 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, + 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, + 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, + 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, + 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, + 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, + 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, + 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, + 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, + 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, + 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, + 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, + 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, + 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, + 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, + 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, + 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, + 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, + 0x4A, 0x5E, 0xC1, 0xE0, + + 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, + 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, + 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, + 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, + 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, + 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, + 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, + 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, + 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, + 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, + 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, + 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, + 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, + 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, + 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, + 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, + 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, + 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, + 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, + 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, + 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, + 0x55, 0x09, 0xBE, 0x91 +}; + +const word32 Twofish::Base::mds[4][256] = { + 0xbcbc3275, 0xecec21f3, 0x202043c6, 0xb3b3c9f4, + 0xdada03db, 0x02028b7b, 0xe2e22bfb, 0x9e9efac8, + 0xc9c9ec4a, 0xd4d409d3, 0x18186be6, 0x1e1e9f6b, + 0x98980e45, 0xb2b2387d, 0xa6a6d2e8, 0x2626b74b, + 0x3c3c57d6, 0x93938a32, 0x8282eed8, 0x525298fd, + 0x7b7bd437, 0xbbbb3771, 0x5b5b97f1, 0x474783e1, + 0x24243c30, 0x5151e20f, 0xbabac6f8, 0x4a4af31b, + 0xbfbf4887, 0x0d0d70fa, 0xb0b0b306, 0x7575de3f, + 0xd2d2fd5e, 0x7d7d20ba, 0x666631ae, 0x3a3aa35b, + 0x59591c8a, 0x00000000, 0xcdcd93bc, 0x1a1ae09d, + 0xaeae2c6d, 0x7f7fabc1, 0x2b2bc7b1, 0xbebeb90e, + 0xe0e0a080, 0x8a8a105d, 0x3b3b52d2, 0x6464bad5, + 0xd8d888a0, 0xe7e7a584, 0x5f5fe807, 0x1b1b1114, + 0x2c2cc2b5, 0xfcfcb490, 0x3131272c, 0x808065a3, + 0x73732ab2, 0x0c0c8173, 0x79795f4c, 0x6b6b4154, + 0x4b4b0292, 0x53536974, 0x94948f36, 0x83831f51, + 0x2a2a3638, 0xc4c49cb0, 0x2222c8bd, 0xd5d5f85a, + 0xbdbdc3fc, 0x48487860, 0xffffce62, 0x4c4c0796, + 0x4141776c, 0xc7c7e642, 0xebeb24f7, 0x1c1c1410, + 0x5d5d637c, 0x36362228, 0x6767c027, 0xe9e9af8c, + 0x4444f913, 0x1414ea95, 0xf5f5bb9c, 0xcfcf18c7, + 0x3f3f2d24, 0xc0c0e346, 0x7272db3b, 0x54546c70, + 0x29294cca, 0xf0f035e3, 0x0808fe85, 0xc6c617cb, + 0xf3f34f11, 0x8c8ce4d0, 0xa4a45993, 0xcaca96b8, + 0x68683ba6, 0xb8b84d83, 0x38382820, 0xe5e52eff, + 0xadad569f, 0x0b0b8477, 0xc8c81dc3, 0x9999ffcc, + 0x5858ed03, 0x19199a6f, 0x0e0e0a08, 0x95957ebf, + 0x70705040, 0xf7f730e7, 0x6e6ecf2b, 0x1f1f6ee2, + 0xb5b53d79, 0x09090f0c, 0x616134aa, 0x57571682, + 0x9f9f0b41, 0x9d9d803a, 0x111164ea, 0x2525cdb9, + 0xafafdde4, 0x4545089a, 0xdfdf8da4, 0xa3a35c97, + 0xeaead57e, 0x353558da, 0xededd07a, 0x4343fc17, + 0xf8f8cb66, 0xfbfbb194, 0x3737d3a1, 0xfafa401d, + 0xc2c2683d, 0xb4b4ccf0, 0x32325dde, 0x9c9c71b3, + 0x5656e70b, 0xe3e3da72, 0x878760a7, 0x15151b1c, + 0xf9f93aef, 0x6363bfd1, 0x3434a953, 0x9a9a853e, + 0xb1b1428f, 0x7c7cd133, 0x88889b26, 0x3d3da65f, + 0xa1a1d7ec, 0xe4e4df76, 0x8181942a, 0x91910149, + 0x0f0ffb81, 0xeeeeaa88, 0x161661ee, 0xd7d77321, + 0x9797f5c4, 0xa5a5a81a, 0xfefe3feb, 0x6d6db5d9, + 0x7878aec5, 0xc5c56d39, 0x1d1de599, 0x7676a4cd, + 0x3e3edcad, 0xcbcb6731, 0xb6b6478b, 0xefef5b01, + 0x12121e18, 0x6060c523, 0x6a6ab0dd, 0x4d4df61f, + 0xcecee94e, 0xdede7c2d, 0x55559df9, 0x7e7e5a48, + 0x2121b24f, 0x03037af2, 0xa0a02665, 0x5e5e198e, + 0x5a5a6678, 0x65654b5c, 0x62624e58, 0xfdfd4519, + 0x0606f48d, 0x404086e5, 0xf2f2be98, 0x3333ac57, + 0x17179067, 0x05058e7f, 0xe8e85e05, 0x4f4f7d64, + 0x89896aaf, 0x10109563, 0x74742fb6, 0x0a0a75fe, + 0x5c5c92f5, 0x9b9b74b7, 0x2d2d333c, 0x3030d6a5, + 0x2e2e49ce, 0x494989e9, 0x46467268, 0x77775544, + 0xa8a8d8e0, 0x9696044d, 0x2828bd43, 0xa9a92969, + 0xd9d97929, 0x8686912e, 0xd1d187ac, 0xf4f44a15, + 0x8d8d1559, 0xd6d682a8, 0xb9b9bc0a, 0x42420d9e, + 0xf6f6c16e, 0x2f2fb847, 0xdddd06df, 0x23233934, + 0xcccc6235, 0xf1f1c46a, 0xc1c112cf, 0x8585ebdc, + 0x8f8f9e22, 0x7171a1c9, 0x9090f0c0, 0xaaaa539b, + 0x0101f189, 0x8b8be1d4, 0x4e4e8ced, 0x8e8e6fab, + 0xababa212, 0x6f6f3ea2, 0xe6e6540d, 0xdbdbf252, + 0x92927bbb, 0xb7b7b602, 0x6969ca2f, 0x3939d9a9, + 0xd3d30cd7, 0xa7a72361, 0xa2a2ad1e, 0xc3c399b4, + 0x6c6c4450, 0x07070504, 0x04047ff6, 0x272746c2, + 0xacaca716, 0xd0d07625, 0x50501386, 0xdcdcf756, + 0x84841a55, 0xe1e15109, 0x7a7a25be, 0x1313ef91, + + 0xa9d93939, 0x67901717, 0xb3719c9c, 0xe8d2a6a6, + 0x04050707, 0xfd985252, 0xa3658080, 0x76dfe4e4, + 0x9a084545, 0x92024b4b, 0x80a0e0e0, 0x78665a5a, + 0xe4ddafaf, 0xddb06a6a, 0xd1bf6363, 0x38362a2a, + 0x0d54e6e6, 0xc6432020, 0x3562cccc, 0x98bef2f2, + 0x181e1212, 0xf724ebeb, 0xecd7a1a1, 0x6c774141, + 0x43bd2828, 0x7532bcbc, 0x37d47b7b, 0x269b8888, + 0xfa700d0d, 0x13f94444, 0x94b1fbfb, 0x485a7e7e, + 0xf27a0303, 0xd0e48c8c, 0x8b47b6b6, 0x303c2424, + 0x84a5e7e7, 0x54416b6b, 0xdf06dddd, 0x23c56060, + 0x1945fdfd, 0x5ba33a3a, 0x3d68c2c2, 0x59158d8d, + 0xf321ecec, 0xae316666, 0xa23e6f6f, 0x82165757, + 0x63951010, 0x015befef, 0x834db8b8, 0x2e918686, + 0xd9b56d6d, 0x511f8383, 0x9b53aaaa, 0x7c635d5d, + 0xa63b6868, 0xeb3ffefe, 0xa5d63030, 0xbe257a7a, + 0x16a7acac, 0x0c0f0909, 0xe335f0f0, 0x6123a7a7, + 0xc0f09090, 0x8cafe9e9, 0x3a809d9d, 0xf5925c5c, + 0x73810c0c, 0x2c273131, 0x2576d0d0, 0x0be75656, + 0xbb7b9292, 0x4ee9cece, 0x89f10101, 0x6b9f1e1e, + 0x53a93434, 0x6ac4f1f1, 0xb499c3c3, 0xf1975b5b, + 0xe1834747, 0xe66b1818, 0xbdc82222, 0x450e9898, + 0xe26e1f1f, 0xf4c9b3b3, 0xb62f7474, 0x66cbf8f8, + 0xccff9999, 0x95ea1414, 0x03ed5858, 0x56f7dcdc, + 0xd4e18b8b, 0x1c1b1515, 0x1eada2a2, 0xd70cd3d3, + 0xfb2be2e2, 0xc31dc8c8, 0x8e195e5e, 0xb5c22c2c, + 0xe9894949, 0xcf12c1c1, 0xbf7e9595, 0xba207d7d, + 0xea641111, 0x77840b0b, 0x396dc5c5, 0xaf6a8989, + 0x33d17c7c, 0xc9a17171, 0x62ceffff, 0x7137bbbb, + 0x81fb0f0f, 0x793db5b5, 0x0951e1e1, 0xaddc3e3e, + 0x242d3f3f, 0xcda47676, 0xf99d5555, 0xd8ee8282, + 0xe5864040, 0xc5ae7878, 0xb9cd2525, 0x4d049696, + 0x44557777, 0x080a0e0e, 0x86135050, 0xe730f7f7, + 0xa1d33737, 0x1d40fafa, 0xaa346161, 0xed8c4e4e, + 0x06b3b0b0, 0x706c5454, 0xb22a7373, 0xd2523b3b, + 0x410b9f9f, 0x7b8b0202, 0xa088d8d8, 0x114ff3f3, + 0x3167cbcb, 0xc2462727, 0x27c06767, 0x90b4fcfc, + 0x20283838, 0xf67f0404, 0x60784848, 0xff2ee5e5, + 0x96074c4c, 0x5c4b6565, 0xb1c72b2b, 0xab6f8e8e, + 0x9e0d4242, 0x9cbbf5f5, 0x52f2dbdb, 0x1bf34a4a, + 0x5fa63d3d, 0x9359a4a4, 0x0abcb9b9, 0xef3af9f9, + 0x91ef1313, 0x85fe0808, 0x49019191, 0xee611616, + 0x2d7cdede, 0x4fb22121, 0x8f42b1b1, 0x3bdb7272, + 0x47b82f2f, 0x8748bfbf, 0x6d2caeae, 0x46e3c0c0, + 0xd6573c3c, 0x3e859a9a, 0x6929a9a9, 0x647d4f4f, + 0x2a948181, 0xce492e2e, 0xcb17c6c6, 0x2fca6969, + 0xfcc3bdbd, 0x975ca3a3, 0x055ee8e8, 0x7ad0eded, + 0xac87d1d1, 0x7f8e0505, 0xd5ba6464, 0x1aa8a5a5, + 0x4bb72626, 0x0eb9bebe, 0xa7608787, 0x5af8d5d5, + 0x28223636, 0x14111b1b, 0x3fde7575, 0x2979d9d9, + 0x88aaeeee, 0x3c332d2d, 0x4c5f7979, 0x02b6b7b7, + 0xb896caca, 0xda583535, 0xb09cc4c4, 0x17fc4343, + 0x551a8484, 0x1ff64d4d, 0x8a1c5959, 0x7d38b2b2, + 0x57ac3333, 0xc718cfcf, 0x8df40606, 0x74695353, + 0xb7749b9b, 0xc4f59797, 0x9f56adad, 0x72dae3e3, + 0x7ed5eaea, 0x154af4f4, 0x229e8f8f, 0x12a2abab, + 0x584e6262, 0x07e85f5f, 0x99e51d1d, 0x34392323, + 0x6ec1f6f6, 0x50446c6c, 0xde5d3232, 0x68724646, + 0x6526a0a0, 0xbc93cdcd, 0xdb03dada, 0xf8c6baba, + 0xc8fa9e9e, 0xa882d6d6, 0x2bcf6e6e, 0x40507070, + 0xdceb8585, 0xfe750a0a, 0x328a9393, 0xa48ddfdf, + 0xca4c2929, 0x10141c1c, 0x2173d7d7, 0xf0ccb4b4, + 0xd309d4d4, 0x5d108a8a, 0x0fe25151, 0x00000000, + 0x6f9a1919, 0x9de01a1a, 0x368f9494, 0x42e6c7c7, + 0x4aecc9c9, 0x5efdd2d2, 0xc1ab7f7f, 0xe0d8a8a8, + + 0xbc75bc32, 0xecf3ec21, 0x20c62043, 0xb3f4b3c9, + 0xdadbda03, 0x027b028b, 0xe2fbe22b, 0x9ec89efa, + 0xc94ac9ec, 0xd4d3d409, 0x18e6186b, 0x1e6b1e9f, + 0x9845980e, 0xb27db238, 0xa6e8a6d2, 0x264b26b7, + 0x3cd63c57, 0x9332938a, 0x82d882ee, 0x52fd5298, + 0x7b377bd4, 0xbb71bb37, 0x5bf15b97, 0x47e14783, + 0x2430243c, 0x510f51e2, 0xbaf8bac6, 0x4a1b4af3, + 0xbf87bf48, 0x0dfa0d70, 0xb006b0b3, 0x753f75de, + 0xd25ed2fd, 0x7dba7d20, 0x66ae6631, 0x3a5b3aa3, + 0x598a591c, 0x00000000, 0xcdbccd93, 0x1a9d1ae0, + 0xae6dae2c, 0x7fc17fab, 0x2bb12bc7, 0xbe0ebeb9, + 0xe080e0a0, 0x8a5d8a10, 0x3bd23b52, 0x64d564ba, + 0xd8a0d888, 0xe784e7a5, 0x5f075fe8, 0x1b141b11, + 0x2cb52cc2, 0xfc90fcb4, 0x312c3127, 0x80a38065, + 0x73b2732a, 0x0c730c81, 0x794c795f, 0x6b546b41, + 0x4b924b02, 0x53745369, 0x9436948f, 0x8351831f, + 0x2a382a36, 0xc4b0c49c, 0x22bd22c8, 0xd55ad5f8, + 0xbdfcbdc3, 0x48604878, 0xff62ffce, 0x4c964c07, + 0x416c4177, 0xc742c7e6, 0xebf7eb24, 0x1c101c14, + 0x5d7c5d63, 0x36283622, 0x672767c0, 0xe98ce9af, + 0x441344f9, 0x149514ea, 0xf59cf5bb, 0xcfc7cf18, + 0x3f243f2d, 0xc046c0e3, 0x723b72db, 0x5470546c, + 0x29ca294c, 0xf0e3f035, 0x088508fe, 0xc6cbc617, + 0xf311f34f, 0x8cd08ce4, 0xa493a459, 0xcab8ca96, + 0x68a6683b, 0xb883b84d, 0x38203828, 0xe5ffe52e, + 0xad9fad56, 0x0b770b84, 0xc8c3c81d, 0x99cc99ff, + 0x580358ed, 0x196f199a, 0x0e080e0a, 0x95bf957e, + 0x70407050, 0xf7e7f730, 0x6e2b6ecf, 0x1fe21f6e, + 0xb579b53d, 0x090c090f, 0x61aa6134, 0x57825716, + 0x9f419f0b, 0x9d3a9d80, 0x11ea1164, 0x25b925cd, + 0xafe4afdd, 0x459a4508, 0xdfa4df8d, 0xa397a35c, + 0xea7eead5, 0x35da3558, 0xed7aedd0, 0x431743fc, + 0xf866f8cb, 0xfb94fbb1, 0x37a137d3, 0xfa1dfa40, + 0xc23dc268, 0xb4f0b4cc, 0x32de325d, 0x9cb39c71, + 0x560b56e7, 0xe372e3da, 0x87a78760, 0x151c151b, + 0xf9eff93a, 0x63d163bf, 0x345334a9, 0x9a3e9a85, + 0xb18fb142, 0x7c337cd1, 0x8826889b, 0x3d5f3da6, + 0xa1eca1d7, 0xe476e4df, 0x812a8194, 0x91499101, + 0x0f810ffb, 0xee88eeaa, 0x16ee1661, 0xd721d773, + 0x97c497f5, 0xa51aa5a8, 0xfeebfe3f, 0x6dd96db5, + 0x78c578ae, 0xc539c56d, 0x1d991de5, 0x76cd76a4, + 0x3ead3edc, 0xcb31cb67, 0xb68bb647, 0xef01ef5b, + 0x1218121e, 0x602360c5, 0x6add6ab0, 0x4d1f4df6, + 0xce4ecee9, 0xde2dde7c, 0x55f9559d, 0x7e487e5a, + 0x214f21b2, 0x03f2037a, 0xa065a026, 0x5e8e5e19, + 0x5a785a66, 0x655c654b, 0x6258624e, 0xfd19fd45, + 0x068d06f4, 0x40e54086, 0xf298f2be, 0x335733ac, + 0x17671790, 0x057f058e, 0xe805e85e, 0x4f644f7d, + 0x89af896a, 0x10631095, 0x74b6742f, 0x0afe0a75, + 0x5cf55c92, 0x9bb79b74, 0x2d3c2d33, 0x30a530d6, + 0x2ece2e49, 0x49e94989, 0x46684672, 0x77447755, + 0xa8e0a8d8, 0x964d9604, 0x284328bd, 0xa969a929, + 0xd929d979, 0x862e8691, 0xd1acd187, 0xf415f44a, + 0x8d598d15, 0xd6a8d682, 0xb90ab9bc, 0x429e420d, + 0xf66ef6c1, 0x2f472fb8, 0xdddfdd06, 0x23342339, + 0xcc35cc62, 0xf16af1c4, 0xc1cfc112, 0x85dc85eb, + 0x8f228f9e, 0x71c971a1, 0x90c090f0, 0xaa9baa53, + 0x018901f1, 0x8bd48be1, 0x4eed4e8c, 0x8eab8e6f, + 0xab12aba2, 0x6fa26f3e, 0xe60de654, 0xdb52dbf2, + 0x92bb927b, 0xb702b7b6, 0x692f69ca, 0x39a939d9, + 0xd3d7d30c, 0xa761a723, 0xa21ea2ad, 0xc3b4c399, + 0x6c506c44, 0x07040705, 0x04f6047f, 0x27c22746, + 0xac16aca7, 0xd025d076, 0x50865013, 0xdc56dcf7, + 0x8455841a, 0xe109e151, 0x7abe7a25, 0x139113ef, + + 0xd939a9d9, 0x90176790, 0x719cb371, 0xd2a6e8d2, + 0x05070405, 0x9852fd98, 0x6580a365, 0xdfe476df, + 0x08459a08, 0x024b9202, 0xa0e080a0, 0x665a7866, + 0xddafe4dd, 0xb06addb0, 0xbf63d1bf, 0x362a3836, + 0x54e60d54, 0x4320c643, 0x62cc3562, 0xbef298be, + 0x1e12181e, 0x24ebf724, 0xd7a1ecd7, 0x77416c77, + 0xbd2843bd, 0x32bc7532, 0xd47b37d4, 0x9b88269b, + 0x700dfa70, 0xf94413f9, 0xb1fb94b1, 0x5a7e485a, + 0x7a03f27a, 0xe48cd0e4, 0x47b68b47, 0x3c24303c, + 0xa5e784a5, 0x416b5441, 0x06dddf06, 0xc56023c5, + 0x45fd1945, 0xa33a5ba3, 0x68c23d68, 0x158d5915, + 0x21ecf321, 0x3166ae31, 0x3e6fa23e, 0x16578216, + 0x95106395, 0x5bef015b, 0x4db8834d, 0x91862e91, + 0xb56dd9b5, 0x1f83511f, 0x53aa9b53, 0x635d7c63, + 0x3b68a63b, 0x3ffeeb3f, 0xd630a5d6, 0x257abe25, + 0xa7ac16a7, 0x0f090c0f, 0x35f0e335, 0x23a76123, + 0xf090c0f0, 0xafe98caf, 0x809d3a80, 0x925cf592, + 0x810c7381, 0x27312c27, 0x76d02576, 0xe7560be7, + 0x7b92bb7b, 0xe9ce4ee9, 0xf10189f1, 0x9f1e6b9f, + 0xa93453a9, 0xc4f16ac4, 0x99c3b499, 0x975bf197, + 0x8347e183, 0x6b18e66b, 0xc822bdc8, 0x0e98450e, + 0x6e1fe26e, 0xc9b3f4c9, 0x2f74b62f, 0xcbf866cb, + 0xff99ccff, 0xea1495ea, 0xed5803ed, 0xf7dc56f7, + 0xe18bd4e1, 0x1b151c1b, 0xada21ead, 0x0cd3d70c, + 0x2be2fb2b, 0x1dc8c31d, 0x195e8e19, 0xc22cb5c2, + 0x8949e989, 0x12c1cf12, 0x7e95bf7e, 0x207dba20, + 0x6411ea64, 0x840b7784, 0x6dc5396d, 0x6a89af6a, + 0xd17c33d1, 0xa171c9a1, 0xceff62ce, 0x37bb7137, + 0xfb0f81fb, 0x3db5793d, 0x51e10951, 0xdc3eaddc, + 0x2d3f242d, 0xa476cda4, 0x9d55f99d, 0xee82d8ee, + 0x8640e586, 0xae78c5ae, 0xcd25b9cd, 0x04964d04, + 0x55774455, 0x0a0e080a, 0x13508613, 0x30f7e730, + 0xd337a1d3, 0x40fa1d40, 0x3461aa34, 0x8c4eed8c, + 0xb3b006b3, 0x6c54706c, 0x2a73b22a, 0x523bd252, + 0x0b9f410b, 0x8b027b8b, 0x88d8a088, 0x4ff3114f, + 0x67cb3167, 0x4627c246, 0xc06727c0, 0xb4fc90b4, + 0x28382028, 0x7f04f67f, 0x78486078, 0x2ee5ff2e, + 0x074c9607, 0x4b655c4b, 0xc72bb1c7, 0x6f8eab6f, + 0x0d429e0d, 0xbbf59cbb, 0xf2db52f2, 0xf34a1bf3, + 0xa63d5fa6, 0x59a49359, 0xbcb90abc, 0x3af9ef3a, + 0xef1391ef, 0xfe0885fe, 0x01914901, 0x6116ee61, + 0x7cde2d7c, 0xb2214fb2, 0x42b18f42, 0xdb723bdb, + 0xb82f47b8, 0x48bf8748, 0x2cae6d2c, 0xe3c046e3, + 0x573cd657, 0x859a3e85, 0x29a96929, 0x7d4f647d, + 0x94812a94, 0x492ece49, 0x17c6cb17, 0xca692fca, + 0xc3bdfcc3, 0x5ca3975c, 0x5ee8055e, 0xd0ed7ad0, + 0x87d1ac87, 0x8e057f8e, 0xba64d5ba, 0xa8a51aa8, + 0xb7264bb7, 0xb9be0eb9, 0x6087a760, 0xf8d55af8, + 0x22362822, 0x111b1411, 0xde753fde, 0x79d92979, + 0xaaee88aa, 0x332d3c33, 0x5f794c5f, 0xb6b702b6, + 0x96cab896, 0x5835da58, 0x9cc4b09c, 0xfc4317fc, + 0x1a84551a, 0xf64d1ff6, 0x1c598a1c, 0x38b27d38, + 0xac3357ac, 0x18cfc718, 0xf4068df4, 0x69537469, + 0x749bb774, 0xf597c4f5, 0x56ad9f56, 0xdae372da, + 0xd5ea7ed5, 0x4af4154a, 0x9e8f229e, 0xa2ab12a2, + 0x4e62584e, 0xe85f07e8, 0xe51d99e5, 0x39233439, + 0xc1f66ec1, 0x446c5044, 0x5d32de5d, 0x72466872, + 0x26a06526, 0x93cdbc93, 0x03dadb03, 0xc6baf8c6, + 0xfa9ec8fa, 0x82d6a882, 0xcf6e2bcf, 0x50704050, + 0xeb85dceb, 0x750afe75, 0x8a93328a, 0x8ddfa48d, + 0x4c29ca4c, 0x141c1014, 0x73d72173, 0xccb4f0cc, + 0x09d4d309, 0x108a5d10, 0xe2510fe2, 0x00000000, + 0x9a196f9a, 0xe01a9de0, 0x8f94368f, 0xe6c742e6, + 0xecc94aec, 0xfdd25efd, 0xab7fc1ab, 0xd8a8e0d8}; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/threefish.cpp b/external/ours/library/crypto/src/shared/original/threefish.cpp new file mode 100755 index 000000000..bf038ab89 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/threefish.cpp @@ -0,0 +1,503 @@ +// threefish.cpp - 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/. + +#include "pch.h" +#include "config.h" + +#include "threefish.h" +#include "misc.h" +#include "algparam.h" +#include "argnames.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; +using CryptoPP::word64; +using CryptoPP::rotlConstant; +using CryptoPP::rotrConstant; +using CryptoPP::rotlVariable; +using CryptoPP::rotrVariable; + +template +inline void G256(word64& G0, word64& G1, word64& G2, word64& G3) +{ + G0 += G1; + G1 = rotlConstant(G1) ^ G0; + G2 += G3; + G3 = rotlConstant(G3) ^ G2; +} + +template +inline void IG256(word64& G0, word64& G1, word64& G2, word64& G3) +{ + G3 = rotrConstant(G3 ^ G2); + G2 -= G3; + G1 = rotrConstant(G1 ^ G0); + G0 -= G1; +} + +#define KS256(r) \ + G0 += m_rkey[(r + 1) % 5]; \ + G1 += m_rkey[(r + 2) % 5] + m_tweak[(r + 1) % 3]; \ + G2 += m_rkey[(r + 3) % 5] + m_tweak[(r + 2) % 3]; \ + G3 += m_rkey[(r + 4) % 5] + r + 1; + +#define IKS256(r) \ + G0 -= m_rkey[(r + 1) % 5]; \ + G1 -= (m_rkey[(r + 2) % 5] + m_tweak[(r + 1) % 3]); \ + G2 -= (m_rkey[(r + 3) % 5] + m_tweak[(r + 2) % 3]); \ + G3 -= (m_rkey[(r + 4) % 5] + r + 1); + +#define G256x8(r) \ + G256<14, 16>(G0, G1, G2, G3); \ + G256<52, 57>(G0, G3, G2, G1); \ + G256<23, 40>(G0, G1, G2, G3); \ + G256< 5, 37>(G0, G3, G2, G1); \ + KS256(r); \ + G256<25, 33>(G0, G1, G2, G3); \ + G256<46, 12>(G0, G3, G2, G1); \ + G256<58, 22>(G0, G1, G2, G3); \ + G256<32, 32>(G0, G3, G2, G1); \ + KS256(r + 1); + +#define IG256x8(r) \ + IG256<32, 32>(G0, G3, G2, G1); \ + IG256<58, 22>(G0, G1, G2, G3); \ + IG256<46, 12>(G0, G3, G2, G1); \ + IG256<25, 33>(G0, G1, G2, G3); \ + IKS256(r); \ + IG256< 5, 37>(G0, G3, G2, G1); \ + IG256<23, 40>(G0, G1, G2, G3); \ + IG256<52, 57>(G0, G3, G2, G1); \ + IG256<14, 16>(G0, G1, G2, G3); \ + IKS256(r - 1); + +/////////////////// + +template +inline void G512(word64& G0, word64& G1, word64& G2, word64& G3, word64& G4, word64& G5, word64& G6, word64& G7) +{ + G0 += G1; + G1 = rotlConstant(G1) ^ G0; + G2 += G3; + G3 = rotlConstant(G3) ^ G2; + G4 += G5; + G5 = rotlConstant(G5) ^ G4; + G6 += G7; + G7 = rotlConstant(G7) ^ G6; +} + +template +inline void IG512(word64& G0, word64& G1, word64& G2, word64& G3, word64& G4, word64& G5, word64& G6, word64& G7) +{ + G7 = rotrConstant(G7 ^ G6); + G6 -= G7; + G5 = rotrConstant(G5 ^ G4); + G4 -= G5; + G3 = rotrConstant(G3 ^ G2); + G2 -= G3; + G1 = rotrConstant(G1 ^ G0); + G0 -= G1; +} + +#define KS512(r) \ + G0 += m_rkey[(r + 1) % 9]; \ + G1 += m_rkey[(r + 2) % 9]; \ + G2 += m_rkey[(r + 3) % 9]; \ + G3 += m_rkey[(r + 4) % 9]; \ + G4 += m_rkey[(r + 5) % 9]; \ + G5 += m_rkey[(r + 6) % 9] + m_tweak[(r + 1) % 3]; \ + G6 += m_rkey[(r + 7) % 9] + m_tweak[(r + 2) % 3]; \ + G7 += m_rkey[(r + 8) % 9] + r + 1; + +#define IKS512(r) \ + G0 -= m_rkey[(r + 1) % 9]; \ + G1 -= m_rkey[(r + 2) % 9]; \ + G2 -= m_rkey[(r + 3) % 9]; \ + G3 -= m_rkey[(r + 4) % 9]; \ + G4 -= m_rkey[(r + 5) % 9]; \ + G5 -= (m_rkey[(r + 6) % 9] + m_tweak[(r + 1) % 3]); \ + G6 -= (m_rkey[(r + 7) % 9] + m_tweak[(r + 2) % 3]); \ + G7 -= (m_rkey[(r + 8) % 9] + r + 1); + +#define IG512x8(r) \ + IG512< 8, 35, 56, 22>(G6, G1, G0, G7, G2, G5, G4, G3); \ + IG512<25, 29, 39, 43>(G4, G1, G6, G3, G0, G5, G2, G7); \ + IG512<13, 50, 10, 17>(G2, G1, G4, G7, G6, G5, G0, G3); \ + IG512<39, 30, 34, 24>(G0, G1, G2, G3, G4, G5, G6, G7); \ + IKS512(r) \ + IG512<44, 9, 54, 56>(G6, G1, G0, G7, G2, G5, G4, G3); \ + IG512<17, 49, 36, 39>(G4, G1, G6, G3, G0, G5, G2, G7); \ + IG512<33, 27, 14, 42>(G2, G1, G4, G7, G6, G5, G0, G3); \ + IG512<46, 36, 19, 37>(G0, G1, G2, G3, G4, G5, G6, G7); \ + IKS512(r - 1) + +#define G512x8(r) \ + G512<46, 36, 19, 37>(G0, G1, G2, G3, G4, G5, G6, G7); \ + G512<33, 27, 14, 42>(G2, G1, G4, G7, G6, G5, G0, G3); \ + G512<17, 49, 36, 39>(G4, G1, G6, G3, G0, G5, G2, G7); \ + G512<44, 9, 54, 56>(G6, G1, G0, G7, G2, G5, G4, G3); \ + KS512(r) \ + G512<39, 30, 34, 24>(G0, G1, G2, G3, G4, G5, G6, G7); \ + G512<13, 50, 10, 17>(G2, G1, G4, G7, G6, G5, G0, G3); \ + G512<25, 29, 39, 43>(G4, G1, G6, G3, G0, G5, G2, G7); \ + G512< 8, 35, 56, 22>(G6, G1, G0, G7, G2, G5, G4, G3); \ + KS512(r + 1) + +/////////////////// + +template +inline void G1024A(word64& G0, word64& G1, word64& G2, word64& G3, + word64& G4, word64& G5, word64& G6, word64& G7) +{ + G0 += G1; + G1 = rotlConstant(G1) ^ G0; + G2 += G3; + G3 = rotlConstant(G3) ^ G2; + G4 += G5; + G5 = rotlConstant(G5) ^ G4; + G6 += G7; + G7 = rotlConstant(G7) ^ G6; +} + +template +inline void G1024B(word64& G8, word64& G9, word64& G10, word64& G11, + word64& G12, word64& G13, word64& G14, word64& G15) +{ + G8 += G9; + G9 = rotlConstant(G9) ^ G8; + G10 += G11; + G11 = rotlConstant(G11) ^ G10; + G12 += G13; + G13 = rotlConstant(G13) ^ G12; + G14 += G15; + G15 = rotlConstant(G15) ^ G14; +} + +template +inline void G1024(word64& G0, word64& G1, word64& G2, word64& G3, word64& G4, word64& G5, + word64& G6, word64& G7, word64& G8, word64& G9, word64& G10, word64& G11, word64& G12, + word64& G13, word64& G14, word64& G15) +{ + // The extra gyrations promote inlining. Without it Threefish1024 looses 10 cpb. + G1024A(G0, G1, G2, G3, G4, G5, G6, G7); + G1024B(G8, G9, G10, G11, G12, G13, G14, G15); +} + +template +inline void IG1024A(word64& G8, word64& G9, word64& G10, word64& G11, + word64& G12, word64& G13, word64& G14, word64& G15) +{ + G15 = rotrConstant(G15 ^ G14); + G14 -= G15; + G13 = rotrConstant(G13 ^ G12); + G12 -= G13; + G11 = rotrConstant(G11 ^ G10); + G10 -= G11; + G9 = rotrConstant(G9 ^ G8); + G8 -= G9; +} + +template +inline void IG1024B(word64& G0, word64& G1, word64& G2, word64& G3, + word64& G4, word64& G5, word64& G6, word64& G7) +{ + G7 = rotrConstant(G7 ^ G6); + G6 -= G7; + G5 = rotrConstant(G5 ^ G4); + G4 -= G5; + G3 = rotrConstant(G3 ^ G2); + G2 -= G3; + G1 = rotrConstant(G1 ^ G0); + G0 -= G1; +} + +template +inline void IG1024(word64& G0, word64& G1, word64& G2, word64& G3, word64& G4, word64& G5, + word64& G6, word64& G7, word64& G8, word64& G9, word64& G10, word64& G11, word64& G12, + word64& G13, word64& G14, word64& G15) +{ + // The extra gyrations promote inlining. Without it Threefish1024 looses 10 cpb. + IG1024A(G8, G9, G10, G11, G12, G13, G14, G15); + IG1024B(G0, G1, G2, G3, G4, G5, G6, G7); +} + +#define KS1024(r) \ + G0 += m_rkey[(r + 1) % 17]; \ + G1 += m_rkey[(r + 2) % 17]; \ + G2 += m_rkey[(r + 3) % 17]; \ + G3 += m_rkey[(r + 4) % 17]; \ + G4 += m_rkey[(r + 5) % 17]; \ + G5 += m_rkey[(r + 6) % 17]; \ + G6 += m_rkey[(r + 7) % 17]; \ + G7 += m_rkey[(r + 8) % 17]; \ + G8 += m_rkey[(r + 9) % 17]; \ + G9 += m_rkey[(r + 10) % 17]; \ + G10 += m_rkey[(r + 11) % 17]; \ + G11 += m_rkey[(r + 12) % 17]; \ + G12 += m_rkey[(r + 13) % 17]; \ + G13 += m_rkey[(r + 14) % 17] + m_tweak[(r + 1) % 3]; \ + G14 += m_rkey[(r + 15) % 17] + m_tweak[(r + 2) % 3]; \ + G15 += m_rkey[(r + 16) % 17] + r + 1; + +#define IKS1024(r) \ + G0 -= m_rkey[(r + 1) % 17]; \ + G1 -= m_rkey[(r + 2) % 17]; \ + G2 -= m_rkey[(r + 3) % 17]; \ + G3 -= m_rkey[(r + 4) % 17]; \ + G4 -= m_rkey[(r + 5) % 17]; \ + G5 -= m_rkey[(r + 6) % 17]; \ + G6 -= m_rkey[(r + 7) % 17]; \ + G7 -= m_rkey[(r + 8) % 17]; \ + G8 -= m_rkey[(r + 9) % 17]; \ + G9 -= m_rkey[(r + 10) % 17]; \ + G10 -= m_rkey[(r + 11) % 17]; \ + G11 -= m_rkey[(r + 12) % 17]; \ + G12 -= m_rkey[(r + 13) % 17]; \ + G13 -= (m_rkey[(r + 14) % 17] + m_tweak[(r + 1) % 3]); \ + G14 -= (m_rkey[(r + 15) % 17] + m_tweak[(r + 2) % 3]); \ + G15 -= (m_rkey[(r + 16) % 17] + r + 1); + +#define G1024x8(r) \ + G1024A<24, 13, 8, 47>(G0, G1, G2, G3, G4, G5, G6, G7); \ + G1024B< 8, 17, 22, 37>(G8, G9, G10, G11, G12, G13, G14, G15); \ + G1024A<38, 19, 10, 55>(G0, G9, G2, G13, G6, G11, G4, G15); \ + G1024B<49, 18, 23, 52>(G10, G7, G12, G3, G14, G5, G8, G1); \ + G1024A<33, 4, 51, 13>(G0, G7, G2, G5, G4, G3, G6, G1); \ + G1024B<34, 41, 59, 17>(G12, G15, G14, G13, G8, G11, G10, G9); \ + G1024A< 5, 20, 48, 41>(G0, G15, G2, G11, G6, G13, G4, G9); \ + G1024B<47, 28, 16, 25>(G14, G1, G8, G5, G10, G3, G12, G7); \ + KS1024(r); \ + G1024A<41, 9, 37, 31>(G0, G1, G2, G3, G4, G5, G6, G7); \ + G1024B<12, 47, 44, 30>(G8, G9, G10, G11, G12, G13, G14, G15); \ + G1024A<16, 34, 56, 51>(G0, G9, G2, G13, G6, G11, G4, G15); \ + G1024B< 4, 53, 42, 41>(G10, G7, G12, G3, G14, G5, G8, G1); \ + G1024A<31, 44, 47, 46>(G0, G7, G2, G5, G4, G3, G6, G1); \ + G1024B<19, 42, 44, 25>(G12, G15, G14, G13, G8, G11, G10, G9); \ + G1024A< 9, 48, 35, 52>(G0, G15, G2, G11, G6, G13, G4, G9); \ + G1024B<23, 31, 37, 20>(G14, G1, G8, G5, G10, G3, G12, G7); \ + KS1024(r + 1); + +#define IG1024x8(r) \ + IG1024A< 9, 48, 35, 52>(G0, G15, G2, G11, G6, G13, G4, G9); \ + IG1024B<23, 31, 37, 20>(G14, G1, G8, G5, G10, G3, G12, G7); \ + IG1024A<31, 44, 47, 46>(G0, G7, G2, G5, G4, G3, G6, G1); \ + IG1024B<19, 42, 44, 25>(G12, G15, G14, G13, G8, G11, G10, G9); \ + IG1024A<16, 34, 56, 51>(G0, G9, G2, G13, G6, G11, G4, G15); \ + IG1024B< 4, 53, 42, 41>(G10, G7, G12, G3, G14, G5, G8, G1); \ + IG1024A<41, 9, 37, 31>(G0, G1, G2, G3, G4, G5, G6, G7); \ + IG1024B<12, 47, 44, 30>(G8, G9, G10, G11, G12, G13, G14, G15); \ + IKS1024(r); \ + IG1024A< 5, 20, 48, 41>(G0, G15, G2, G11, G6, G13, G4, G9); \ + IG1024B<47, 28, 16, 25>(G14, G1, G8, G5, G10, G3, G12, G7); \ + IG1024A<33, 4, 51, 13>(G0, G7, G2, G5, G4, G3, G6, G1); \ + IG1024B<34, 41, 59, 17>(G12, G15, G14, G13, G8, G11, G10, G9); \ + IG1024A<38, 19, 10, 55>(G0, G9, G2, G13, G6, G11, G4, G15); \ + IG1024B<49, 18, 23, 52>(G10, G7, G12, G3, G14, G5, G8, G1); \ + IG1024A<24, 13, 8, 47>(G0, G1, G2, G3, G4, G5, G6, G7); \ + IG1024B< 8, 17, 22, 37>(G8, G9, G10, G11, G12, G13, G14, G15); \ + IKS1024(r - 1); + +ANONYMOUS_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +NAMESPACE_BEGIN(CryptoPP) + +void Threefish256::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + // Blocksize is Keylength for Threefish + CRYPTOPP_ASSERT(keyLength == KEYLENGTH); + + m_rkey.New(5); + m_wspace.New(4); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_rkey.begin(), 4, userKey, keyLength); + m_rkey[4] = W64LIT(0x1BD11BDAA9FC1A22) ^ m_rkey[0] ^ m_rkey[1] ^ m_rkey[2] ^ m_rkey[3]; + + SetTweak(params); +} + +void Threefish256::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 &G0=m_wspace[0], &G1=m_wspace[1], &G2=m_wspace[2], &G3=m_wspace[3]; + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(G0)(G1)(G2)(G3); + + G0 += m_rkey[0]; G1 += m_rkey[1]; G2 += m_rkey[2]; + G3 += m_rkey[3]; G1 += m_tweak[0]; G2 += m_tweak[1]; + + G256x8(0); G256x8(2); G256x8(4); G256x8(6); G256x8(8); + G256x8(10); G256x8(12); G256x8(14); G256x8(16); + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(G0)(G1)(G2)(G3); +} + +void Threefish256::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 &G0=m_wspace[0], &G1=m_wspace[1], &G2=m_wspace[2], &G3=m_wspace[3]; + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(G0)(G1)(G2)(G3); + + G0 -= m_rkey[3]; G1 -= m_rkey[4]; G2 -= m_rkey[0]; G3 -= m_rkey[1]; + G1 -= m_tweak[0]; G2 -= m_tweak[1]; G3 -= 18; + + IG256x8(16); IG256x8(14); IG256x8(12); IG256x8(10); + IG256x8(8); IG256x8(6); IG256x8(4); IG256x8(2); IG256x8(0); + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(G0)(G1)(G2)(G3); +} + +///////////////////////////////////////////////////////////////// + +void Threefish512::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + // Blocksize is Keylength for Threefish + CRYPTOPP_ASSERT(keyLength == KEYLENGTH); + + m_rkey.New(9); + m_wspace.New(8); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_rkey.begin(), 8, userKey, keyLength); + m_rkey[8] = W64LIT(0x1BD11BDAA9FC1A22) ^ m_rkey[0] ^ m_rkey[1] ^ m_rkey[2] ^ m_rkey[3] ^ + m_rkey[4] ^ m_rkey[5] ^ m_rkey[6] ^ m_rkey[7]; + + SetTweak(params); +} + +void Threefish512::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 &G0=m_wspace[0], &G1=m_wspace[1], &G2=m_wspace[2], &G3=m_wspace[3]; + word64 &G4=m_wspace[4], &G5=m_wspace[5], &G6=m_wspace[6], &G7=m_wspace[7]; + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(G0)(G1)(G2)(G3)(G4)(G5)(G6)(G7); + + // 34 integer instructions total + G0 += m_rkey[0]; G1 += m_rkey[1]; G2 += m_rkey[2]; G3 += m_rkey[3]; + G4 += m_rkey[4]; G5 += m_rkey[5]; G6 += m_rkey[6]; G7 += m_rkey[7]; + G5 += m_tweak[0]; G6 += m_tweak[1]; + + G512x8(0); G512x8(2); G512x8(4); G512x8(6); G512x8(8); + G512x8(10); G512x8(12); G512x8(14); G512x8(16); + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(G0)(G1)(G2)(G3)(G4)(G5)(G6)(G7); +} + +void Threefish512::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 &G0=m_wspace[0], &G1=m_wspace[1], &G2=m_wspace[2], &G3=m_wspace[3]; + word64 &G4=m_wspace[4], &G5=m_wspace[5], &G6=m_wspace[6], &G7=m_wspace[7]; + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(G0)(G1)(G2)(G3)(G4)(G5)(G6)(G7); + + G0 -= m_rkey[0]; G1 -= m_rkey[1]; G2 -= m_rkey[2]; G3 -= m_rkey[3]; + G4 -= m_rkey[4]; G5 -= m_rkey[5]; G6 -= m_rkey[6]; G7 -= m_rkey[7]; + G5 -= m_tweak[0]; G6 -= m_tweak[1]; G7 -= 18; + + IG512x8(16); IG512x8(14); IG512x8(12); IG512x8(10); + IG512x8(8); IG512x8(6); IG512x8(4); IG512x8(2); IG512x8(0); + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(G0)(G1)(G2)(G3)(G4)(G5)(G6)(G7); +} + +///////////////////////////////////////////////////////////////// + +void Threefish1024::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + // Blocksize is Keylength for Threefish + CRYPTOPP_ASSERT(keyLength == KEYLENGTH); + + m_rkey.New(17); + m_wspace.New(16); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_rkey.begin(), 16, userKey, keyLength); + m_rkey[16] = W64LIT(0x1BD11BDAA9FC1A22) ^ m_rkey[0] ^ m_rkey[1] ^ m_rkey[2] ^ m_rkey[3] ^ m_rkey[4] ^ + m_rkey[5] ^ m_rkey[6] ^ m_rkey[7] ^ m_rkey[8] ^ m_rkey[9] ^ m_rkey[10] ^ m_rkey[11] ^ m_rkey[12] ^ + m_rkey[13] ^ m_rkey[14] ^ m_rkey[15]; + + SetTweak(params); +} + +void Threefish1024::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 &G0=m_wspace[0], &G1=m_wspace[1], &G2=m_wspace[2], &G3=m_wspace[3]; + word64 &G4=m_wspace[4], &G5=m_wspace[5], &G6=m_wspace[6], &G7=m_wspace[7]; + word64 &G8=m_wspace[8], &G9=m_wspace[9], &G10=m_wspace[10], &G11=m_wspace[11]; + word64 &G12=m_wspace[12], &G13=m_wspace[13], &G14=m_wspace[14], &G15=m_wspace[15]; + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(G0)(G1)(G2)(G3)(G4)(G5)(G6)(G7)(G8)(G9)(G10)(G11)(G12)(G13)(G14)(G15); + + G0 += m_rkey[0]; G1 += m_rkey[1]; G2 += m_rkey[2]; G3 += m_rkey[3]; + G4 += m_rkey[4]; G5 += m_rkey[5]; G6 += m_rkey[6]; G7 += m_rkey[7]; + G8 += m_rkey[8]; G9 += m_rkey[9]; G10 += m_rkey[10]; G11 += m_rkey[11]; + G12 += m_rkey[12]; G13 += m_rkey[13]; G14 += m_rkey[14]; G15 += m_rkey[15]; + G13 += m_tweak[0]; G14 += m_tweak[1]; + + G1024x8(0); G1024x8(2); G1024x8(4); G1024x8(6); G1024x8(8); + G1024x8(10); G1024x8(12); G1024x8(14); G1024x8(16); G1024x8(18); + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(G0)(G1)(G2)(G3)(G4)(G5)(G6)(G7)(G8)(G9)(G10)(G11)(G12)(G13)(G14)(G15); +} + +void Threefish1024::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word64 &G0=m_wspace[0], &G1=m_wspace[1], &G2=m_wspace[2], &G3=m_wspace[3]; + word64 &G4=m_wspace[4], &G5=m_wspace[5], &G6=m_wspace[6], &G7=m_wspace[7]; + word64 &G8=m_wspace[8], &G9=m_wspace[9], &G10=m_wspace[10], &G11=m_wspace[11]; + word64 &G12=m_wspace[12], &G13=m_wspace[13], &G14=m_wspace[14], &G15=m_wspace[15]; + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef GetBlock InBlock; + InBlock iblk(inBlock); + iblk(G0)(G1)(G2)(G3)(G4)(G5)(G6)(G7)(G8)(G9)(G10)(G11)(G12)(G13)(G14)(G15); + + G0 -= m_rkey[3]; G1 -= m_rkey[4]; G2 -= m_rkey[5]; G3 -= m_rkey[6]; + G4 -= m_rkey[7]; G5 -= m_rkey[8]; G6 -= m_rkey[9]; G7 -= m_rkey[10]; + G8 -= m_rkey[11]; G9 -= m_rkey[12]; G10 -= m_rkey[13]; G11 -= m_rkey[14]; + G12 -= m_rkey[15]; G13 -= m_rkey[16]; G14 -= m_rkey[0]; G15 -= m_rkey[1]; + G13 -= m_tweak[2]; G14 -= m_tweak[0]; G15 -= 20; + + IG1024x8(18); IG1024x8(16); IG1024x8(14); IG1024x8(12); IG1024x8(10); + IG1024x8(8); IG1024x8(6); IG1024x8(4); IG1024x8(2); IG1024x8(0); + + // Reverse bytes on BigEndian; align pointer on LittleEndian + typedef PutBlock OutBlock; + OutBlock oblk(xorBlock, outBlock); + oblk(G0)(G1)(G2)(G3)(G4)(G5)(G6)(G7)(G8)(G9)(G10)(G11)(G12)(G13)(G14)(G15); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/threefish.h b/external/ours/library/crypto/src/shared/original/threefish.h new file mode 100755 index 000000000..cb53d78a9 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/tiger.cpp b/external/ours/library/crypto/src/shared/original/tiger.cpp new file mode 100755 index 000000000..c71cdc2f5 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/tiger.cpp @@ -0,0 +1,282 @@ +// tiger.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "config.h" + +#include "tiger.h" +#include "misc.h" +#include "cpu.h" + +#if defined(CRYPTOPP_DISABLE_TIGER_ASM) +# undef CRYPTOPP_X86_ASM_AVAILABLE +# undef CRYPTOPP_X32_ASM_AVAILABLE +# undef CRYPTOPP_X64_ASM_AVAILABLE +# undef CRYPTOPP_SSE2_ASM_AVAILABLE +#endif + +NAMESPACE_BEGIN(CryptoPP) + +std::string Tiger::AlgorithmProvider() const +{ +#ifndef CRYPTOPP_DISABLE_TIGER_ASM +# if CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return "SSE2"; +# endif +#endif + return "C++"; +} + +void Tiger::InitState(HashWordType *state) +{ + state[0] = W64LIT(0x0123456789ABCDEF); + state[1] = W64LIT(0xFEDCBA9876543210); + state[2] = W64LIT(0xF096A5B4C3B2E187); +} + +void Tiger::TruncatedFinal(byte *digest, size_t digestSize) +{ + CRYPTOPP_ASSERT(digest != NULLPTR); + ThrowIfInvalidTruncatedSize(digestSize); + + PadLastBlock(56, 0x01); + CorrectEndianess(m_data, m_data, 56); + + m_data[7] = GetBitCountLo(); + + Transform(m_state, m_data); + CorrectEndianess(m_state, m_state, DigestSize()); + memcpy(digest, m_state, digestSize); + + Restart(); // reinit for next use +} + +void Tiger::Transform (word64 *state, const word64 *data) +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 + if (HasSSE2()) + { +#ifdef __GNUC__ + __asm__ __volatile__ + ( + INTEL_NOPREFIX + AS_PUSH_IF86(bx) +#else + AS2( lea edx, [table]) + AS2( mov eax, state) + AS2( mov esi, data) +#endif + AS2( movq mm0, [eax]) + AS2( movq mm1, [eax+1*8]) + AS2( movq mm5, mm1) + AS2( movq mm2, [eax+2*8]) + AS2( movq mm7, [edx+4*2048+0*8]) + AS2( movq mm6, [edx+4*2048+1*8]) + AS2( mov ecx, esp) + AS2( and esp, 0xfffffff0) + AS2( sub esp, 8*8) + AS_PUSH_IF86(cx) + +#define SSE2_round(a,b,c,x,mul) \ + AS2( pxor c, [x])\ + AS2( movd ecx, c)\ + AS2( movzx edi, cl)\ + AS2( movq mm3, [edx+0*2048+edi*8])\ + AS2( movzx edi, ch)\ + AS2( movq mm4, [edx+3*2048+edi*8])\ + AS2( shr ecx, 16)\ + AS2( movzx edi, cl)\ + AS2( pxor mm3, [edx+1*2048+edi*8])\ + AS2( movzx edi, ch)\ + AS2( pxor mm4, [edx+2*2048+edi*8])\ + AS3( pextrw ecx, c, 2)\ + AS2( movzx edi, cl)\ + AS2( pxor mm3, [edx+2*2048+edi*8])\ + AS2( movzx edi, ch)\ + AS2( pxor mm4, [edx+1*2048+edi*8])\ + AS3( pextrw ecx, c, 3)\ + AS2( movzx edi, cl)\ + AS2( pxor mm3, [edx+3*2048+edi*8])\ + AS2( psubq a, mm3)\ + AS2( movzx edi, ch)\ + AS2( pxor mm4, [edx+0*2048+edi*8])\ + AS2( paddq b, mm4)\ + SSE2_mul_##mul(b) + +#define SSE2_mul_5(b) \ + AS2( movq mm3, b)\ + AS2( psllq b, 2)\ + AS2( paddq b, mm3) + +#define SSE2_mul_7(b) \ + AS2( movq mm3, b)\ + AS2( psllq b, 3)\ + AS2( psubq b, mm3) + +#define SSE2_mul_9(b) \ + AS2( movq mm3, b)\ + AS2( psllq b, 3)\ + AS2( paddq b, mm3) + +#define label2_5 1 +#define label2_7 2 +#define label2_9 3 + +#define SSE2_pass(A,B,C,mul,X) \ + AS2( xor ebx, ebx)\ + ASL(mul)\ + SSE2_round(A,B,C,X+0*8+ebx,mul)\ + SSE2_round(B,C,A,X+1*8+ebx,mul)\ + AS2( cmp ebx, 6*8)\ + ASJ( je, label2_##mul, f)\ + SSE2_round(C,A,B,X+2*8+ebx,mul)\ + AS2( add ebx, 3*8)\ + ASJ( jmp, mul, b)\ + ASL(label2_##mul) + +#define SSE2_key_schedule(Y,X) \ + AS2( movq mm3, [X+7*8])\ + AS2( pxor mm3, mm6)\ + AS2( movq mm4, [X+0*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+0*8], mm4)\ + AS2( pxor mm4, [X+1*8])\ + AS2( movq mm3, mm4)\ + AS2( movq [Y+1*8], mm4)\ + AS2( paddq mm4, [X+2*8])\ + AS2( pxor mm3, mm7)\ + AS2( psllq mm3, 19)\ + AS2( movq [Y+2*8], mm4)\ + AS2( pxor mm3, mm4)\ + AS2( movq mm4, [X+3*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+3*8], mm4)\ + AS2( pxor mm4, [X+4*8])\ + AS2( movq mm3, mm4)\ + AS2( movq [Y+4*8], mm4)\ + AS2( paddq mm4, [X+5*8])\ + AS2( pxor mm3, mm7)\ + AS2( psrlq mm3, 23)\ + AS2( movq [Y+5*8], mm4)\ + AS2( pxor mm3, mm4)\ + AS2( movq mm4, [X+6*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+6*8], mm4)\ + AS2( pxor mm4, [X+7*8])\ + AS2( movq mm3, mm4)\ + AS2( movq [Y+7*8], mm4)\ + AS2( paddq mm4, [Y+0*8])\ + AS2( pxor mm3, mm7)\ + AS2( psllq mm3, 19)\ + AS2( movq [Y+0*8], mm4)\ + AS2( pxor mm3, mm4)\ + AS2( movq mm4, [Y+1*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+1*8], mm4)\ + AS2( pxor mm4, [Y+2*8])\ + AS2( movq mm3, mm4)\ + AS2( movq [Y+2*8], mm4)\ + AS2( paddq mm4, [Y+3*8])\ + AS2( pxor mm3, mm7)\ + AS2( psrlq mm3, 23)\ + AS2( movq [Y+3*8], mm4)\ + AS2( pxor mm3, mm4)\ + AS2( movq mm4, [Y+4*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+4*8], mm4)\ + AS2( pxor mm4, [Y+5*8])\ + AS2( movq [Y+5*8], mm4)\ + AS2( paddq mm4, [Y+6*8])\ + AS2( movq [Y+6*8], mm4)\ + AS2( pxor mm4, [edx+4*2048+2*8])\ + AS2( movq mm3, [Y+7*8])\ + AS2( psubq mm3, mm4)\ + AS2( movq [Y+7*8], mm3) + + SSE2_pass(mm0, mm1, mm2, 5, esi) + SSE2_key_schedule(esp+4, esi) + SSE2_pass(mm2, mm0, mm1, 7, esp+4) + SSE2_key_schedule(esp+4, esp+4) + SSE2_pass(mm1, mm2, mm0, 9, esp+4) + + AS2( pxor mm0, [eax+0*8]) + AS2( movq [eax+0*8], mm0) + AS2( psubq mm1, mm5) + AS2( movq [eax+1*8], mm1) + AS2( paddq mm2, [eax+2*8]) + AS2( movq [eax+2*8], mm2) + + AS_POP_IF86(sp) + AS1( emms) + +#ifdef __GNUC__ + AS_POP_IF86(bx) + ATT_PREFIX + : + : "a" (state), "S" (data), "d" (table) + : "%ecx", "%edi", "memory", "cc" + ); +#endif + } + else +#endif + { + word64 a = state[0]; + word64 b = state[1]; + word64 c = state[2]; + word64 Y[8]; + +#define t1 (table) +#define t2 (table+256) +#define t3 (table+256*2) +#define t4 (table+256*3) + +#define round(a,b,c,x,mul) \ + c ^= x; \ + a -= t1[GETBYTE(c,0)] ^ t2[GETBYTE(c,2)] ^ t3[GETBYTE(c,4)] ^ t4[GETBYTE(c,6)]; \ + b += t4[GETBYTE(c,1)] ^ t3[GETBYTE(c,3)] ^ t2[GETBYTE(c,5)] ^ t1[GETBYTE(c,7)]; \ + b *= mul + +#define pass(a,b,c,mul,X) {\ + int i=0;\ + while (true)\ + {\ + round(a,b,c,X[i+0],mul); \ + round(b,c,a,X[i+1],mul); \ + if (i==6)\ + break;\ + round(c,a,b,X[i+2],mul); \ + i+=3;\ + }} + +#define key_schedule(Y,X) \ + Y[0] = X[0] - (X[7]^W64LIT(0xA5A5A5A5A5A5A5A5)); \ + Y[1] = X[1] ^ Y[0]; \ + Y[2] = X[2] + Y[1]; \ + Y[3] = X[3] - (Y[2] ^ ((~Y[1])<<19)); \ + Y[4] = X[4] ^ Y[3]; \ + Y[5] = X[5] + Y[4]; \ + Y[6] = X[6] - (Y[5] ^ ((~Y[4])>>23)); \ + Y[7] = X[7] ^ Y[6]; \ + Y[0] += Y[7]; \ + Y[1] -= Y[0] ^ ((~Y[7])<<19); \ + Y[2] ^= Y[1]; \ + Y[3] += Y[2]; \ + Y[4] -= Y[3] ^ ((~Y[2])>>23); \ + Y[5] ^= Y[4]; \ + Y[6] += Y[5]; \ + Y[7] -= Y[6] ^ W64LIT(0x0123456789ABCDEF) + + pass(a,b,c,5,data); + key_schedule(Y,data); + pass(c,a,b,7,Y); + key_schedule(Y,Y); + pass(b,c,a,9,Y); + + state[0] = a ^ state[0]; + state[1] = b - state[1]; + state[2] = c + state[2]; + } +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/tiger.h b/external/ours/library/crypto/src/shared/original/tiger.h new file mode 100755 index 000000000..4737dd923 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/tigertab.cpp b/external/ours/library/crypto/src/shared/original/tigertab.cpp new file mode 100755 index 000000000..5e219dcf6 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/tigertab.cpp @@ -0,0 +1,525 @@ +#include "pch.h" +#include "tiger.h" + +NAMESPACE_BEGIN(CryptoPP) + +const word64 Tiger::table[4*256+3] = +{ + W64LIT(0x02AAB17CF7E90C5E) /* 0 */, W64LIT(0xAC424B03E243A8EC) /* 1 */, + W64LIT(0x72CD5BE30DD5FCD3) /* 2 */, W64LIT(0x6D019B93F6F97F3A) /* 3 */, + W64LIT(0xCD9978FFD21F9193) /* 4 */, W64LIT(0x7573A1C9708029E2) /* 5 */, + W64LIT(0xB164326B922A83C3) /* 6 */, W64LIT(0x46883EEE04915870) /* 7 */, + W64LIT(0xEAACE3057103ECE6) /* 8 */, W64LIT(0xC54169B808A3535C) /* 9 */, + W64LIT(0x4CE754918DDEC47C) /* 10 */, W64LIT(0x0AA2F4DFDC0DF40C) /* 11 */, + W64LIT(0x10B76F18A74DBEFA) /* 12 */, W64LIT(0xC6CCB6235AD1AB6A) /* 13 */, + W64LIT(0x13726121572FE2FF) /* 14 */, W64LIT(0x1A488C6F199D921E) /* 15 */, + W64LIT(0x4BC9F9F4DA0007CA) /* 16 */, W64LIT(0x26F5E6F6E85241C7) /* 17 */, + W64LIT(0x859079DBEA5947B6) /* 18 */, W64LIT(0x4F1885C5C99E8C92) /* 19 */, + W64LIT(0xD78E761EA96F864B) /* 20 */, W64LIT(0x8E36428C52B5C17D) /* 21 */, + W64LIT(0x69CF6827373063C1) /* 22 */, W64LIT(0xB607C93D9BB4C56E) /* 23 */, + W64LIT(0x7D820E760E76B5EA) /* 24 */, W64LIT(0x645C9CC6F07FDC42) /* 25 */, + W64LIT(0xBF38A078243342E0) /* 26 */, W64LIT(0x5F6B343C9D2E7D04) /* 27 */, + W64LIT(0xF2C28AEB600B0EC6) /* 28 */, W64LIT(0x6C0ED85F7254BCAC) /* 29 */, + W64LIT(0x71592281A4DB4FE5) /* 30 */, W64LIT(0x1967FA69CE0FED9F) /* 31 */, + W64LIT(0xFD5293F8B96545DB) /* 32 */, W64LIT(0xC879E9D7F2A7600B) /* 33 */, + W64LIT(0x860248920193194E) /* 34 */, W64LIT(0xA4F9533B2D9CC0B3) /* 35 */, + W64LIT(0x9053836C15957613) /* 36 */, W64LIT(0xDB6DCF8AFC357BF1) /* 37 */, + W64LIT(0x18BEEA7A7A370F57) /* 38 */, W64LIT(0x037117CA50B99066) /* 39 */, + W64LIT(0x6AB30A9774424A35) /* 40 */, W64LIT(0xF4E92F02E325249B) /* 41 */, + W64LIT(0x7739DB07061CCAE1) /* 42 */, W64LIT(0xD8F3B49CECA42A05) /* 43 */, + W64LIT(0xBD56BE3F51382F73) /* 44 */, W64LIT(0x45FAED5843B0BB28) /* 45 */, + W64LIT(0x1C813D5C11BF1F83) /* 46 */, W64LIT(0x8AF0E4B6D75FA169) /* 47 */, + W64LIT(0x33EE18A487AD9999) /* 48 */, W64LIT(0x3C26E8EAB1C94410) /* 49 */, + W64LIT(0xB510102BC0A822F9) /* 50 */, W64LIT(0x141EEF310CE6123B) /* 51 */, + W64LIT(0xFC65B90059DDB154) /* 52 */, W64LIT(0xE0158640C5E0E607) /* 53 */, + W64LIT(0x884E079826C3A3CF) /* 54 */, W64LIT(0x930D0D9523C535FD) /* 55 */, + W64LIT(0x35638D754E9A2B00) /* 56 */, W64LIT(0x4085FCCF40469DD5) /* 57 */, + W64LIT(0xC4B17AD28BE23A4C) /* 58 */, W64LIT(0xCAB2F0FC6A3E6A2E) /* 59 */, + W64LIT(0x2860971A6B943FCD) /* 60 */, W64LIT(0x3DDE6EE212E30446) /* 61 */, + W64LIT(0x6222F32AE01765AE) /* 62 */, W64LIT(0x5D550BB5478308FE) /* 63 */, + W64LIT(0xA9EFA98DA0EDA22A) /* 64 */, W64LIT(0xC351A71686C40DA7) /* 65 */, + W64LIT(0x1105586D9C867C84) /* 66 */, W64LIT(0xDCFFEE85FDA22853) /* 67 */, + W64LIT(0xCCFBD0262C5EEF76) /* 68 */, W64LIT(0xBAF294CB8990D201) /* 69 */, + W64LIT(0xE69464F52AFAD975) /* 70 */, W64LIT(0x94B013AFDF133E14) /* 71 */, + W64LIT(0x06A7D1A32823C958) /* 72 */, W64LIT(0x6F95FE5130F61119) /* 73 */, + W64LIT(0xD92AB34E462C06C0) /* 74 */, W64LIT(0xED7BDE33887C71D2) /* 75 */, + W64LIT(0x79746D6E6518393E) /* 76 */, W64LIT(0x5BA419385D713329) /* 77 */, + W64LIT(0x7C1BA6B948A97564) /* 78 */, W64LIT(0x31987C197BFDAC67) /* 79 */, + W64LIT(0xDE6C23C44B053D02) /* 80 */, W64LIT(0x581C49FED002D64D) /* 81 */, + W64LIT(0xDD474D6338261571) /* 82 */, W64LIT(0xAA4546C3E473D062) /* 83 */, + W64LIT(0x928FCE349455F860) /* 84 */, W64LIT(0x48161BBACAAB94D9) /* 85 */, + W64LIT(0x63912430770E6F68) /* 86 */, W64LIT(0x6EC8A5E602C6641C) /* 87 */, + W64LIT(0x87282515337DDD2B) /* 88 */, W64LIT(0x2CDA6B42034B701B) /* 89 */, + W64LIT(0xB03D37C181CB096D) /* 90 */, W64LIT(0xE108438266C71C6F) /* 91 */, + W64LIT(0x2B3180C7EB51B255) /* 92 */, W64LIT(0xDF92B82F96C08BBC) /* 93 */, + W64LIT(0x5C68C8C0A632F3BA) /* 94 */, W64LIT(0x5504CC861C3D0556) /* 95 */, + W64LIT(0xABBFA4E55FB26B8F) /* 96 */, W64LIT(0x41848B0AB3BACEB4) /* 97 */, + W64LIT(0xB334A273AA445D32) /* 98 */, W64LIT(0xBCA696F0A85AD881) /* 99 */, + W64LIT(0x24F6EC65B528D56C) /* 100 */, W64LIT(0x0CE1512E90F4524A) /* 101 */, + W64LIT(0x4E9DD79D5506D35A) /* 102 */, W64LIT(0x258905FAC6CE9779) /* 103 */, + W64LIT(0x2019295B3E109B33) /* 104 */, W64LIT(0xF8A9478B73A054CC) /* 105 */, + W64LIT(0x2924F2F934417EB0) /* 106 */, W64LIT(0x3993357D536D1BC4) /* 107 */, + W64LIT(0x38A81AC21DB6FF8B) /* 108 */, W64LIT(0x47C4FBF17D6016BF) /* 109 */, + W64LIT(0x1E0FAADD7667E3F5) /* 110 */, W64LIT(0x7ABCFF62938BEB96) /* 111 */, + W64LIT(0xA78DAD948FC179C9) /* 112 */, W64LIT(0x8F1F98B72911E50D) /* 113 */, + W64LIT(0x61E48EAE27121A91) /* 114 */, W64LIT(0x4D62F7AD31859808) /* 115 */, + W64LIT(0xECEBA345EF5CEAEB) /* 116 */, W64LIT(0xF5CEB25EBC9684CE) /* 117 */, + W64LIT(0xF633E20CB7F76221) /* 118 */, W64LIT(0xA32CDF06AB8293E4) /* 119 */, + W64LIT(0x985A202CA5EE2CA4) /* 120 */, W64LIT(0xCF0B8447CC8A8FB1) /* 121 */, + W64LIT(0x9F765244979859A3) /* 122 */, W64LIT(0xA8D516B1A1240017) /* 123 */, + W64LIT(0x0BD7BA3EBB5DC726) /* 124 */, W64LIT(0xE54BCA55B86ADB39) /* 125 */, + W64LIT(0x1D7A3AFD6C478063) /* 126 */, W64LIT(0x519EC608E7669EDD) /* 127 */, + W64LIT(0x0E5715A2D149AA23) /* 128 */, W64LIT(0x177D4571848FF194) /* 129 */, + W64LIT(0xEEB55F3241014C22) /* 130 */, W64LIT(0x0F5E5CA13A6E2EC2) /* 131 */, + W64LIT(0x8029927B75F5C361) /* 132 */, W64LIT(0xAD139FABC3D6E436) /* 133 */, + W64LIT(0x0D5DF1A94CCF402F) /* 134 */, W64LIT(0x3E8BD948BEA5DFC8) /* 135 */, + W64LIT(0xA5A0D357BD3FF77E) /* 136 */, W64LIT(0xA2D12E251F74F645) /* 137 */, + W64LIT(0x66FD9E525E81A082) /* 138 */, W64LIT(0x2E0C90CE7F687A49) /* 139 */, + W64LIT(0xC2E8BCBEBA973BC5) /* 140 */, W64LIT(0x000001BCE509745F) /* 141 */, + W64LIT(0x423777BBE6DAB3D6) /* 142 */, W64LIT(0xD1661C7EAEF06EB5) /* 143 */, + W64LIT(0xA1781F354DAACFD8) /* 144 */, W64LIT(0x2D11284A2B16AFFC) /* 145 */, + W64LIT(0xF1FC4F67FA891D1F) /* 146 */, W64LIT(0x73ECC25DCB920ADA) /* 147 */, + W64LIT(0xAE610C22C2A12651) /* 148 */, W64LIT(0x96E0A810D356B78A) /* 149 */, + W64LIT(0x5A9A381F2FE7870F) /* 150 */, W64LIT(0xD5AD62EDE94E5530) /* 151 */, + W64LIT(0xD225E5E8368D1427) /* 152 */, W64LIT(0x65977B70C7AF4631) /* 153 */, + W64LIT(0x99F889B2DE39D74F) /* 154 */, W64LIT(0x233F30BF54E1D143) /* 155 */, + W64LIT(0x9A9675D3D9A63C97) /* 156 */, W64LIT(0x5470554FF334F9A8) /* 157 */, + W64LIT(0x166ACB744A4F5688) /* 158 */, W64LIT(0x70C74CAAB2E4AEAD) /* 159 */, + W64LIT(0xF0D091646F294D12) /* 160 */, W64LIT(0x57B82A89684031D1) /* 161 */, + W64LIT(0xEFD95A5A61BE0B6B) /* 162 */, W64LIT(0x2FBD12E969F2F29A) /* 163 */, + W64LIT(0x9BD37013FEFF9FE8) /* 164 */, W64LIT(0x3F9B0404D6085A06) /* 165 */, + W64LIT(0x4940C1F3166CFE15) /* 166 */, W64LIT(0x09542C4DCDF3DEFB) /* 167 */, + W64LIT(0xB4C5218385CD5CE3) /* 168 */, W64LIT(0xC935B7DC4462A641) /* 169 */, + W64LIT(0x3417F8A68ED3B63F) /* 170 */, W64LIT(0xB80959295B215B40) /* 171 */, + W64LIT(0xF99CDAEF3B8C8572) /* 172 */, W64LIT(0x018C0614F8FCB95D) /* 173 */, + W64LIT(0x1B14ACCD1A3ACDF3) /* 174 */, W64LIT(0x84D471F200BB732D) /* 175 */, + W64LIT(0xC1A3110E95E8DA16) /* 176 */, W64LIT(0x430A7220BF1A82B8) /* 177 */, + W64LIT(0xB77E090D39DF210E) /* 178 */, W64LIT(0x5EF4BD9F3CD05E9D) /* 179 */, + W64LIT(0x9D4FF6DA7E57A444) /* 180 */, W64LIT(0xDA1D60E183D4A5F8) /* 181 */, + W64LIT(0xB287C38417998E47) /* 182 */, W64LIT(0xFE3EDC121BB31886) /* 183 */, + W64LIT(0xC7FE3CCC980CCBEF) /* 184 */, W64LIT(0xE46FB590189BFD03) /* 185 */, + W64LIT(0x3732FD469A4C57DC) /* 186 */, W64LIT(0x7EF700A07CF1AD65) /* 187 */, + W64LIT(0x59C64468A31D8859) /* 188 */, W64LIT(0x762FB0B4D45B61F6) /* 189 */, + W64LIT(0x155BAED099047718) /* 190 */, W64LIT(0x68755E4C3D50BAA6) /* 191 */, + W64LIT(0xE9214E7F22D8B4DF) /* 192 */, W64LIT(0x2ADDBF532EAC95F4) /* 193 */, + W64LIT(0x32AE3909B4BD0109) /* 194 */, W64LIT(0x834DF537B08E3450) /* 195 */, + W64LIT(0xFA209DA84220728D) /* 196 */, W64LIT(0x9E691D9B9EFE23F7) /* 197 */, + W64LIT(0x0446D288C4AE8D7F) /* 198 */, W64LIT(0x7B4CC524E169785B) /* 199 */, + W64LIT(0x21D87F0135CA1385) /* 200 */, W64LIT(0xCEBB400F137B8AA5) /* 201 */, + W64LIT(0x272E2B66580796BE) /* 202 */, W64LIT(0x3612264125C2B0DE) /* 203 */, + W64LIT(0x057702BDAD1EFBB2) /* 204 */, W64LIT(0xD4BABB8EACF84BE9) /* 205 */, + W64LIT(0x91583139641BC67B) /* 206 */, W64LIT(0x8BDC2DE08036E024) /* 207 */, + W64LIT(0x603C8156F49F68ED) /* 208 */, W64LIT(0xF7D236F7DBEF5111) /* 209 */, + W64LIT(0x9727C4598AD21E80) /* 210 */, W64LIT(0xA08A0896670A5FD7) /* 211 */, + W64LIT(0xCB4A8F4309EBA9CB) /* 212 */, W64LIT(0x81AF564B0F7036A1) /* 213 */, + W64LIT(0xC0B99AA778199ABD) /* 214 */, W64LIT(0x959F1EC83FC8E952) /* 215 */, + W64LIT(0x8C505077794A81B9) /* 216 */, W64LIT(0x3ACAAF8F056338F0) /* 217 */, + W64LIT(0x07B43F50627A6778) /* 218 */, W64LIT(0x4A44AB49F5ECCC77) /* 219 */, + W64LIT(0x3BC3D6E4B679EE98) /* 220 */, W64LIT(0x9CC0D4D1CF14108C) /* 221 */, + W64LIT(0x4406C00B206BC8A0) /* 222 */, W64LIT(0x82A18854C8D72D89) /* 223 */, + W64LIT(0x67E366B35C3C432C) /* 224 */, W64LIT(0xB923DD61102B37F2) /* 225 */, + W64LIT(0x56AB2779D884271D) /* 226 */, W64LIT(0xBE83E1B0FF1525AF) /* 227 */, + W64LIT(0xFB7C65D4217E49A9) /* 228 */, W64LIT(0x6BDBE0E76D48E7D4) /* 229 */, + W64LIT(0x08DF828745D9179E) /* 230 */, W64LIT(0x22EA6A9ADD53BD34) /* 231 */, + W64LIT(0xE36E141C5622200A) /* 232 */, W64LIT(0x7F805D1B8CB750EE) /* 233 */, + W64LIT(0xAFE5C7A59F58E837) /* 234 */, W64LIT(0xE27F996A4FB1C23C) /* 235 */, + W64LIT(0xD3867DFB0775F0D0) /* 236 */, W64LIT(0xD0E673DE6E88891A) /* 237 */, + W64LIT(0x123AEB9EAFB86C25) /* 238 */, W64LIT(0x30F1D5D5C145B895) /* 239 */, + W64LIT(0xBB434A2DEE7269E7) /* 240 */, W64LIT(0x78CB67ECF931FA38) /* 241 */, + W64LIT(0xF33B0372323BBF9C) /* 242 */, W64LIT(0x52D66336FB279C74) /* 243 */, + W64LIT(0x505F33AC0AFB4EAA) /* 244 */, W64LIT(0xE8A5CD99A2CCE187) /* 245 */, + W64LIT(0x534974801E2D30BB) /* 246 */, W64LIT(0x8D2D5711D5876D90) /* 247 */, + W64LIT(0x1F1A412891BC038E) /* 248 */, W64LIT(0xD6E2E71D82E56648) /* 249 */, + W64LIT(0x74036C3A497732B7) /* 250 */, W64LIT(0x89B67ED96361F5AB) /* 251 */, + W64LIT(0xFFED95D8F1EA02A2) /* 252 */, W64LIT(0xE72B3BD61464D43D) /* 253 */, + W64LIT(0xA6300F170BDC4820) /* 254 */, W64LIT(0xEBC18760ED78A77A) /* 255 */, + W64LIT(0xE6A6BE5A05A12138) /* 256 */, W64LIT(0xB5A122A5B4F87C98) /* 257 */, + W64LIT(0x563C6089140B6990) /* 258 */, W64LIT(0x4C46CB2E391F5DD5) /* 259 */, + W64LIT(0xD932ADDBC9B79434) /* 260 */, W64LIT(0x08EA70E42015AFF5) /* 261 */, + W64LIT(0xD765A6673E478CF1) /* 262 */, W64LIT(0xC4FB757EAB278D99) /* 263 */, + W64LIT(0xDF11C6862D6E0692) /* 264 */, W64LIT(0xDDEB84F10D7F3B16) /* 265 */, + W64LIT(0x6F2EF604A665EA04) /* 266 */, W64LIT(0x4A8E0F0FF0E0DFB3) /* 267 */, + W64LIT(0xA5EDEEF83DBCBA51) /* 268 */, W64LIT(0xFC4F0A2A0EA4371E) /* 269 */, + W64LIT(0xE83E1DA85CB38429) /* 270 */, W64LIT(0xDC8FF882BA1B1CE2) /* 271 */, + W64LIT(0xCD45505E8353E80D) /* 272 */, W64LIT(0x18D19A00D4DB0717) /* 273 */, + W64LIT(0x34A0CFEDA5F38101) /* 274 */, W64LIT(0x0BE77E518887CAF2) /* 275 */, + W64LIT(0x1E341438B3C45136) /* 276 */, W64LIT(0xE05797F49089CCF9) /* 277 */, + W64LIT(0xFFD23F9DF2591D14) /* 278 */, W64LIT(0x543DDA228595C5CD) /* 279 */, + W64LIT(0x661F81FD99052A33) /* 280 */, W64LIT(0x8736E641DB0F7B76) /* 281 */, + W64LIT(0x15227725418E5307) /* 282 */, W64LIT(0xE25F7F46162EB2FA) /* 283 */, + W64LIT(0x48A8B2126C13D9FE) /* 284 */, W64LIT(0xAFDC541792E76EEA) /* 285 */, + W64LIT(0x03D912BFC6D1898F) /* 286 */, W64LIT(0x31B1AAFA1B83F51B) /* 287 */, + W64LIT(0xF1AC2796E42AB7D9) /* 288 */, W64LIT(0x40A3A7D7FCD2EBAC) /* 289 */, + W64LIT(0x1056136D0AFBBCC5) /* 290 */, W64LIT(0x7889E1DD9A6D0C85) /* 291 */, + W64LIT(0xD33525782A7974AA) /* 292 */, W64LIT(0xA7E25D09078AC09B) /* 293 */, + W64LIT(0xBD4138B3EAC6EDD0) /* 294 */, W64LIT(0x920ABFBE71EB9E70) /* 295 */, + W64LIT(0xA2A5D0F54FC2625C) /* 296 */, W64LIT(0xC054E36B0B1290A3) /* 297 */, + W64LIT(0xF6DD59FF62FE932B) /* 298 */, W64LIT(0x3537354511A8AC7D) /* 299 */, + W64LIT(0xCA845E9172FADCD4) /* 300 */, W64LIT(0x84F82B60329D20DC) /* 301 */, + W64LIT(0x79C62CE1CD672F18) /* 302 */, W64LIT(0x8B09A2ADD124642C) /* 303 */, + W64LIT(0xD0C1E96A19D9E726) /* 304 */, W64LIT(0x5A786A9B4BA9500C) /* 305 */, + W64LIT(0x0E020336634C43F3) /* 306 */, W64LIT(0xC17B474AEB66D822) /* 307 */, + W64LIT(0x6A731AE3EC9BAAC2) /* 308 */, W64LIT(0x8226667AE0840258) /* 309 */, + W64LIT(0x67D4567691CAECA5) /* 310 */, W64LIT(0x1D94155C4875ADB5) /* 311 */, + W64LIT(0x6D00FD985B813FDF) /* 312 */, W64LIT(0x51286EFCB774CD06) /* 313 */, + W64LIT(0x5E8834471FA744AF) /* 314 */, W64LIT(0xF72CA0AEE761AE2E) /* 315 */, + W64LIT(0xBE40E4CDAEE8E09A) /* 316 */, W64LIT(0xE9970BBB5118F665) /* 317 */, + W64LIT(0x726E4BEB33DF1964) /* 318 */, W64LIT(0x703B000729199762) /* 319 */, + W64LIT(0x4631D816F5EF30A7) /* 320 */, W64LIT(0xB880B5B51504A6BE) /* 321 */, + W64LIT(0x641793C37ED84B6C) /* 322 */, W64LIT(0x7B21ED77F6E97D96) /* 323 */, + W64LIT(0x776306312EF96B73) /* 324 */, W64LIT(0xAE528948E86FF3F4) /* 325 */, + W64LIT(0x53DBD7F286A3F8F8) /* 326 */, W64LIT(0x16CADCE74CFC1063) /* 327 */, + W64LIT(0x005C19BDFA52C6DD) /* 328 */, W64LIT(0x68868F5D64D46AD3) /* 329 */, + W64LIT(0x3A9D512CCF1E186A) /* 330 */, W64LIT(0x367E62C2385660AE) /* 331 */, + W64LIT(0xE359E7EA77DCB1D7) /* 332 */, W64LIT(0x526C0773749ABE6E) /* 333 */, + W64LIT(0x735AE5F9D09F734B) /* 334 */, W64LIT(0x493FC7CC8A558BA8) /* 335 */, + W64LIT(0xB0B9C1533041AB45) /* 336 */, W64LIT(0x321958BA470A59BD) /* 337 */, + W64LIT(0x852DB00B5F46C393) /* 338 */, W64LIT(0x91209B2BD336B0E5) /* 339 */, + W64LIT(0x6E604F7D659EF19F) /* 340 */, W64LIT(0xB99A8AE2782CCB24) /* 341 */, + W64LIT(0xCCF52AB6C814C4C7) /* 342 */, W64LIT(0x4727D9AFBE11727B) /* 343 */, + W64LIT(0x7E950D0C0121B34D) /* 344 */, W64LIT(0x756F435670AD471F) /* 345 */, + W64LIT(0xF5ADD442615A6849) /* 346 */, W64LIT(0x4E87E09980B9957A) /* 347 */, + W64LIT(0x2ACFA1DF50AEE355) /* 348 */, W64LIT(0xD898263AFD2FD556) /* 349 */, + W64LIT(0xC8F4924DD80C8FD6) /* 350 */, W64LIT(0xCF99CA3D754A173A) /* 351 */, + W64LIT(0xFE477BACAF91BF3C) /* 352 */, W64LIT(0xED5371F6D690C12D) /* 353 */, + W64LIT(0x831A5C285E687094) /* 354 */, W64LIT(0xC5D3C90A3708A0A4) /* 355 */, + W64LIT(0x0F7F903717D06580) /* 356 */, W64LIT(0x19F9BB13B8FDF27F) /* 357 */, + W64LIT(0xB1BD6F1B4D502843) /* 358 */, W64LIT(0x1C761BA38FFF4012) /* 359 */, + W64LIT(0x0D1530C4E2E21F3B) /* 360 */, W64LIT(0x8943CE69A7372C8A) /* 361 */, + W64LIT(0xE5184E11FEB5CE66) /* 362 */, W64LIT(0x618BDB80BD736621) /* 363 */, + W64LIT(0x7D29BAD68B574D0B) /* 364 */, W64LIT(0x81BB613E25E6FE5B) /* 365 */, + W64LIT(0x071C9C10BC07913F) /* 366 */, W64LIT(0xC7BEEB7909AC2D97) /* 367 */, + W64LIT(0xC3E58D353BC5D757) /* 368 */, W64LIT(0xEB017892F38F61E8) /* 369 */, + W64LIT(0xD4EFFB9C9B1CC21A) /* 370 */, W64LIT(0x99727D26F494F7AB) /* 371 */, + W64LIT(0xA3E063A2956B3E03) /* 372 */, W64LIT(0x9D4A8B9A4AA09C30) /* 373 */, + W64LIT(0x3F6AB7D500090FB4) /* 374 */, W64LIT(0x9CC0F2A057268AC0) /* 375 */, + W64LIT(0x3DEE9D2DEDBF42D1) /* 376 */, W64LIT(0x330F49C87960A972) /* 377 */, + W64LIT(0xC6B2720287421B41) /* 378 */, W64LIT(0x0AC59EC07C00369C) /* 379 */, + W64LIT(0xEF4EAC49CB353425) /* 380 */, W64LIT(0xF450244EEF0129D8) /* 381 */, + W64LIT(0x8ACC46E5CAF4DEB6) /* 382 */, W64LIT(0x2FFEAB63989263F7) /* 383 */, + W64LIT(0x8F7CB9FE5D7A4578) /* 384 */, W64LIT(0x5BD8F7644E634635) /* 385 */, + W64LIT(0x427A7315BF2DC900) /* 386 */, W64LIT(0x17D0C4AA2125261C) /* 387 */, + W64LIT(0x3992486C93518E50) /* 388 */, W64LIT(0xB4CBFEE0A2D7D4C3) /* 389 */, + W64LIT(0x7C75D6202C5DDD8D) /* 390 */, W64LIT(0xDBC295D8E35B6C61) /* 391 */, + W64LIT(0x60B369D302032B19) /* 392 */, W64LIT(0xCE42685FDCE44132) /* 393 */, + W64LIT(0x06F3DDB9DDF65610) /* 394 */, W64LIT(0x8EA4D21DB5E148F0) /* 395 */, + W64LIT(0x20B0FCE62FCD496F) /* 396 */, W64LIT(0x2C1B912358B0EE31) /* 397 */, + W64LIT(0xB28317B818F5A308) /* 398 */, W64LIT(0xA89C1E189CA6D2CF) /* 399 */, + W64LIT(0x0C6B18576AAADBC8) /* 400 */, W64LIT(0xB65DEAA91299FAE3) /* 401 */, + W64LIT(0xFB2B794B7F1027E7) /* 402 */, W64LIT(0x04E4317F443B5BEB) /* 403 */, + W64LIT(0x4B852D325939D0A6) /* 404 */, W64LIT(0xD5AE6BEEFB207FFC) /* 405 */, + W64LIT(0x309682B281C7D374) /* 406 */, W64LIT(0xBAE309A194C3B475) /* 407 */, + W64LIT(0x8CC3F97B13B49F05) /* 408 */, W64LIT(0x98A9422FF8293967) /* 409 */, + W64LIT(0x244B16B01076FF7C) /* 410 */, W64LIT(0xF8BF571C663D67EE) /* 411 */, + W64LIT(0x1F0D6758EEE30DA1) /* 412 */, W64LIT(0xC9B611D97ADEB9B7) /* 413 */, + W64LIT(0xB7AFD5887B6C57A2) /* 414 */, W64LIT(0x6290AE846B984FE1) /* 415 */, + W64LIT(0x94DF4CDEACC1A5FD) /* 416 */, W64LIT(0x058A5BD1C5483AFF) /* 417 */, + W64LIT(0x63166CC142BA3C37) /* 418 */, W64LIT(0x8DB8526EB2F76F40) /* 419 */, + W64LIT(0xE10880036F0D6D4E) /* 420 */, W64LIT(0x9E0523C9971D311D) /* 421 */, + W64LIT(0x45EC2824CC7CD691) /* 422 */, W64LIT(0x575B8359E62382C9) /* 423 */, + W64LIT(0xFA9E400DC4889995) /* 424 */, W64LIT(0xD1823ECB45721568) /* 425 */, + W64LIT(0xDAFD983B8206082F) /* 426 */, W64LIT(0xAA7D29082386A8CB) /* 427 */, + W64LIT(0x269FCD4403B87588) /* 428 */, W64LIT(0x1B91F5F728BDD1E0) /* 429 */, + W64LIT(0xE4669F39040201F6) /* 430 */, W64LIT(0x7A1D7C218CF04ADE) /* 431 */, + W64LIT(0x65623C29D79CE5CE) /* 432 */, W64LIT(0x2368449096C00BB1) /* 433 */, + W64LIT(0xAB9BF1879DA503BA) /* 434 */, W64LIT(0xBC23ECB1A458058E) /* 435 */, + W64LIT(0x9A58DF01BB401ECC) /* 436 */, W64LIT(0xA070E868A85F143D) /* 437 */, + W64LIT(0x4FF188307DF2239E) /* 438 */, W64LIT(0x14D565B41A641183) /* 439 */, + W64LIT(0xEE13337452701602) /* 440 */, W64LIT(0x950E3DCF3F285E09) /* 441 */, + W64LIT(0x59930254B9C80953) /* 442 */, W64LIT(0x3BF299408930DA6D) /* 443 */, + W64LIT(0xA955943F53691387) /* 444 */, W64LIT(0xA15EDECAA9CB8784) /* 445 */, + W64LIT(0x29142127352BE9A0) /* 446 */, W64LIT(0x76F0371FFF4E7AFB) /* 447 */, + W64LIT(0x0239F450274F2228) /* 448 */, W64LIT(0xBB073AF01D5E868B) /* 449 */, + W64LIT(0xBFC80571C10E96C1) /* 450 */, W64LIT(0xD267088568222E23) /* 451 */, + W64LIT(0x9671A3D48E80B5B0) /* 452 */, W64LIT(0x55B5D38AE193BB81) /* 453 */, + W64LIT(0x693AE2D0A18B04B8) /* 454 */, W64LIT(0x5C48B4ECADD5335F) /* 455 */, + W64LIT(0xFD743B194916A1CA) /* 456 */, W64LIT(0x2577018134BE98C4) /* 457 */, + W64LIT(0xE77987E83C54A4AD) /* 458 */, W64LIT(0x28E11014DA33E1B9) /* 459 */, + W64LIT(0x270CC59E226AA213) /* 460 */, W64LIT(0x71495F756D1A5F60) /* 461 */, + W64LIT(0x9BE853FB60AFEF77) /* 462 */, W64LIT(0xADC786A7F7443DBF) /* 463 */, + W64LIT(0x0904456173B29A82) /* 464 */, W64LIT(0x58BC7A66C232BD5E) /* 465 */, + W64LIT(0xF306558C673AC8B2) /* 466 */, W64LIT(0x41F639C6B6C9772A) /* 467 */, + W64LIT(0x216DEFE99FDA35DA) /* 468 */, W64LIT(0x11640CC71C7BE615) /* 469 */, + W64LIT(0x93C43694565C5527) /* 470 */, W64LIT(0xEA038E6246777839) /* 471 */, + W64LIT(0xF9ABF3CE5A3E2469) /* 472 */, W64LIT(0x741E768D0FD312D2) /* 473 */, + W64LIT(0x0144B883CED652C6) /* 474 */, W64LIT(0xC20B5A5BA33F8552) /* 475 */, + W64LIT(0x1AE69633C3435A9D) /* 476 */, W64LIT(0x97A28CA4088CFDEC) /* 477 */, + W64LIT(0x8824A43C1E96F420) /* 478 */, W64LIT(0x37612FA66EEEA746) /* 479 */, + W64LIT(0x6B4CB165F9CF0E5A) /* 480 */, W64LIT(0x43AA1C06A0ABFB4A) /* 481 */, + W64LIT(0x7F4DC26FF162796B) /* 482 */, W64LIT(0x6CBACC8E54ED9B0F) /* 483 */, + W64LIT(0xA6B7FFEFD2BB253E) /* 484 */, W64LIT(0x2E25BC95B0A29D4F) /* 485 */, + W64LIT(0x86D6A58BDEF1388C) /* 486 */, W64LIT(0xDED74AC576B6F054) /* 487 */, + W64LIT(0x8030BDBC2B45805D) /* 488 */, W64LIT(0x3C81AF70E94D9289) /* 489 */, + W64LIT(0x3EFF6DDA9E3100DB) /* 490 */, W64LIT(0xB38DC39FDFCC8847) /* 491 */, + W64LIT(0x123885528D17B87E) /* 492 */, W64LIT(0xF2DA0ED240B1B642) /* 493 */, + W64LIT(0x44CEFADCD54BF9A9) /* 494 */, W64LIT(0x1312200E433C7EE6) /* 495 */, + W64LIT(0x9FFCC84F3A78C748) /* 496 */, W64LIT(0xF0CD1F72248576BB) /* 497 */, + W64LIT(0xEC6974053638CFE4) /* 498 */, W64LIT(0x2BA7B67C0CEC4E4C) /* 499 */, + W64LIT(0xAC2F4DF3E5CE32ED) /* 500 */, W64LIT(0xCB33D14326EA4C11) /* 501 */, + W64LIT(0xA4E9044CC77E58BC) /* 502 */, W64LIT(0x5F513293D934FCEF) /* 503 */, + W64LIT(0x5DC9645506E55444) /* 504 */, W64LIT(0x50DE418F317DE40A) /* 505 */, + W64LIT(0x388CB31A69DDE259) /* 506 */, W64LIT(0x2DB4A83455820A86) /* 507 */, + W64LIT(0x9010A91E84711AE9) /* 508 */, W64LIT(0x4DF7F0B7B1498371) /* 509 */, + W64LIT(0xD62A2EABC0977179) /* 510 */, W64LIT(0x22FAC097AA8D5C0E) /* 511 */, + W64LIT(0xF49FCC2FF1DAF39B) /* 512 */, W64LIT(0x487FD5C66FF29281) /* 513 */, + W64LIT(0xE8A30667FCDCA83F) /* 514 */, W64LIT(0x2C9B4BE3D2FCCE63) /* 515 */, + W64LIT(0xDA3FF74B93FBBBC2) /* 516 */, W64LIT(0x2FA165D2FE70BA66) /* 517 */, + W64LIT(0xA103E279970E93D4) /* 518 */, W64LIT(0xBECDEC77B0E45E71) /* 519 */, + W64LIT(0xCFB41E723985E497) /* 520 */, W64LIT(0xB70AAA025EF75017) /* 521 */, + W64LIT(0xD42309F03840B8E0) /* 522 */, W64LIT(0x8EFC1AD035898579) /* 523 */, + W64LIT(0x96C6920BE2B2ABC5) /* 524 */, W64LIT(0x66AF4163375A9172) /* 525 */, + W64LIT(0x2174ABDCCA7127FB) /* 526 */, W64LIT(0xB33CCEA64A72FF41) /* 527 */, + W64LIT(0xF04A4933083066A5) /* 528 */, W64LIT(0x8D970ACDD7289AF5) /* 529 */, + W64LIT(0x8F96E8E031C8C25E) /* 530 */, W64LIT(0xF3FEC02276875D47) /* 531 */, + W64LIT(0xEC7BF310056190DD) /* 532 */, W64LIT(0xF5ADB0AEBB0F1491) /* 533 */, + W64LIT(0x9B50F8850FD58892) /* 534 */, W64LIT(0x4975488358B74DE8) /* 535 */, + W64LIT(0xA3354FF691531C61) /* 536 */, W64LIT(0x0702BBE481D2C6EE) /* 537 */, + W64LIT(0x89FB24057DEDED98) /* 538 */, W64LIT(0xAC3075138596E902) /* 539 */, + W64LIT(0x1D2D3580172772ED) /* 540 */, W64LIT(0xEB738FC28E6BC30D) /* 541 */, + W64LIT(0x5854EF8F63044326) /* 542 */, W64LIT(0x9E5C52325ADD3BBE) /* 543 */, + W64LIT(0x90AA53CF325C4623) /* 544 */, W64LIT(0xC1D24D51349DD067) /* 545 */, + W64LIT(0x2051CFEEA69EA624) /* 546 */, W64LIT(0x13220F0A862E7E4F) /* 547 */, + W64LIT(0xCE39399404E04864) /* 548 */, W64LIT(0xD9C42CA47086FCB7) /* 549 */, + W64LIT(0x685AD2238A03E7CC) /* 550 */, W64LIT(0x066484B2AB2FF1DB) /* 551 */, + W64LIT(0xFE9D5D70EFBF79EC) /* 552 */, W64LIT(0x5B13B9DD9C481854) /* 553 */, + W64LIT(0x15F0D475ED1509AD) /* 554 */, W64LIT(0x0BEBCD060EC79851) /* 555 */, + W64LIT(0xD58C6791183AB7F8) /* 556 */, W64LIT(0xD1187C5052F3EEE4) /* 557 */, + W64LIT(0xC95D1192E54E82FF) /* 558 */, W64LIT(0x86EEA14CB9AC6CA2) /* 559 */, + W64LIT(0x3485BEB153677D5D) /* 560 */, W64LIT(0xDD191D781F8C492A) /* 561 */, + W64LIT(0xF60866BAA784EBF9) /* 562 */, W64LIT(0x518F643BA2D08C74) /* 563 */, + W64LIT(0x8852E956E1087C22) /* 564 */, W64LIT(0xA768CB8DC410AE8D) /* 565 */, + W64LIT(0x38047726BFEC8E1A) /* 566 */, W64LIT(0xA67738B4CD3B45AA) /* 567 */, + W64LIT(0xAD16691CEC0DDE19) /* 568 */, W64LIT(0xC6D4319380462E07) /* 569 */, + W64LIT(0xC5A5876D0BA61938) /* 570 */, W64LIT(0x16B9FA1FA58FD840) /* 571 */, + W64LIT(0x188AB1173CA74F18) /* 572 */, W64LIT(0xABDA2F98C99C021F) /* 573 */, + W64LIT(0x3E0580AB134AE816) /* 574 */, W64LIT(0x5F3B05B773645ABB) /* 575 */, + W64LIT(0x2501A2BE5575F2F6) /* 576 */, W64LIT(0x1B2F74004E7E8BA9) /* 577 */, + W64LIT(0x1CD7580371E8D953) /* 578 */, W64LIT(0x7F6ED89562764E30) /* 579 */, + W64LIT(0xB15926FF596F003D) /* 580 */, W64LIT(0x9F65293DA8C5D6B9) /* 581 */, + W64LIT(0x6ECEF04DD690F84C) /* 582 */, W64LIT(0x4782275FFF33AF88) /* 583 */, + W64LIT(0xE41433083F820801) /* 584 */, W64LIT(0xFD0DFE409A1AF9B5) /* 585 */, + W64LIT(0x4325A3342CDB396B) /* 586 */, W64LIT(0x8AE77E62B301B252) /* 587 */, + W64LIT(0xC36F9E9F6655615A) /* 588 */, W64LIT(0x85455A2D92D32C09) /* 589 */, + W64LIT(0xF2C7DEA949477485) /* 590 */, W64LIT(0x63CFB4C133A39EBA) /* 591 */, + W64LIT(0x83B040CC6EBC5462) /* 592 */, W64LIT(0x3B9454C8FDB326B0) /* 593 */, + W64LIT(0x56F56A9E87FFD78C) /* 594 */, W64LIT(0x2DC2940D99F42BC6) /* 595 */, + W64LIT(0x98F7DF096B096E2D) /* 596 */, W64LIT(0x19A6E01E3AD852BF) /* 597 */, + W64LIT(0x42A99CCBDBD4B40B) /* 598 */, W64LIT(0xA59998AF45E9C559) /* 599 */, + W64LIT(0x366295E807D93186) /* 600 */, W64LIT(0x6B48181BFAA1F773) /* 601 */, + W64LIT(0x1FEC57E2157A0A1D) /* 602 */, W64LIT(0x4667446AF6201AD5) /* 603 */, + W64LIT(0xE615EBCACFB0F075) /* 604 */, W64LIT(0xB8F31F4F68290778) /* 605 */, + W64LIT(0x22713ED6CE22D11E) /* 606 */, W64LIT(0x3057C1A72EC3C93B) /* 607 */, + W64LIT(0xCB46ACC37C3F1F2F) /* 608 */, W64LIT(0xDBB893FD02AAF50E) /* 609 */, + W64LIT(0x331FD92E600B9FCF) /* 610 */, W64LIT(0xA498F96148EA3AD6) /* 611 */, + W64LIT(0xA8D8426E8B6A83EA) /* 612 */, W64LIT(0xA089B274B7735CDC) /* 613 */, + W64LIT(0x87F6B3731E524A11) /* 614 */, W64LIT(0x118808E5CBC96749) /* 615 */, + W64LIT(0x9906E4C7B19BD394) /* 616 */, W64LIT(0xAFED7F7E9B24A20C) /* 617 */, + W64LIT(0x6509EADEEB3644A7) /* 618 */, W64LIT(0x6C1EF1D3E8EF0EDE) /* 619 */, + W64LIT(0xB9C97D43E9798FB4) /* 620 */, W64LIT(0xA2F2D784740C28A3) /* 621 */, + W64LIT(0x7B8496476197566F) /* 622 */, W64LIT(0x7A5BE3E6B65F069D) /* 623 */, + W64LIT(0xF96330ED78BE6F10) /* 624 */, W64LIT(0xEEE60DE77A076A15) /* 625 */, + W64LIT(0x2B4BEE4AA08B9BD0) /* 626 */, W64LIT(0x6A56A63EC7B8894E) /* 627 */, + W64LIT(0x02121359BA34FEF4) /* 628 */, W64LIT(0x4CBF99F8283703FC) /* 629 */, + W64LIT(0x398071350CAF30C8) /* 630 */, W64LIT(0xD0A77A89F017687A) /* 631 */, + W64LIT(0xF1C1A9EB9E423569) /* 632 */, W64LIT(0x8C7976282DEE8199) /* 633 */, + W64LIT(0x5D1737A5DD1F7ABD) /* 634 */, W64LIT(0x4F53433C09A9FA80) /* 635 */, + W64LIT(0xFA8B0C53DF7CA1D9) /* 636 */, W64LIT(0x3FD9DCBC886CCB77) /* 637 */, + W64LIT(0xC040917CA91B4720) /* 638 */, W64LIT(0x7DD00142F9D1DCDF) /* 639 */, + W64LIT(0x8476FC1D4F387B58) /* 640 */, W64LIT(0x23F8E7C5F3316503) /* 641 */, + W64LIT(0x032A2244E7E37339) /* 642 */, W64LIT(0x5C87A5D750F5A74B) /* 643 */, + W64LIT(0x082B4CC43698992E) /* 644 */, W64LIT(0xDF917BECB858F63C) /* 645 */, + W64LIT(0x3270B8FC5BF86DDA) /* 646 */, W64LIT(0x10AE72BB29B5DD76) /* 647 */, + W64LIT(0x576AC94E7700362B) /* 648 */, W64LIT(0x1AD112DAC61EFB8F) /* 649 */, + W64LIT(0x691BC30EC5FAA427) /* 650 */, W64LIT(0xFF246311CC327143) /* 651 */, + W64LIT(0x3142368E30E53206) /* 652 */, W64LIT(0x71380E31E02CA396) /* 653 */, + W64LIT(0x958D5C960AAD76F1) /* 654 */, W64LIT(0xF8D6F430C16DA536) /* 655 */, + W64LIT(0xC8FFD13F1BE7E1D2) /* 656 */, W64LIT(0x7578AE66004DDBE1) /* 657 */, + W64LIT(0x05833F01067BE646) /* 658 */, W64LIT(0xBB34B5AD3BFE586D) /* 659 */, + W64LIT(0x095F34C9A12B97F0) /* 660 */, W64LIT(0x247AB64525D60CA8) /* 661 */, + W64LIT(0xDCDBC6F3017477D1) /* 662 */, W64LIT(0x4A2E14D4DECAD24D) /* 663 */, + W64LIT(0xBDB5E6D9BE0A1EEB) /* 664 */, W64LIT(0x2A7E70F7794301AB) /* 665 */, + W64LIT(0xDEF42D8A270540FD) /* 666 */, W64LIT(0x01078EC0A34C22C1) /* 667 */, + W64LIT(0xE5DE511AF4C16387) /* 668 */, W64LIT(0x7EBB3A52BD9A330A) /* 669 */, + W64LIT(0x77697857AA7D6435) /* 670 */, W64LIT(0x004E831603AE4C32) /* 671 */, + W64LIT(0xE7A21020AD78E312) /* 672 */, W64LIT(0x9D41A70C6AB420F2) /* 673 */, + W64LIT(0x28E06C18EA1141E6) /* 674 */, W64LIT(0xD2B28CBD984F6B28) /* 675 */, + W64LIT(0x26B75F6C446E9D83) /* 676 */, W64LIT(0xBA47568C4D418D7F) /* 677 */, + W64LIT(0xD80BADBFE6183D8E) /* 678 */, W64LIT(0x0E206D7F5F166044) /* 679 */, + W64LIT(0xE258A43911CBCA3E) /* 680 */, W64LIT(0x723A1746B21DC0BC) /* 681 */, + W64LIT(0xC7CAA854F5D7CDD3) /* 682 */, W64LIT(0x7CAC32883D261D9C) /* 683 */, + W64LIT(0x7690C26423BA942C) /* 684 */, W64LIT(0x17E55524478042B8) /* 685 */, + W64LIT(0xE0BE477656A2389F) /* 686 */, W64LIT(0x4D289B5E67AB2DA0) /* 687 */, + W64LIT(0x44862B9C8FBBFD31) /* 688 */, W64LIT(0xB47CC8049D141365) /* 689 */, + W64LIT(0x822C1B362B91C793) /* 690 */, W64LIT(0x4EB14655FB13DFD8) /* 691 */, + W64LIT(0x1ECBBA0714E2A97B) /* 692 */, W64LIT(0x6143459D5CDE5F14) /* 693 */, + W64LIT(0x53A8FBF1D5F0AC89) /* 694 */, W64LIT(0x97EA04D81C5E5B00) /* 695 */, + W64LIT(0x622181A8D4FDB3F3) /* 696 */, W64LIT(0xE9BCD341572A1208) /* 697 */, + W64LIT(0x1411258643CCE58A) /* 698 */, W64LIT(0x9144C5FEA4C6E0A4) /* 699 */, + W64LIT(0x0D33D06565CF620F) /* 700 */, W64LIT(0x54A48D489F219CA1) /* 701 */, + W64LIT(0xC43E5EAC6D63C821) /* 702 */, W64LIT(0xA9728B3A72770DAF) /* 703 */, + W64LIT(0xD7934E7B20DF87EF) /* 704 */, W64LIT(0xE35503B61A3E86E5) /* 705 */, + W64LIT(0xCAE321FBC819D504) /* 706 */, W64LIT(0x129A50B3AC60BFA6) /* 707 */, + W64LIT(0xCD5E68EA7E9FB6C3) /* 708 */, W64LIT(0xB01C90199483B1C7) /* 709 */, + W64LIT(0x3DE93CD5C295376C) /* 710 */, W64LIT(0xAED52EDF2AB9AD13) /* 711 */, + W64LIT(0x2E60F512C0A07884) /* 712 */, W64LIT(0xBC3D86A3E36210C9) /* 713 */, + W64LIT(0x35269D9B163951CE) /* 714 */, W64LIT(0x0C7D6E2AD0CDB5FA) /* 715 */, + W64LIT(0x59E86297D87F5733) /* 716 */, W64LIT(0x298EF221898DB0E7) /* 717 */, + W64LIT(0x55000029D1A5AA7E) /* 718 */, W64LIT(0x8BC08AE1B5061B45) /* 719 */, + W64LIT(0xC2C31C2B6C92703A) /* 720 */, W64LIT(0x94CC596BAF25EF42) /* 721 */, + W64LIT(0x0A1D73DB22540456) /* 722 */, W64LIT(0x04B6A0F9D9C4179A) /* 723 */, + W64LIT(0xEFFDAFA2AE3D3C60) /* 724 */, W64LIT(0xF7C8075BB49496C4) /* 725 */, + W64LIT(0x9CC5C7141D1CD4E3) /* 726 */, W64LIT(0x78BD1638218E5534) /* 727 */, + W64LIT(0xB2F11568F850246A) /* 728 */, W64LIT(0xEDFABCFA9502BC29) /* 729 */, + W64LIT(0x796CE5F2DA23051B) /* 730 */, W64LIT(0xAAE128B0DC93537C) /* 731 */, + W64LIT(0x3A493DA0EE4B29AE) /* 732 */, W64LIT(0xB5DF6B2C416895D7) /* 733 */, + W64LIT(0xFCABBD25122D7F37) /* 734 */, W64LIT(0x70810B58105DC4B1) /* 735 */, + W64LIT(0xE10FDD37F7882A90) /* 736 */, W64LIT(0x524DCAB5518A3F5C) /* 737 */, + W64LIT(0x3C9E85878451255B) /* 738 */, W64LIT(0x4029828119BD34E2) /* 739 */, + W64LIT(0x74A05B6F5D3CECCB) /* 740 */, W64LIT(0xB610021542E13ECA) /* 741 */, + W64LIT(0x0FF979D12F59E2AC) /* 742 */, W64LIT(0x6037DA27E4F9CC50) /* 743 */, + W64LIT(0x5E92975A0DF1847D) /* 744 */, W64LIT(0xD66DE190D3E623FE) /* 745 */, + W64LIT(0x5032D6B87B568048) /* 746 */, W64LIT(0x9A36B7CE8235216E) /* 747 */, + W64LIT(0x80272A7A24F64B4A) /* 748 */, W64LIT(0x93EFED8B8C6916F7) /* 749 */, + W64LIT(0x37DDBFF44CCE1555) /* 750 */, W64LIT(0x4B95DB5D4B99BD25) /* 751 */, + W64LIT(0x92D3FDA169812FC0) /* 752 */, W64LIT(0xFB1A4A9A90660BB6) /* 753 */, + W64LIT(0x730C196946A4B9B2) /* 754 */, W64LIT(0x81E289AA7F49DA68) /* 755 */, + W64LIT(0x64669A0F83B1A05F) /* 756 */, W64LIT(0x27B3FF7D9644F48B) /* 757 */, + W64LIT(0xCC6B615C8DB675B3) /* 758 */, W64LIT(0x674F20B9BCEBBE95) /* 759 */, + W64LIT(0x6F31238275655982) /* 760 */, W64LIT(0x5AE488713E45CF05) /* 761 */, + W64LIT(0xBF619F9954C21157) /* 762 */, W64LIT(0xEABAC46040A8EAE9) /* 763 */, + W64LIT(0x454C6FE9F2C0C1CD) /* 764 */, W64LIT(0x419CF6496412691C) /* 765 */, + W64LIT(0xD3DC3BEF265B0F70) /* 766 */, W64LIT(0x6D0E60F5C3578A9E) /* 767 */, + W64LIT(0x5B0E608526323C55) /* 768 */, W64LIT(0x1A46C1A9FA1B59F5) /* 769 */, + W64LIT(0xA9E245A17C4C8FFA) /* 770 */, W64LIT(0x65CA5159DB2955D7) /* 771 */, + W64LIT(0x05DB0A76CE35AFC2) /* 772 */, W64LIT(0x81EAC77EA9113D45) /* 773 */, + W64LIT(0x528EF88AB6AC0A0D) /* 774 */, W64LIT(0xA09EA253597BE3FF) /* 775 */, + W64LIT(0x430DDFB3AC48CD56) /* 776 */, W64LIT(0xC4B3A67AF45CE46F) /* 777 */, + W64LIT(0x4ECECFD8FBE2D05E) /* 778 */, W64LIT(0x3EF56F10B39935F0) /* 779 */, + W64LIT(0x0B22D6829CD619C6) /* 780 */, W64LIT(0x17FD460A74DF2069) /* 781 */, + W64LIT(0x6CF8CC8E8510ED40) /* 782 */, W64LIT(0xD6C824BF3A6ECAA7) /* 783 */, + W64LIT(0x61243D581A817049) /* 784 */, W64LIT(0x048BACB6BBC163A2) /* 785 */, + W64LIT(0xD9A38AC27D44CC32) /* 786 */, W64LIT(0x7FDDFF5BAAF410AB) /* 787 */, + W64LIT(0xAD6D495AA804824B) /* 788 */, W64LIT(0xE1A6A74F2D8C9F94) /* 789 */, + W64LIT(0xD4F7851235DEE8E3) /* 790 */, W64LIT(0xFD4B7F886540D893) /* 791 */, + W64LIT(0x247C20042AA4BFDA) /* 792 */, W64LIT(0x096EA1C517D1327C) /* 793 */, + W64LIT(0xD56966B4361A6685) /* 794 */, W64LIT(0x277DA5C31221057D) /* 795 */, + W64LIT(0x94D59893A43ACFF7) /* 796 */, W64LIT(0x64F0C51CCDC02281) /* 797 */, + W64LIT(0x3D33BCC4FF6189DB) /* 798 */, W64LIT(0xE005CB184CE66AF1) /* 799 */, + W64LIT(0xFF5CCD1D1DB99BEA) /* 800 */, W64LIT(0xB0B854A7FE42980F) /* 801 */, + W64LIT(0x7BD46A6A718D4B9F) /* 802 */, W64LIT(0xD10FA8CC22A5FD8C) /* 803 */, + W64LIT(0xD31484952BE4BD31) /* 804 */, W64LIT(0xC7FA975FCB243847) /* 805 */, + W64LIT(0x4886ED1E5846C407) /* 806 */, W64LIT(0x28CDDB791EB70B04) /* 807 */, + W64LIT(0xC2B00BE2F573417F) /* 808 */, W64LIT(0x5C9590452180F877) /* 809 */, + W64LIT(0x7A6BDDFFF370EB00) /* 810 */, W64LIT(0xCE509E38D6D9D6A4) /* 811 */, + W64LIT(0xEBEB0F00647FA702) /* 812 */, W64LIT(0x1DCC06CF76606F06) /* 813 */, + W64LIT(0xE4D9F28BA286FF0A) /* 814 */, W64LIT(0xD85A305DC918C262) /* 815 */, + W64LIT(0x475B1D8732225F54) /* 816 */, W64LIT(0x2D4FB51668CCB5FE) /* 817 */, + W64LIT(0xA679B9D9D72BBA20) /* 818 */, W64LIT(0x53841C0D912D43A5) /* 819 */, + W64LIT(0x3B7EAA48BF12A4E8) /* 820 */, W64LIT(0x781E0E47F22F1DDF) /* 821 */, + W64LIT(0xEFF20CE60AB50973) /* 822 */, W64LIT(0x20D261D19DFFB742) /* 823 */, + W64LIT(0x16A12B03062A2E39) /* 824 */, W64LIT(0x1960EB2239650495) /* 825 */, + W64LIT(0x251C16FED50EB8B8) /* 826 */, W64LIT(0x9AC0C330F826016E) /* 827 */, + W64LIT(0xED152665953E7671) /* 828 */, W64LIT(0x02D63194A6369570) /* 829 */, + W64LIT(0x5074F08394B1C987) /* 830 */, W64LIT(0x70BA598C90B25CE1) /* 831 */, + W64LIT(0x794A15810B9742F6) /* 832 */, W64LIT(0x0D5925E9FCAF8C6C) /* 833 */, + W64LIT(0x3067716CD868744E) /* 834 */, W64LIT(0x910AB077E8D7731B) /* 835 */, + W64LIT(0x6A61BBDB5AC42F61) /* 836 */, W64LIT(0x93513EFBF0851567) /* 837 */, + W64LIT(0xF494724B9E83E9D5) /* 838 */, W64LIT(0xE887E1985C09648D) /* 839 */, + W64LIT(0x34B1D3C675370CFD) /* 840 */, W64LIT(0xDC35E433BC0D255D) /* 841 */, + W64LIT(0xD0AAB84234131BE0) /* 842 */, W64LIT(0x08042A50B48B7EAF) /* 843 */, + W64LIT(0x9997C4EE44A3AB35) /* 844 */, W64LIT(0x829A7B49201799D0) /* 845 */, + W64LIT(0x263B8307B7C54441) /* 846 */, W64LIT(0x752F95F4FD6A6CA6) /* 847 */, + W64LIT(0x927217402C08C6E5) /* 848 */, W64LIT(0x2A8AB754A795D9EE) /* 849 */, + W64LIT(0xA442F7552F72943D) /* 850 */, W64LIT(0x2C31334E19781208) /* 851 */, + W64LIT(0x4FA98D7CEAEE6291) /* 852 */, W64LIT(0x55C3862F665DB309) /* 853 */, + W64LIT(0xBD0610175D53B1F3) /* 854 */, W64LIT(0x46FE6CB840413F27) /* 855 */, + W64LIT(0x3FE03792DF0CFA59) /* 856 */, W64LIT(0xCFE700372EB85E8F) /* 857 */, + W64LIT(0xA7BE29E7ADBCE118) /* 858 */, W64LIT(0xE544EE5CDE8431DD) /* 859 */, + W64LIT(0x8A781B1B41F1873E) /* 860 */, W64LIT(0xA5C94C78A0D2F0E7) /* 861 */, + W64LIT(0x39412E2877B60728) /* 862 */, W64LIT(0xA1265EF3AFC9A62C) /* 863 */, + W64LIT(0xBCC2770C6A2506C5) /* 864 */, W64LIT(0x3AB66DD5DCE1CE12) /* 865 */, + W64LIT(0xE65499D04A675B37) /* 866 */, W64LIT(0x7D8F523481BFD216) /* 867 */, + W64LIT(0x0F6F64FCEC15F389) /* 868 */, W64LIT(0x74EFBE618B5B13C8) /* 869 */, + W64LIT(0xACDC82B714273E1D) /* 870 */, W64LIT(0xDD40BFE003199D17) /* 871 */, + W64LIT(0x37E99257E7E061F8) /* 872 */, W64LIT(0xFA52626904775AAA) /* 873 */, + W64LIT(0x8BBBF63A463D56F9) /* 874 */, W64LIT(0xF0013F1543A26E64) /* 875 */, + W64LIT(0xA8307E9F879EC898) /* 876 */, W64LIT(0xCC4C27A4150177CC) /* 877 */, + W64LIT(0x1B432F2CCA1D3348) /* 878 */, W64LIT(0xDE1D1F8F9F6FA013) /* 879 */, + W64LIT(0x606602A047A7DDD6) /* 880 */, W64LIT(0xD237AB64CC1CB2C7) /* 881 */, + W64LIT(0x9B938E7225FCD1D3) /* 882 */, W64LIT(0xEC4E03708E0FF476) /* 883 */, + W64LIT(0xFEB2FBDA3D03C12D) /* 884 */, W64LIT(0xAE0BCED2EE43889A) /* 885 */, + W64LIT(0x22CB8923EBFB4F43) /* 886 */, W64LIT(0x69360D013CF7396D) /* 887 */, + W64LIT(0x855E3602D2D4E022) /* 888 */, W64LIT(0x073805BAD01F784C) /* 889 */, + W64LIT(0x33E17A133852F546) /* 890 */, W64LIT(0xDF4874058AC7B638) /* 891 */, + W64LIT(0xBA92B29C678AA14A) /* 892 */, W64LIT(0x0CE89FC76CFAADCD) /* 893 */, + W64LIT(0x5F9D4E0908339E34) /* 894 */, W64LIT(0xF1AFE9291F5923B9) /* 895 */, + W64LIT(0x6E3480F60F4A265F) /* 896 */, W64LIT(0xEEBF3A2AB29B841C) /* 897 */, + W64LIT(0xE21938A88F91B4AD) /* 898 */, W64LIT(0x57DFEFF845C6D3C3) /* 899 */, + W64LIT(0x2F006B0BF62CAAF2) /* 900 */, W64LIT(0x62F479EF6F75EE78) /* 901 */, + W64LIT(0x11A55AD41C8916A9) /* 902 */, W64LIT(0xF229D29084FED453) /* 903 */, + W64LIT(0x42F1C27B16B000E6) /* 904 */, W64LIT(0x2B1F76749823C074) /* 905 */, + W64LIT(0x4B76ECA3C2745360) /* 906 */, W64LIT(0x8C98F463B91691BD) /* 907 */, + W64LIT(0x14BCC93CF1ADE66A) /* 908 */, W64LIT(0x8885213E6D458397) /* 909 */, + W64LIT(0x8E177DF0274D4711) /* 910 */, W64LIT(0xB49B73B5503F2951) /* 911 */, + W64LIT(0x10168168C3F96B6B) /* 912 */, W64LIT(0x0E3D963B63CAB0AE) /* 913 */, + W64LIT(0x8DFC4B5655A1DB14) /* 914 */, W64LIT(0xF789F1356E14DE5C) /* 915 */, + W64LIT(0x683E68AF4E51DAC1) /* 916 */, W64LIT(0xC9A84F9D8D4B0FD9) /* 917 */, + W64LIT(0x3691E03F52A0F9D1) /* 918 */, W64LIT(0x5ED86E46E1878E80) /* 919 */, + W64LIT(0x3C711A0E99D07150) /* 920 */, W64LIT(0x5A0865B20C4E9310) /* 921 */, + W64LIT(0x56FBFC1FE4F0682E) /* 922 */, W64LIT(0xEA8D5DE3105EDF9B) /* 923 */, + W64LIT(0x71ABFDB12379187A) /* 924 */, W64LIT(0x2EB99DE1BEE77B9C) /* 925 */, + W64LIT(0x21ECC0EA33CF4523) /* 926 */, W64LIT(0x59A4D7521805C7A1) /* 927 */, + W64LIT(0x3896F5EB56AE7C72) /* 928 */, W64LIT(0xAA638F3DB18F75DC) /* 929 */, + W64LIT(0x9F39358DABE9808E) /* 930 */, W64LIT(0xB7DEFA91C00B72AC) /* 931 */, + W64LIT(0x6B5541FD62492D92) /* 932 */, W64LIT(0x6DC6DEE8F92E4D5B) /* 933 */, + W64LIT(0x353F57ABC4BEEA7E) /* 934 */, W64LIT(0x735769D6DA5690CE) /* 935 */, + W64LIT(0x0A234AA642391484) /* 936 */, W64LIT(0xF6F9508028F80D9D) /* 937 */, + W64LIT(0xB8E319A27AB3F215) /* 938 */, W64LIT(0x31AD9C1151341A4D) /* 939 */, + W64LIT(0x773C22A57BEF5805) /* 940 */, W64LIT(0x45C7561A07968633) /* 941 */, + W64LIT(0xF913DA9E249DBE36) /* 942 */, W64LIT(0xDA652D9B78A64C68) /* 943 */, + W64LIT(0x4C27A97F3BC334EF) /* 944 */, W64LIT(0x76621220E66B17F4) /* 945 */, + W64LIT(0x967743899ACD7D0B) /* 946 */, W64LIT(0xF3EE5BCAE0ED6782) /* 947 */, + W64LIT(0x409F753600C879FC) /* 948 */, W64LIT(0x06D09A39B5926DB6) /* 949 */, + W64LIT(0x6F83AEB0317AC588) /* 950 */, W64LIT(0x01E6CA4A86381F21) /* 951 */, + W64LIT(0x66FF3462D19F3025) /* 952 */, W64LIT(0x72207C24DDFD3BFB) /* 953 */, + W64LIT(0x4AF6B6D3E2ECE2EB) /* 954 */, W64LIT(0x9C994DBEC7EA08DE) /* 955 */, + W64LIT(0x49ACE597B09A8BC4) /* 956 */, W64LIT(0xB38C4766CF0797BA) /* 957 */, + W64LIT(0x131B9373C57C2A75) /* 958 */, W64LIT(0xB1822CCE61931E58) /* 959 */, + W64LIT(0x9D7555B909BA1C0C) /* 960 */, W64LIT(0x127FAFDD937D11D2) /* 961 */, + W64LIT(0x29DA3BADC66D92E4) /* 962 */, W64LIT(0xA2C1D57154C2ECBC) /* 963 */, + W64LIT(0x58C5134D82F6FE24) /* 964 */, W64LIT(0x1C3AE3515B62274F) /* 965 */, + W64LIT(0xE907C82E01CB8126) /* 966 */, W64LIT(0xF8ED091913E37FCB) /* 967 */, + W64LIT(0x3249D8F9C80046C9) /* 968 */, W64LIT(0x80CF9BEDE388FB63) /* 969 */, + W64LIT(0x1881539A116CF19E) /* 970 */, W64LIT(0x5103F3F76BD52457) /* 971 */, + W64LIT(0x15B7E6F5AE47F7A8) /* 972 */, W64LIT(0xDBD7C6DED47E9CCF) /* 973 */, + W64LIT(0x44E55C410228BB1A) /* 974 */, W64LIT(0xB647D4255EDB4E99) /* 975 */, + W64LIT(0x5D11882BB8AAFC30) /* 976 */, W64LIT(0xF5098BBB29D3212A) /* 977 */, + W64LIT(0x8FB5EA14E90296B3) /* 978 */, W64LIT(0x677B942157DD025A) /* 979 */, + W64LIT(0xFB58E7C0A390ACB5) /* 980 */, W64LIT(0x89D3674C83BD4A01) /* 981 */, + W64LIT(0x9E2DA4DF4BF3B93B) /* 982 */, W64LIT(0xFCC41E328CAB4829) /* 983 */, + W64LIT(0x03F38C96BA582C52) /* 984 */, W64LIT(0xCAD1BDBD7FD85DB2) /* 985 */, + W64LIT(0xBBB442C16082AE83) /* 986 */, W64LIT(0xB95FE86BA5DA9AB0) /* 987 */, + W64LIT(0xB22E04673771A93F) /* 988 */, W64LIT(0x845358C9493152D8) /* 989 */, + W64LIT(0xBE2A488697B4541E) /* 990 */, W64LIT(0x95A2DC2DD38E6966) /* 991 */, + W64LIT(0xC02C11AC923C852B) /* 992 */, W64LIT(0x2388B1990DF2A87B) /* 993 */, + W64LIT(0x7C8008FA1B4F37BE) /* 994 */, W64LIT(0x1F70D0C84D54E503) /* 995 */, + W64LIT(0x5490ADEC7ECE57D4) /* 996 */, W64LIT(0x002B3C27D9063A3A) /* 997 */, + W64LIT(0x7EAEA3848030A2BF) /* 998 */, W64LIT(0xC602326DED2003C0) /* 999 */, + W64LIT(0x83A7287D69A94086) /* 1000 */, W64LIT(0xC57A5FCB30F57A8A) /* 1001 */, + W64LIT(0xB56844E479EBE779) /* 1002 */, W64LIT(0xA373B40F05DCBCE9) /* 1003 */, + W64LIT(0xD71A786E88570EE2) /* 1004 */, W64LIT(0x879CBACDBDE8F6A0) /* 1005 */, + W64LIT(0x976AD1BCC164A32F) /* 1006 */, W64LIT(0xAB21E25E9666D78B) /* 1007 */, + W64LIT(0x901063AAE5E5C33C) /* 1008 */, W64LIT(0x9818B34448698D90) /* 1009 */, + W64LIT(0xE36487AE3E1E8ABB) /* 1010 */, W64LIT(0xAFBDF931893BDCB4) /* 1011 */, + W64LIT(0x6345A0DC5FBBD519) /* 1012 */, W64LIT(0x8628FE269B9465CA) /* 1013 */, + W64LIT(0x1E5D01603F9C51EC) /* 1014 */, W64LIT(0x4DE44006A15049B7) /* 1015 */, + W64LIT(0xBF6C70E5F776CBB1) /* 1016 */, W64LIT(0x411218F2EF552BED) /* 1017 */, + W64LIT(0xCB0C0708705A36A3) /* 1018 */, W64LIT(0xE74D14754F986044) /* 1019 */, + W64LIT(0xCD56D9430EA8280E) /* 1020 */, W64LIT(0xC12591D7535F5065) /* 1021 */, + W64LIT(0xC83223F1720AEF96) /* 1022 */, W64LIT(0xC3A0396F7363A51F) /* 1023 */, + W64LIT(0xffffffffffffffff), + W64LIT(0xA5A5A5A5A5A5A5A5), + W64LIT(0x0123456789ABCDEF), +}; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/trap.h b/external/ours/library/crypto/src/shared/original/trap.h new file mode 100755 index 000000000..15360b562 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/trunhash.h b/external/ours/library/crypto/src/shared/original/trunhash.h new file mode 100755 index 000000000..36df5bebe --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/ttmac.cpp b/external/ours/library/crypto/src/shared/original/ttmac.cpp new file mode 100755 index 000000000..db7e3485f --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/ttmac.cpp @@ -0,0 +1,348 @@ +// ttmac.cpp - written and placed in the public domain by Kevin Springle + +#include "pch.h" +#include "ttmac.h" +#include "misc.h" + +ANONYMOUS_NAMESPACE_BEGIN + +using CryptoPP::word32; +using CryptoPP::rotlVariable; +using CryptoPP::rotlConstant; + +// RIPEMD-160 definitions used by Two-Track-MAC +word32 F(word32 x, word32 y, word32 z) { return x ^ y ^ z; } +word32 G(word32 x, word32 y, word32 z) { return z ^ (x & (y^z)); } +word32 H(word32 x, word32 y, word32 z) { return z ^ (x | ~y); } +word32 I(word32 x, word32 y, word32 z) { return y ^ (z & (x^y)); } +word32 J(word32 x, word32 y, word32 z) { return x ^ (y | ~z); } + +template +void Subround(Fn fn, word32& a, word32 b, word32& c, word32 d, word32 e, word32 x, word32 k) +{ + a += fn(b, c, d) + x + k; + a = rotlVariable(a, S) + e; + c = rotlConstant<10>(c); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +const unsigned int k0 = 0; +const unsigned int k1 = 0x5a827999; +const unsigned int k2 = 0x6ed9eba1; +const unsigned int k3 = 0x8f1bbcdc; +const unsigned int k4 = 0xa953fd4e; +const unsigned int k5 = 0x50a28be6; +const unsigned int k6 = 0x5c4dd124; +const unsigned int k7 = 0x6d703ef3; +const unsigned int k8 = 0x7a6d76e9; +const unsigned int k9 = 0; + +void TTMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &) +{ + AssertValidKeyLength(keylength); + + memcpy(m_key, userKey, KEYLENGTH); + CorrectEndianess(m_key, m_key, KEYLENGTH); + + Init(); +} + +void TTMAC_Base::Init() +{ + m_digest[0] = m_digest[5] = m_key[0]; + m_digest[1] = m_digest[6] = m_key[1]; + m_digest[2] = m_digest[7] = m_key[2]; + m_digest[3] = m_digest[8] = m_key[3]; + m_digest[4] = m_digest[9] = m_key[4]; +} + +void TTMAC_Base::TruncatedFinal(byte *hash, size_t size) +{ + PadLastBlock(BlockSize() - 2*sizeof(HashWordType)); + CorrectEndianess(m_data, m_data, BlockSize() - 2*sizeof(HashWordType)); + + m_data[m_data.size()-2] = GetBitCountLo(); + m_data[m_data.size()-1] = GetBitCountHi(); + + Transform(m_digest, m_data, true); + + word32 t2 = m_digest[2]; + word32 t3 = m_digest[3]; + if (size != DIGESTSIZE) + { + switch (size) + { + case 16: + m_digest[3] += m_digest[1] + m_digest[4]; + // fall through + case 12: + m_digest[2] += m_digest[0] + t3; + // fall through + case 8: + m_digest[0] += m_digest[1] + t3; + m_digest[1] += m_digest[4] + t2; + break; + + case 4: + m_digest[0] += + m_digest[1] + + m_digest[2] + + m_digest[3] + + m_digest[4]; + break; + + case 0: + // Used by HashTransformation::Restart() + break; + + default: + throw InvalidArgument("TTMAC_Base: can't truncate a Two-Track-MAC 20 byte digest to " + IntToString(size) + " bytes"); + break; + } + } + + CorrectEndianess(m_digest, m_digest, size); + memcpy(hash, m_digest, size); + + Restart(); // reinit for next use +} + +void TTMAC_Base::Transform(word32 *digest, const word32 *X, bool last) +{ + word32 a1, b1, c1, d1, e1, a2, b2, c2, d2, e2; + word32 *trackA, *trackB; + + if (!last) + { + trackA = digest; + trackB = digest+5; + } + else + { + trackB = digest; + trackA = digest+5; + } + a1 = trackA[0]; + b1 = trackA[1]; + c1 = trackA[2]; + d1 = trackA[3]; + e1 = trackA[4]; + a2 = trackB[0]; + b2 = trackB[1]; + c2 = trackB[2]; + d2 = trackB[3]; + e2 = trackB[4]; + + Subround<11>(F, a1, b1, c1, d1, e1, X[ 0], k0); + Subround<14>(F, e1, a1, b1, c1, d1, X[ 1], k0); + Subround<15>(F, d1, e1, a1, b1, c1, X[ 2], k0); + Subround<12>(F, c1, d1, e1, a1, b1, X[ 3], k0); + Subround< 5>(F, b1, c1, d1, e1, a1, X[ 4], k0); + Subround< 8>(F, a1, b1, c1, d1, e1, X[ 5], k0); + Subround< 7>(F, e1, a1, b1, c1, d1, X[ 6], k0); + Subround< 9>(F, d1, e1, a1, b1, c1, X[ 7], k0); + Subround<11>(F, c1, d1, e1, a1, b1, X[ 8], k0); + Subround<13>(F, b1, c1, d1, e1, a1, X[ 9], k0); + Subround<14>(F, a1, b1, c1, d1, e1, X[10], k0); + Subround<15>(F, e1, a1, b1, c1, d1, X[11], k0); + Subround< 6>(F, d1, e1, a1, b1, c1, X[12], k0); + Subround< 7>(F, c1, d1, e1, a1, b1, X[13], k0); + Subround< 9>(F, b1, c1, d1, e1, a1, X[14], k0); + Subround< 8>(F, a1, b1, c1, d1, e1, X[15], k0); + + Subround< 7>(G, e1, a1, b1, c1, d1, X[ 7], k1); + Subround< 6>(G, d1, e1, a1, b1, c1, X[ 4], k1); + Subround< 8>(G, c1, d1, e1, a1, b1, X[13], k1); + Subround<13>(G, b1, c1, d1, e1, a1, X[ 1], k1); + Subround<11>(G, a1, b1, c1, d1, e1, X[10], k1); + Subround< 9>(G, e1, a1, b1, c1, d1, X[ 6], k1); + Subround< 7>(G, d1, e1, a1, b1, c1, X[15], k1); + Subround<15>(G, c1, d1, e1, a1, b1, X[ 3], k1); + Subround< 7>(G, b1, c1, d1, e1, a1, X[12], k1); + Subround<12>(G, a1, b1, c1, d1, e1, X[ 0], k1); + Subround<15>(G, e1, a1, b1, c1, d1, X[ 9], k1); + Subround< 9>(G, d1, e1, a1, b1, c1, X[ 5], k1); + Subround<11>(G, c1, d1, e1, a1, b1, X[ 2], k1); + Subround< 7>(G, b1, c1, d1, e1, a1, X[14], k1); + Subround<13>(G, a1, b1, c1, d1, e1, X[11], k1); + Subround<12>(G, e1, a1, b1, c1, d1, X[ 8], k1); + + Subround<11>(H, d1, e1, a1, b1, c1, X[ 3], k2); + Subround<13>(H, c1, d1, e1, a1, b1, X[10], k2); + Subround< 6>(H, b1, c1, d1, e1, a1, X[14], k2); + Subround< 7>(H, a1, b1, c1, d1, e1, X[ 4], k2); + Subround<14>(H, e1, a1, b1, c1, d1, X[ 9], k2); + Subround< 9>(H, d1, e1, a1, b1, c1, X[15], k2); + Subround<13>(H, c1, d1, e1, a1, b1, X[ 8], k2); + Subround<15>(H, b1, c1, d1, e1, a1, X[ 1], k2); + Subround<14>(H, a1, b1, c1, d1, e1, X[ 2], k2); + Subround< 8>(H, e1, a1, b1, c1, d1, X[ 7], k2); + Subround<13>(H, d1, e1, a1, b1, c1, X[ 0], k2); + Subround< 6>(H, c1, d1, e1, a1, b1, X[ 6], k2); + Subround< 5>(H, b1, c1, d1, e1, a1, X[13], k2); + Subround<12>(H, a1, b1, c1, d1, e1, X[11], k2); + Subround< 7>(H, e1, a1, b1, c1, d1, X[ 5], k2); + Subround< 5>(H, d1, e1, a1, b1, c1, X[12], k2); + + Subround<11>(I, c1, d1, e1, a1, b1, X[ 1], k3); + Subround<12>(I, b1, c1, d1, e1, a1, X[ 9], k3); + Subround<14>(I, a1, b1, c1, d1, e1, X[11], k3); + Subround<15>(I, e1, a1, b1, c1, d1, X[10], k3); + Subround<14>(I, d1, e1, a1, b1, c1, X[ 0], k3); + Subround<15>(I, c1, d1, e1, a1, b1, X[ 8], k3); + Subround< 9>(I, b1, c1, d1, e1, a1, X[12], k3); + Subround< 8>(I, a1, b1, c1, d1, e1, X[ 4], k3); + Subround< 9>(I, e1, a1, b1, c1, d1, X[13], k3); + Subround<14>(I, d1, e1, a1, b1, c1, X[ 3], k3); + Subround< 5>(I, c1, d1, e1, a1, b1, X[ 7], k3); + Subround< 6>(I, b1, c1, d1, e1, a1, X[15], k3); + Subround< 8>(I, a1, b1, c1, d1, e1, X[14], k3); + Subround< 6>(I, e1, a1, b1, c1, d1, X[ 5], k3); + Subround< 5>(I, d1, e1, a1, b1, c1, X[ 6], k3); + Subround<12>(I, c1, d1, e1, a1, b1, X[ 2], k3); + + Subround< 9>(J, b1, c1, d1, e1, a1, X[ 4], k4); + Subround<15>(J, a1, b1, c1, d1, e1, X[ 0], k4); + Subround< 5>(J, e1, a1, b1, c1, d1, X[ 5], k4); + Subround<11>(J, d1, e1, a1, b1, c1, X[ 9], k4); + Subround< 6>(J, c1, d1, e1, a1, b1, X[ 7], k4); + Subround< 8>(J, b1, c1, d1, e1, a1, X[12], k4); + Subround<13>(J, a1, b1, c1, d1, e1, X[ 2], k4); + Subround<12>(J, e1, a1, b1, c1, d1, X[10], k4); + Subround< 5>(J, d1, e1, a1, b1, c1, X[14], k4); + Subround<12>(J, c1, d1, e1, a1, b1, X[ 1], k4); + Subround<13>(J, b1, c1, d1, e1, a1, X[ 3], k4); + Subround<14>(J, a1, b1, c1, d1, e1, X[ 8], k4); + Subround<11>(J, e1, a1, b1, c1, d1, X[11], k4); + Subround< 8>(J, d1, e1, a1, b1, c1, X[ 6], k4); + Subround< 5>(J, c1, d1, e1, a1, b1, X[15], k4); + Subround< 6>(J, b1, c1, d1, e1, a1, X[13], k4); + + Subround< 8>(J, a2, b2, c2, d2, e2, X[ 5], k5); + Subround< 9>(J, e2, a2, b2, c2, d2, X[14], k5); + Subround< 9>(J, d2, e2, a2, b2, c2, X[ 7], k5); + Subround<11>(J, c2, d2, e2, a2, b2, X[ 0], k5); + Subround<13>(J, b2, c2, d2, e2, a2, X[ 9], k5); + Subround<15>(J, a2, b2, c2, d2, e2, X[ 2], k5); + Subround<15>(J, e2, a2, b2, c2, d2, X[11], k5); + Subround< 5>(J, d2, e2, a2, b2, c2, X[ 4], k5); + Subround< 7>(J, c2, d2, e2, a2, b2, X[13], k5); + Subround< 7>(J, b2, c2, d2, e2, a2, X[ 6], k5); + Subround< 8>(J, a2, b2, c2, d2, e2, X[15], k5); + Subround<11>(J, e2, a2, b2, c2, d2, X[ 8], k5); + Subround<14>(J, d2, e2, a2, b2, c2, X[ 1], k5); + Subround<14>(J, c2, d2, e2, a2, b2, X[10], k5); + Subround<12>(J, b2, c2, d2, e2, a2, X[ 3], k5); + Subround< 6>(J, a2, b2, c2, d2, e2, X[12], k5); + + Subround< 9>(I, e2, a2, b2, c2, d2, X[ 6], k6); + Subround<13>(I, d2, e2, a2, b2, c2, X[11], k6); + Subround<15>(I, c2, d2, e2, a2, b2, X[ 3], k6); + Subround< 7>(I, b2, c2, d2, e2, a2, X[ 7], k6); + Subround<12>(I, a2, b2, c2, d2, e2, X[ 0], k6); + Subround< 8>(I, e2, a2, b2, c2, d2, X[13], k6); + Subround< 9>(I, d2, e2, a2, b2, c2, X[ 5], k6); + Subround<11>(I, c2, d2, e2, a2, b2, X[10], k6); + Subround< 7>(I, b2, c2, d2, e2, a2, X[14], k6); + Subround< 7>(I, a2, b2, c2, d2, e2, X[15], k6); + Subround<12>(I, e2, a2, b2, c2, d2, X[ 8], k6); + Subround< 7>(I, d2, e2, a2, b2, c2, X[12], k6); + Subround< 6>(I, c2, d2, e2, a2, b2, X[ 4], k6); + Subround<15>(I, b2, c2, d2, e2, a2, X[ 9], k6); + Subround<13>(I, a2, b2, c2, d2, e2, X[ 1], k6); + Subround<11>(I, e2, a2, b2, c2, d2, X[ 2], k6); + + Subround< 9>(H, d2, e2, a2, b2, c2, X[15], k7); + Subround< 7>(H, c2, d2, e2, a2, b2, X[ 5], k7); + Subround<15>(H, b2, c2, d2, e2, a2, X[ 1], k7); + Subround<11>(H, a2, b2, c2, d2, e2, X[ 3], k7); + Subround< 8>(H, e2, a2, b2, c2, d2, X[ 7], k7); + Subround< 6>(H, d2, e2, a2, b2, c2, X[14], k7); + Subround< 6>(H, c2, d2, e2, a2, b2, X[ 6], k7); + Subround<14>(H, b2, c2, d2, e2, a2, X[ 9], k7); + Subround<12>(H, a2, b2, c2, d2, e2, X[11], k7); + Subround<13>(H, e2, a2, b2, c2, d2, X[ 8], k7); + Subround< 5>(H, d2, e2, a2, b2, c2, X[12], k7); + Subround<14>(H, c2, d2, e2, a2, b2, X[ 2], k7); + Subround<13>(H, b2, c2, d2, e2, a2, X[10], k7); + Subround<13>(H, a2, b2, c2, d2, e2, X[ 0], k7); + Subround< 7>(H, e2, a2, b2, c2, d2, X[ 4], k7); + Subround< 5>(H, d2, e2, a2, b2, c2, X[13], k7); + + Subround<15>(G, c2, d2, e2, a2, b2, X[ 8], k8); + Subround< 5>(G, b2, c2, d2, e2, a2, X[ 6], k8); + Subround< 8>(G, a2, b2, c2, d2, e2, X[ 4], k8); + Subround<11>(G, e2, a2, b2, c2, d2, X[ 1], k8); + Subround<14>(G, d2, e2, a2, b2, c2, X[ 3], k8); + Subround<14>(G, c2, d2, e2, a2, b2, X[11], k8); + Subround< 6>(G, b2, c2, d2, e2, a2, X[15], k8); + Subround<14>(G, a2, b2, c2, d2, e2, X[ 0], k8); + Subround< 6>(G, e2, a2, b2, c2, d2, X[ 5], k8); + Subround< 9>(G, d2, e2, a2, b2, c2, X[12], k8); + Subround<12>(G, c2, d2, e2, a2, b2, X[ 2], k8); + Subround< 9>(G, b2, c2, d2, e2, a2, X[13], k8); + Subround<12>(G, a2, b2, c2, d2, e2, X[ 9], k8); + Subround< 5>(G, e2, a2, b2, c2, d2, X[ 7], k8); + Subround<15>(G, d2, e2, a2, b2, c2, X[10], k8); + Subround< 8>(G, c2, d2, e2, a2, b2, X[14], k8); + + Subround< 8>(F, b2, c2, d2, e2, a2, X[12], k9); + Subround< 5>(F, a2, b2, c2, d2, e2, X[15], k9); + Subround<12>(F, e2, a2, b2, c2, d2, X[10], k9); + Subround< 9>(F, d2, e2, a2, b2, c2, X[ 4], k9); + Subround<12>(F, c2, d2, e2, a2, b2, X[ 1], k9); + Subround< 5>(F, b2, c2, d2, e2, a2, X[ 5], k9); + Subround<14>(F, a2, b2, c2, d2, e2, X[ 8], k9); + Subround< 6>(F, e2, a2, b2, c2, d2, X[ 7], k9); + Subround< 8>(F, d2, e2, a2, b2, c2, X[ 6], k9); + Subround<13>(F, c2, d2, e2, a2, b2, X[ 2], k9); + Subround< 6>(F, b2, c2, d2, e2, a2, X[13], k9); + Subround< 5>(F, a2, b2, c2, d2, e2, X[14], k9); + Subround<15>(F, e2, a2, b2, c2, d2, X[ 0], k9); + Subround<13>(F, d2, e2, a2, b2, c2, X[ 3], k9); + Subround<11>(F, c2, d2, e2, a2, b2, X[ 9], k9); + Subround<11>(F, b2, c2, d2, e2, a2, X[11], k9); + + a1 -= trackA[0]; + b1 -= trackA[1]; + c1 -= trackA[2]; + d1 -= trackA[3]; + e1 -= trackA[4]; + a2 -= trackB[0]; + b2 -= trackB[1]; + c2 -= trackB[2]; + d2 -= trackB[3]; + e2 -= trackB[4]; + + if (!last) + { + trackA[0] = (b1 + e1) - d2; + trackA[1] = c1 - e2; + trackA[2] = d1 - a2; + trackA[3] = e1 - b2; + trackA[4] = a1 - c2; + trackB[0] = d1 - e2; + trackB[1] = (e1 + c1) - a2; + trackB[2] = a1 - b2; + trackB[3] = b1 - c2; + trackB[4] = c1 - d2; + } + else + { + trackB[0] = a2 - a1; + trackB[1] = b2 - b1; + trackB[2] = c2 - c1; + trackB[3] = d2 - d1; + trackB[4] = e2 - e1; + trackA[0] = 0; + trackA[1] = 0; + trackA[2] = 0; + trackA[3] = 0; + trackA[4] = 0; + } +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/ttmac.h b/external/ours/library/crypto/src/shared/original/ttmac.h new file mode 100755 index 000000000..d50b0038c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/tweetnacl.cpp b/external/ours/library/crypto/src/shared/original/tweetnacl.cpp new file mode 100755 index 000000000..71d80e707 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/tweetnacl.cpp @@ -0,0 +1,924 @@ +// tweetnacl.cpp - modified tweetnacl.c placed in public domain by Jeffrey Walton. +// The NaCl library and tweetnacl.c is public domain source code +// written by Daniel J. Bernstein, Bernard van Gastel, Wesley +// Janssen, Tanja Lange, Peter Schwabe and Sjaak Smetsers. + +#include "pch.h" +#include "config.h" +#include "naclite.h" +#include "misc.h" +#include "osrng.h" +#include "stdcpp.h" + +// Don't destroy const time properties when squashing warnings. +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4146 4242 4244 4245) +#endif + +// Can't use GetAlignmentOf() because of C++11 and constexpr +// Can use 'const unsigned int' because of MSVC 2013 +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +# define ALIGN_SPEC 16 +#else +# define ALIGN_SPEC 4 +#endif + +#ifndef CRYPTOPP_DISABLE_NACL + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(NaCl) + +typedef sword64 gf[16]; + +static const byte + _0[32] = {0}, + _9[32] = {9}; + +static const gf + gf0 = {0}, + gf1 = {1}, + _121665 = {0xDB41,1}, + D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203}, + D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406}, + X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169}, + Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666}, + I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; + +// Added by Crypto++ for TweetNaCl +static void randombytes(byte * block, word64 size) +{ + DefaultAutoSeededRNG prng; + prng.GenerateBlock(block, (size_t)size); +} + +static word32 L32(word32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); } + +static word32 ld32(const byte *x) +{ + word32 u = x[3]; + u = (u<<8)|x[2]; + u = (u<<8)|x[1]; + return (u<<8)|x[0]; +} + +static word64 dl64(const byte *x) +{ + word64 i,u=0; + for(i=0; i<8; ++i) u=(u<<8)|x[i]; + return u; +} + +static void st32(byte *x,word32 u) +{ + int i; + for(i=0; i<4; ++i) { x[i] = u; u >>= 8; } +} + +static void ts64(byte *x,word64 u) +{ + int i; + for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; } +} + +// Extra cast due to Coverity CID 186949 +static int verify_n(const byte *x,const byte *y,word32 n) +{ + word32 i,d = 0; + for(i=0; i> 8)) - 1; +} + +int crypto_verify_16(const byte *x,const byte *y) +{ + return verify_n(x,y,16); +} + +int crypto_verify_32(const byte *x,const byte *y) +{ + return verify_n(x,y,32); +} + +static void core(byte *out,const byte *in,const byte *k,const byte *c,int h) +{ + word32 w[16],x[16],y[16],t[4]; + int i,j,m; + + for(i=0; i<4; ++i) { + x[5*i] = ld32(c+4*i); + x[1+i] = ld32(k+4*i); + x[6+i] = ld32(in+4*i); + x[11+i] = ld32(k+16+4*i); + } + + for(i=0; i<16; ++i) y[i] = x[i]; + + for(i=0; i<20; ++i) { + for(j=0; j<4; ++j) { + for(m=0; m<4; ++m) t[m] = x[(5*j+4*m)%16]; + t[1] ^= L32(t[0]+t[3], 7); + t[2] ^= L32(t[1]+t[0], 9); + t[3] ^= L32(t[2]+t[1],13); + t[0] ^= L32(t[3]+t[2],18); + for(m=0; m<4; ++m) w[4*j+(j+m)%4] = t[m]; + } + for(m=0; m<16; ++m) x[m] = w[m]; + } + + if (h) { + for(i=0; i<16; ++i) x[i] += y[i]; + for(i=0; i<4; ++i) { + x[5*i] -= ld32(c+4*i); + x[6+i] -= ld32(in+4*i); + } + for(i=0; i<4; ++i) { + st32(out+4*i,x[5*i]); + st32(out+16+4*i,x[6+i]); + } + } else + for(i=0; i<16; ++i) st32(out + 4 * i,x[i] + y[i]); +} + +int crypto_core_salsa20(byte *out,const byte *in,const byte *k,const byte *c) +{ + core(out,in,k,c,0); + return 0; +} + +int crypto_core_hsalsa20(byte *out,const byte *in,const byte *k,const byte *c) +{ + core(out,in,k,c,1); + return 0; +} + +static const byte sigma[16] = {0x65,0x78,0x70,0x61,0x6E,0x64,0x20,0x33,0x32,0x2D,0x62,0x79,0x74,0x65,0x20,0x6B}; + +int crypto_stream_salsa20_xor(byte *c,const byte *m,word64 b,const byte *n,const byte *k) +{ + byte z[16],x[64]; + word32 u,i; + if (!b) return 0; + for(i=0; i<16; ++i) z[i] = 0; + for(i=0; i<8; ++i) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x,z,k,sigma); + for(i=0; i<64; ++i) c[i] = (m?m[i]:0) ^ x[i]; + u = 1; + for (i = 8;i < 16;++i) { + u += (word32) z[i]; + z[i] = u; + u >>= 8; + } + b -= 64; + c += 64; + if (m) m += 64; + } + if (b) { + crypto_core_salsa20(x,z,k,sigma); + for(i=0; i>= 8; + } +} + +static const word32 minusp[17] = { + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 +} ; + +int crypto_onetimeauth(byte *out,const byte *m,word64 n,const byte *k) +{ + word32 s,i,j,u,x[17],r[17],h[17],c[17],g[17]; + + for(j=0; j<17; ++j) r[j]=h[j]=0; + for(j=0; j<16; ++j) r[j]=k[j]; + r[3]&=15; + r[4]&=252; + r[7]&=15; + r[8]&=252; + r[11]&=15; + r[12]&=252; + r[15]&=15; + + while (n > 0) { + for(j=0; j<17; ++j) c[j] = 0; + for (j = 0;(j < 16) && (j < n);++j) c[j] = m[j]; + c[j] = 1; + m += j; n -= j; + add1305(h,c); + for(i=0; i<17; ++i) { + x[i] = 0; + for(j=0; j<17; ++j) x[i] += h[j] * ((j <= i) ? r[i - j] : 320 * r[i + 17 - j]); + } + for(i=0; i<17; ++i) h[i] = x[i]; + u = 0; + for(j=0; j<16; ++j) { + u += h[j]; + h[j] = u & 255; + u >>= 8; + } + u += h[16]; h[16] = u & 3; + u = 5 * (u >> 2); + for(j=0; j<16; ++j) { + u += h[j]; + h[j] = u & 255; + u >>= 8; + } + u += h[16]; h[16] = u; + } + + for(j=0; j<17; ++j) g[j] = h[j]; + add1305(h,minusp); + s = -(h[16] >> 7); + for(j=0; j<17; ++j) h[j] ^= s & (g[j] ^ h[j]); + + for(j=0; j<16; ++j) c[j] = k[j + 16]; + c[16] = 0; + add1305(h,c); + for(j=0; j<16; ++j) out[j] = h[j]; + return 0; +} + +int crypto_onetimeauth_verify(const byte *h,const byte *m,word64 n,const byte *k) +{ + byte x[16]; + crypto_onetimeauth(x,m,n,k); + return crypto_verify_16(h,x); +} + +int crypto_secretbox(byte *c,const byte *m,word64 d,const byte *n,const byte *k) +{ + int i; + if (d < 32) return -1; + crypto_stream_xor(c,m,d,n,k); + crypto_onetimeauth(c + 16,c + 32,d - 32,c); + for(i=0; i<16; ++i) c[i] = 0; + return 0; +} + +int crypto_secretbox_open(byte *m,const byte *c,word64 d,const byte *n,const byte *k) +{ + int i; + byte x[32]; + if (d < 32) return -1; + crypto_stream(x,32,n,k); + if (crypto_onetimeauth_verify(c + 16,c + 32,d - 32,x) != 0) return -1; + crypto_stream_xor(m,c,d,n,k); + for(i=0; i<32; ++i) m[i] = 0; + return 0; +} + +static void set25519(gf r, const gf a) +{ + int i; + for(i=0; i<16; ++i) r[i]=a[i]; +} + +static void car25519(gf o) +{ + int i; + sword64 c; + for(i=0; i<16; ++i) { + o[i]+=(1LL<<16); + c=o[i]>>16; + o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15); + o[i]-=((word64)c)<<16; + } +} + +static void sel25519(gf p,gf q,int b) +{ + sword64 t,i,c=~(b-1); + for(i=0; i<16; ++i) { + t= c&(p[i]^q[i]); + p[i]^=t; + q[i]^=t; + } +} + +static void pack25519(byte *o,const gf n) +{ + int i,j,b; + gf m,t; + for(i=0; i<16; ++i) t[i]=n[i]; + car25519(t); + car25519(t); + car25519(t); + for(j=0; j<2; ++j) { + m[0]=t[0]-0xffed; + for(i=1;i<15;i++) { + m[i]=t[i]-0xffff-((m[i-1]>>16)&1); + m[i-1]&=0xffff; + } + m[15]=t[15]-0x7fff-((m[14]>>16)&1); + b=(m[15]>>16)&1; + m[14]&=0xffff; + sel25519(t,m,1-b); + } + for(i=0; i<16; ++i) { + o[2*i]=t[i]&0xff; + o[2*i+1]=t[i]>>8; + } +} + +static int neq25519(const gf a, const gf b) +{ + byte c[32],d[32]; + pack25519(c,a); + pack25519(d,b); + return crypto_verify_32(c,d); +} + +static byte par25519(const gf a) +{ + byte d[32]; + pack25519(d,a); + return d[0]&1; +} + +static void unpack25519(gf o, const byte *n) +{ + int i; + for(i=0; i<16; ++i) o[i]=n[2*i]+((sword64)n[2*i+1]<<8); + o[15]&=0x7fff; +} + +static void A(gf o,const gf a,const gf b) +{ + int i; + for(i=0; i<16; ++i) o[i]=a[i]+b[i]; +} + +static void Z(gf o,const gf a,const gf b) +{ + int i; + for(i=0; i<16; ++i) o[i]=a[i]-b[i]; +} + +static void M(gf o,const gf a,const gf b) +{ + sword64 i,j,t[31]; + for(i=0; i<31; ++i) t[i]=0; + for(i=0; i<16; ++i) for(j=0; j<16; ++j) t[i+j]+=a[i]*b[j]; + for(i=0; i<15; ++i) t[i]+=38*t[i+16]; + for(i=0; i<16; ++i) o[i]=t[i]; + car25519(o); + car25519(o); +} + +static void S(gf o,const gf a) +{ + M(o,a,a); +} + +static void inv25519(gf o,const gf i) +{ + gf c; + int a; + for(a=0; a<16; ++a) c[a]=i[a]; + for(a=253;a>=0;a--) { + S(c,c); + if(a!=2&&a!=4) M(c,c,i); + } + for(a=0; a<16; ++a) o[a]=c[a]; +} + +static void pow2523(gf o,const gf i) +{ + gf c; + int a; + for(a=0; a<16; ++a) c[a]=i[a]; + for(a=250;a>=0;a--) { + S(c,c); + if(a!=1) M(c,c,i); + } + for(a=0; a<16; ++a) o[a]=c[a]; +} + +// https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c +static int has_small_order(const byte s[32]) +{ + CRYPTOPP_ALIGN_DATA(ALIGN_SPEC) + const byte blacklist[][32] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 }, + { 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 }, + { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + { 0xcd, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x80 }, + { 0x4c, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0xd7 }, + { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } + }; + CRYPTOPP_COMPILE_ASSERT(12 == COUNTOF(blacklist)); + + byte c[12] = { 0 }; + for (size_t j = 0; j < 32; j++) { + for (size_t i = 0; i < COUNTOF(blacklist); i++) { + c[i] |= s[j] ^ blacklist[i][j]; + } + } + + unsigned int k = 0; + for (size_t i = 0; i < COUNTOF(blacklist); i++) { + k |= (c[i] - 1); + } + + return (int) ((k >> 8) & 1); +} + +int crypto_scalarmult(byte *q,const byte *n,const byte *p) +{ + byte z[32]; + sword64 x[80],r,i; + gf a,b,c,d,e,f; + for(i=0; i<31; ++i) z[i]=n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for(i=0; i<16; ++i) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for(i=254;i>=0;--i) { + r=(z[i>>3]>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for(i=0; i<16; ++i) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + inv25519(x+32,x+32); + M(x+16,x+16,x+32); + pack25519(q,x+16); + return 0; +} + +int crypto_scalarmult_base(byte *q,const byte *n) +{ + return crypto_scalarmult(q,n,_9); +} + +int crypto_box_keypair(byte *y,byte *x) +{ + randombytes(x,32); + return crypto_scalarmult_base(y,x); +} + +// Avoid small order elements. Also see https://eprint.iacr.org/2017/806.pdf +// and https://github.com/jedisct1/libsodium/commit/675149b9b8b66ff4. +int crypto_box_beforenm(byte *k,const byte *y,const byte *x) +{ + byte s[32]; + if(crypto_scalarmult(s,x,y) != 0) return -1; + if(has_small_order(s) != 0) return -1; + return crypto_core_hsalsa20(k,_0,s,sigma); +} + +// Allow small order elements. Also see https://eprint.iacr.org/2017/806.pdf +int crypto_box_beforenm_unchecked(byte *k,const byte *y,const byte *x) +{ + byte s[32]; + if(crypto_scalarmult(s,x,y) != 0) return -1; + return crypto_core_hsalsa20(k,_0,s,sigma); +} + +int crypto_box_afternm(byte *c,const byte *m,word64 d,const byte *n,const byte *k) +{ + return crypto_secretbox(c,m,d,n,k); +} + +int crypto_box_open_afternm(byte *m,const byte *c,word64 d,const byte *n,const byte *k) +{ + return crypto_secretbox_open(m,c,d,n,k); +} + +int crypto_box(byte *c, const byte *m, word64 d, const byte *n, const byte *y, const byte *x) +{ + byte k[32]; + if (crypto_box_beforenm(k, y, x) != 0) return -1; + return crypto_box_afternm(c, m, d, n, k); +} + +int crypto_box_unchecked(byte *c, const byte *m, word64 d, const byte *n, const byte *y, const byte *x) +{ + byte k[32]; + crypto_box_beforenm_unchecked(k, y, x); + return crypto_box_afternm(c, m, d, n, k); +} + +int crypto_box_open(byte *m,const byte *c,word64 d,const byte *n,const byte *y,const byte *x) +{ + byte k[32]; + if(crypto_box_beforenm(k,y,x) != 0) return -1; + return crypto_box_open_afternm(m,c,d,n,k); +} + +int crypto_box_open_unchecked(byte *m,const byte *c,word64 d,const byte *n,const byte *y,const byte *x) +{ + byte k[32]; + crypto_box_beforenm_unchecked(k,y,x); + return crypto_box_open_afternm(m,c,d,n,k); +} + +static word64 R(word64 x,int c) { return (x >> c) | (x << (64 - c)); } +static word64 Ch(word64 x,word64 y,word64 z) { return (x & y) ^ (~x & z); } +static word64 Maj(word64 x,word64 y,word64 z) { return (x & y) ^ (x & z) ^ (y & z); } +static word64 Sigma0(word64 x) { return R(x,28) ^ R(x,34) ^ R(x,39); } +static word64 Sigma1(word64 x) { return R(x,14) ^ R(x,18) ^ R(x,41); } +static word64 sigma0(word64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); } +static word64 sigma1(word64 x) { return R(x,19) ^ R(x,61) ^ (x >> 6); } + +static const word64 K[80] = +{ + W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), + W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), + W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), + W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), + W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), + W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), + W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), + W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), + W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), + W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), + W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), + W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), + W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), + W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), + W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), + W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), + W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), + W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), + W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), + W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) +}; + +int crypto_hashblocks(byte *x,const byte *m,word64 n) +{ + word64 z[8],b[8],a[8],w[16],t; + int i,j; + + for(i=0; i<8; ++i) z[i] = a[i] = dl64(x + 8 * i); + + while (n >= 128) { + for(i=0; i<16; ++i) w[i] = dl64(m + 8 * i); + + for(i=0; i<80; ++i) { + for(j=0; j<8; ++j) b[j] = a[j]; + t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16]; + b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]); + b[3] += t; + for(j=0; j<8; ++j) a[(j+1)%8] = b[j]; + if (i%16 == 15) + for(j=0; j<16; ++j) + w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]); + } + + for(i=0; i<8; ++i) { a[i] += z[i]; z[i] = a[i]; } + + m += 128; + n -= 128; + } + + for(i=0; i<8; ++i) ts64(x+8*i,z[i]); + + return n; +} + +static const byte iv[64] = { + 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, + 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, + 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, + 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, + 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, + 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, + 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, + 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 +} ; + +int crypto_hash(byte *out,const byte *m,word64 n) +{ + byte h[64],x[256]; + word64 i,b = n; + + for(i=0; i<64; ++i) h[i] = iv[i]; + + crypto_hashblocks(h,m,n); + m += n; + n &= 127; + m -= n; + + for(i=0; i<256; ++i) x[i] = 0; + for(i=0; i> 61; + ts64(x+n-8,b<<3); + crypto_hashblocks(h,x,n); + + for(i=0; i<64; ++i) out[i] = h[i]; + + return 0; +} + +static void add(gf p[4],gf q[4]) +{ + gf a,b,c,d,t,e,f,g,h; + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +static void cswap(gf p[4],gf q[4],byte b) +{ + int i; + for(i=0; i<4; ++i) + sel25519(p[i],q[i],b); +} + +static void pack(byte *r,gf p[4]) +{ + gf tx, ty, zi; + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +static void scalarmult(gf p[4],gf q[4],const byte *s) +{ + int i; + set25519(p[0],gf0); + set25519(p[1],gf1); + set25519(p[2],gf1); + set25519(p[3],gf0); + for (i = 255;i >= 0;--i) { + byte b = (s[i/8]>>(i&7))&1; + cswap(p,q,b); + add(q,p); + add(p,p); + cswap(p,q,b); + } +} + +static void scalarbase(gf p[4],const byte *s) +{ + gf q[4]; + set25519(q[0],X); + set25519(q[1],Y); + set25519(q[2],gf1); + M(q[3],X,Y); + scalarmult(p,q,s); +} + +int crypto_sign_keypair(byte *pk, byte *sk) +{ + byte d[64]; + gf p[4]; + int i; + + randombytes(sk, 32); + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p,d); + pack(pk,p); + + for(i=0; i<32; ++i) sk[32 + i] = pk[i]; + return 0; +} + +int crypto_sign_sk2pk(byte *pk, const byte *sk) +{ + byte d[64]; + gf p[4]; + // int i; + + // randombytes(sk, 32); + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p,d); + pack(pk,p); + + // for(i=0; i<32; ++i) sk[32 + i] = pk[i]; + return 0; +} + +static const word64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; + +static void modL(byte *r,sword64 x[64]) +{ + sword64 carry,i,j; + for (i = 63;i >= 32;--i) { + carry = 0; + for (j = i - 32;j < i - 12;++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = (x[j] + 128) >> 8; + x[j] -= ((word64)carry) << 8; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for(j=0; j<32; ++j) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for(j=0; j<32; ++j) x[j] -= carry * L[j]; + for(i=0; i<32; ++i) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +static void reduce(byte *r) +{ + sword64 x[64],i; + for(i=0; i<64; ++i) x[i] = (word64) r[i]; + for(i=0; i<64; ++i) r[i] = 0; + modL(r,x); +} + +int crypto_sign(byte *sm,word64 *smlen,const byte *m,word64 n,const byte *sk) +{ + byte d[64],h[64],r[64]; + word64 i; sword64 j,x[64]; + gf p[4]; + + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + *smlen = n+64; + for(i=0; i>7)) Z(r[0],gf0,r[0]); + + M(r[3],r[0],r[1]); + return 0; +} + +int crypto_sign_open(byte *m,word64 *mlen,const byte *sm,word64 n,const byte *pk) +{ + word32 i; + byte t[32],h[64]; + gf p[4],q[4]; + + *mlen = ~W64LIT(0); + if (n < 64) return -1; + + if (unpackneg(q,pk)) return -1; + + for(i=0; i>1) ^ ((c & 1) ? (modulus>>1) : 0); - return c | (c1 << 8) | (c2 << 16) | (c1 << 24); -} - -// compute RS(12,8) code with the above polynomial as generator -// this is equivalent to multiplying by the RS matrix -static word32 ReedSolomon(word32 high, word32 low) -{ - for (unsigned int i=0; i<8; i++) - { - high = Mod(high>>24) ^ (high<<8) ^ (low>>24); - low <<= 8; - } - return high; -} - -inline word32 Twofish::h0(word32 x, const word32 *key, unsigned int kLen) -{ - x = x | (x<<8) | (x<<16) | (x<<24); - switch(kLen) - { -#define Q(a, b, c, d, t) q[a][GETBYTE(t,0)] ^ (q[b][GETBYTE(t,1)] << 8) ^ (q[c][GETBYTE(t,2)] << 16) ^ (q[d][GETBYTE(t,3)] << 24) - case 4: x = Q(1, 0, 0, 1, x) ^ key[6]; - case 3: x = Q(1, 1, 0, 0, x) ^ key[4]; - case 2: x = Q(0, 1, 0, 1, x) ^ key[2]; - x = Q(0, 0, 1, 1, x) ^ key[0]; - } - return x; -} - -inline word32 Twofish::h(word32 x, const word32 *key, unsigned int kLen) -{ - x = h0(x, key, kLen); - return mds[0][GETBYTE(x,0)] ^ mds[1][GETBYTE(x,1)] ^ mds[2][GETBYTE(x,2)] ^ mds[3][GETBYTE(x,3)]; -} - -Twofish::Twofish(const byte *userKey, unsigned int keylength) - : m_k(40), m_s(4) -{ - assert(keylength == KeyLength(keylength)); - - unsigned int len = (keylength <= 16 ? 2 : (keylength <= 24 ? 3 : 4)); - SecBlock key(len*2); - GetUserKeyLittleEndian(key.ptr, len*2, userKey, keylength); - - unsigned int i; - for (i=0; i<40; i+=2) - { - word32 a = h(i, key, len); - word32 b = rotlFixed(h(i+1, key+1u, len), 8); - m_k[i] = a+b; - m_k[i+1] = rotlFixed(a+2*b, 9); - } - - SecBlock svec(2*len); - for (i=0; i>1) ^ ((c & 1) ? (modulus>>1) : 0); + return c | (c1 << 8) | (c2 << 16) | (c1 << 24); +} + +// compute RS(12,8) code with the above polynomial as generator +// this is equivalent to multiplying by the RS matrix +static word32 ReedSolomon(word32 high, word32 low) +{ + for (unsigned int i=0; i<8; i++) + { + high = Mod(high>>24) ^ (high<<8) ^ (low>>24); + low <<= 8; + } + return high; +} + +inline word32 Twofish::Base::h0(word32 x, const word32 *key, unsigned int kLen) +{ + x = x | (x<<8) | (x<<16) | (x<<24); + switch(kLen) + { +#define Q(a, b, c, d, t) q[a][GETBYTE(t,0)] ^ (q[b][GETBYTE(t,1)] << 8) ^ (q[c][GETBYTE(t,2)] << 16) ^ (q[d][GETBYTE(t,3)] << 24) + case 4: x = Q(1, 0, 0, 1, x) ^ key[6]; + // fall through + case 3: x = Q(1, 1, 0, 0, x) ^ key[4]; + // fall through + case 2: x = Q(0, 1, 0, 1, x) ^ key[2]; + x = Q(0, 0, 1, 1, x) ^ key[0]; + } + return x; +} + +inline word32 Twofish::Base::h(word32 x, const word32 *key, unsigned int kLen) +{ + x = h0(x, key, kLen); + return mds[0][GETBYTE(x,0)] ^ mds[1][GETBYTE(x,1)] ^ mds[2][GETBYTE(x,2)] ^ mds[3][GETBYTE(x,3)]; +} + +void Twofish::Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &) +{ + AssertValidKeyLength(keylength); + + unsigned int len = (keylength <= 16 ? 2 : (keylength <= 24 ? 3 : 4)); + SecBlock key(len*2); + GetUserKey(LITTLE_ENDIAN_ORDER, key.begin(), len*2, userKey, keylength); + + unsigned int i; + for (i=0; i<40; i+=2) + { + word32 a = h(i, key, len); + word32 b = rotlConstant<8>(h(i + 1, key + 1, len)); + m_k[i] = a+b; + m_k[i + 1] = rotlConstant<9>(a + 2 * b); + } + + SecBlock svec(2*len); + for (i=0; i(c); \ + (d) = rotlConstant<1>(d) ^ y + +#define ENCCYCLE(n) \ + ENCROUND (2 * (n), a, b, c, d); \ + ENCROUND (2 * (n) + 1, c, d, a, b) + +#define DECROUND(n, a, b, c, d) \ + x = G1 (a); y = G2 (b); \ + x += y; y += x; \ + (d) ^= y + k[2 * (n) + 1]; \ + (d) = rotrConstant<1>(d); \ + (c) = rotlConstant<1>(c); \ + (c) ^= (x + k[2 * (n)]) + +#define DECCYCLE(n) \ + DECROUND (2 * (n) + 1, c, d, a, b); \ + DECROUND (2 * (n), a, b, c, d) + +typedef BlockGetAndPut Block; + +void Twofish::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 x, y, a, b, c, d; + + Block::Get(inBlock)(a)(b)(c)(d); + + a ^= m_k[0]; + b ^= m_k[1]; + c ^= m_k[2]; + d ^= m_k[3]; + + const word32 *k = m_k+8; + ENCCYCLE (0); + ENCCYCLE (1); + ENCCYCLE (2); + ENCCYCLE (3); + ENCCYCLE (4); + ENCCYCLE (5); + ENCCYCLE (6); + ENCCYCLE (7); + + c ^= m_k[4]; + d ^= m_k[5]; + a ^= m_k[6]; + b ^= m_k[7]; + + Block::Put(xorBlock, outBlock)(c)(d)(a)(b); +} + +void Twofish::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 x, y, a, b, c, d; + + Block::Get(inBlock)(c)(d)(a)(b); + + c ^= m_k[4]; + d ^= m_k[5]; + a ^= m_k[6]; + b ^= m_k[7]; + + const word32 *k = m_k+8; + DECCYCLE (7); + DECCYCLE (6); + DECCYCLE (5); + DECCYCLE (4); + DECCYCLE (3); + DECCYCLE (2); + DECCYCLE (1); + DECCYCLE (0); + + a ^= m_k[0]; + b ^= m_k[1]; + c ^= m_k[2]; + d ^= m_k[3]; + + Block::Put(xorBlock, outBlock)(a)(b)(c)(d); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/twofish.h b/external/ours/library/crypto/src/shared/original/twofish.h index bc7a84f43..16284b486 100755 --- a/external/ours/library/crypto/src/shared/original/twofish.h +++ b/external/ours/library/crypto/src/shared/original/twofish.h @@ -1,53 +1,64 @@ -#ifndef CRYPTOPP_TWOFISH_H -#define CRYPTOPP_TWOFISH_H - -/** \file -*/ - -#include "cryptlib.h" -#include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -/// base class, do not use directly -class Twofish : public FixedBlockSize<16>, public VariableKeyLength<16, 0, 32> -{ -protected: - Twofish(const byte *userKey, unsigned int keylength); - 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]; - - SecBlock m_k; - SecBlock m_s; -}; - -/// Twofish -class TwofishEncryption : public Twofish -{ -public: - TwofishEncryption(const byte *userKey, unsigned int keylength=DEFAULT_KEYLENGTH) - : Twofish(userKey, keylength) {} - - void ProcessBlock(const byte *inBlock, byte * outBlock) const; - void ProcessBlock(byte * inoutBlock) const - {TwofishEncryption::ProcessBlock(inoutBlock, inoutBlock);} -}; - -/// Twofish -class TwofishDecryption : public Twofish -{ -public: - TwofishDecryption(const byte *userKey, unsigned int keylength=DEFAULT_KEYLENGTH) - : Twofish(userKey, keylength) {} - - void ProcessBlock(const byte *inBlock, byte * outBlock) const; - void ProcessBlock(byte * inoutBlock) const - {TwofishDecryption::ProcessBlock(inoutBlock, inoutBlock);} -}; - -NAMESPACE_END - -#endif +// 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/external/ours/library/crypto/src/shared/original/validat0.cpp b/external/ours/library/crypto/src/shared/original/validat0.cpp new file mode 100755 index 000000000..a32bcf019 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/validat0.cpp @@ -0,0 +1,1669 @@ +// validat0.cpp - originally written and placed in the public domain by Wei Dai and Jeffrey Walton +// Routines in this source file are only tested in Debug builds. +// Source files split in July 2018 to expedite compiles. + +#include "pch.h" + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "cpu.h" +#include "validate.h" + +#include "asn.h" +#include "gf2n.h" +#include "default.h" +#include "integer.h" +#include "polynomi.h" +#include "channels.h" + +#include "ida.h" +#include "gzip.h" +#include "zlib.h" + +#include +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +// Issue 64: "PolynomialMod2::operator<<=", http://github.com/weidai11/cryptopp/issues/64 +bool TestPolynomialMod2() +{ + std::cout << "\nTesting PolynomialMod2 bit operations...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + const unsigned int start = 0; + const unsigned int stop = 4 * WORD_BITS + 1; + + for (unsigned int i = start; i < stop; i++) + { + PolynomialMod2 p(1); + p <<= i; + + Integer n(Integer::One()); + n <<= i; + + std::ostringstream oss1; + oss1 << p; + + std::string str1, str2; + + // str1 needs the commas removed used for grouping + str1 = oss1.str(); + str1.erase(std::remove(str1.begin(), str1.end(), ','), str1.end()); + + // str1 needs the trailing 'b' removed + str1.erase(str1.end() - 1); + + // str2 is fine as-is + str2 = IntToString(n, 2); + + pass1 &= (str1 == str2); + } + + for (unsigned int i = start; i < stop; i++) + { + const word w((word)SIZE_MAX); + + PolynomialMod2 p(w); + p <<= i; + + Integer n(Integer::POSITIVE, static_cast(w)); + n <<= i; + + std::ostringstream oss1; + oss1 << p; + + std::string str1, str2; + + // str1 needs the commas removed used for grouping + str1 = oss1.str(); + str1.erase(std::remove(str1.begin(), str1.end(), ','), str1.end()); + + // str1 needs the trailing 'b' removed + str1.erase(str1.end() - 1); + + // str2 is fine as-is + str2 = IntToString(n, 2); + + pass2 &= (str1 == str2); + } + + RandomNumberGenerator& prng = GlobalRNG(); + for (unsigned int i = start; i < stop; i++) + { + word w; // Cast to lword due to Visual Studio + prng.GenerateBlock((byte*)&w, sizeof(w)); + + PolynomialMod2 p(w); + p <<= i; + + Integer n(Integer::POSITIVE, static_cast(w)); + n <<= i; + + std::ostringstream oss1; + oss1 << p; + + std::string str1, str2; + + // str1 needs the commas removed used for grouping + str1 = oss1.str(); + str1.erase(std::remove(str1.begin(), str1.end(), ','), str1.end()); + + // str1 needs the trailing 'b' removed + str1.erase(str1.end() - 1); + + // str2 is fine as-is + str2 = IntToString(n, 2); + + if (str1 != str2) + { + std::cout << " Oops..." << "\n"; + std::cout << " random: " << std::hex << n << std::dec << "\n"; + std::cout << " str1: " << str1 << "\n"; + std::cout << " str2: " << str2 << "\n"; + } + + pass3 &= (str1 == str2); + } + + std::cout << (!pass1 ? "FAILED" : "passed") << ": " << "1 shifted over range [" << std::dec << start << "," << stop << "]" << "\n"; + std::cout << (!pass2 ? "FAILED" : "passed") << ": " << "0x" << std::hex << word(SIZE_MAX) << std::dec << " shifted over range [" << start << "," << stop << "]" << "\n"; + std::cout << (!pass3 ? "FAILED" : "passed") << ": " << "random values shifted over range [" << std::dec << start << "," << stop << "]" << "\n"; + + return pass1 && pass2 && pass3; +} +#endif + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +bool TestCompressors() +{ + std::cout << "\nTesting Compressors and Decompressors...\n\n"; + bool fail1 = false, fail2 = false, fail3 = false; + const unsigned int COMP_COUNT = 64; + + try + { + // Gzip uses Adler32 checksums. We expect a failure to happen on occasion. + // If we see more than 2 failures in a run of 128, then we need to investigate. + unsigned int truncatedCount=0; + for (unsigned int i = 0; i= 2) + { + std::cout << "FAILED: Gzip failed to detect a truncated stream\n"; + fail1 = true; + } + } + catch (const Exception&) {} + } + } + catch (const Exception& ex) + { + std::cout << "FAILED: " << ex.what() << "\n"; + fail1 = true; + } + + // ************************************************************** + + // Gzip Filename, Filetime and Comment + try + { + std::string filename = "test.txt"; + std::string comment = "This is a test"; + word32 filetime = GlobalRNG().GenerateWord32(4, 0xffffff); + + AlgorithmParameters params = MakeParameters(Name::FileTime(), (int)filetime) + (Name::FileName(), ConstByteArrayParameter(filename.c_str(), false)) + (Name::Comment(), ConstByteArrayParameter(comment.c_str(), false)); + + std::string src, dest; + unsigned int len = GlobalRNG().GenerateWord32(4, 0xfff); + + RandomNumberSource(GlobalRNG(), len, true, new StringSink(src)); + Gunzip unzip(new StringSink(dest)); + StringSource(src, true, new Gzip(params, new Redirector(unzip))); + + if (filename != unzip.GetFilename()) + throw Exception(Exception::OTHER_ERROR, "Failed to retrieve filename"); + + if (filetime != unzip.GetFiletime()) + throw Exception(Exception::OTHER_ERROR, "Failed to retrieve filetime"); + + if (comment != unzip.GetComment()) + throw Exception(Exception::OTHER_ERROR, "Failed to retrieve comment"); + + std::cout << "passed: filenames, filetimes and comments\n"; + } + catch (const Exception& ex) + { + std::cout << "FAILED: " << ex.what() << "\n"; + } + + // Unzip random data. See if we can induce a crash + for (unsigned int i = 0; i strShares(shares); + vector_member_ptrs strSinks(shares); + std::string channel; + + // ********** Create Shares + for (unsigned int i=0; i(i); + strSinks[i]->Put((const byte *)channel.data(), CHID_LENGTH); + channelSwitch->AddRoute(channel, *strSinks[i], DEFAULT_CHANNEL); + } + source.PumpAll(); + + // ********** Randomize shares + + GlobalRNG().Shuffle(strShares.begin(), strShares.end()); + + // ********** Recover secret + try + { + std::string recovered; + InformationRecovery recovery(threshold, new StringSink(recovered)); + + vector_member_ptrs strSources(threshold); + channel.resize(CHID_LENGTH); + + for (unsigned int i=0; iPump(CHID_LENGTH); + strSources[i]->Get((byte*)&channel[0], CHID_LENGTH); + strSources[i]->Attach(new ChannelSwitch(recovery, channel)); + } + + while (strSources[0]->Pump(256)) + { + for (unsigned int i=1; iPump(256); + } + + for (unsigned int i=0; iPumpAll(); + + fail = (message != recovered); + } + catch (const Exception&) + { + fail = true; + } + + pass &= !fail; + } + + std::cout << (fail ? "FAILED:" : "passed:") << " " << INFORMATION_SHARES << " information dispersals\n"; + + // ********** Secret Sharing **********// + + for (unsigned int shares=3; shares strShares(shares); + vector_member_ptrs strSinks(shares); + std::string channel; + + // ********** Create Shares + for (unsigned int i=0; i(i); + strSinks[i]->Put((const byte *)channel.data(), CHID_LENGTH); + channelSwitch->AddRoute(channel, *strSinks[i], DEFAULT_CHANNEL); + } + source.PumpAll(); + + // ********** Randomize shares + + GlobalRNG().Shuffle(strShares.begin(), strShares.end()); + + // ********** Recover secret + try + { + std::string recovered; + SecretRecovery recovery(threshold, new StringSink(recovered)); + + vector_member_ptrs strSources(threshold); + channel.resize(CHID_LENGTH); + for (unsigned int i=0; iPump(CHID_LENGTH); + strSources[i]->Get((byte*)&channel[0], CHID_LENGTH); + strSources[i]->Attach(new ChannelSwitch(recovery, channel)); + } + + while (strSources[0]->Pump(256)) + { + for (unsigned int i=1; iPump(256); + } + + for (unsigned int i=0; iPumpAll(); + + fail = (message != recovered); + } + catch (const Exception&) + { + fail = true; + } + + pass &= !fail; + } + + std::cout << (fail ? "FAILED:" : "passed:") << " " << SECRET_SHARES << " secret sharings\n"; + + return pass; +} + +bool TestRounding() +{ + std::cout << "\nTesting RoundUpToMultipleOf/RoundDownToMultipleOf...\n\n"; + bool pass=true, fail; + + // ********** byte **********// + try + { + const byte v=0, b=0x08; + byte r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, byte, no overflow\n"; + + try + { + const byte v=1, b=0x08; + byte r=RoundUpToMultipleOf(v, b); + fail = (r != b); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, byte, no overflow\n"; + + try + { + const byte v=0x08, b=0x08; + byte r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, byte, no overflow\n"; + + try + { + const byte v=0xf7, b=0x08; + byte r=RoundUpToMultipleOf(v, b); + fail = (r != 0xf8); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, byte, no overflow\n"; + + try + { + const byte v=0xf8, b=0x08; + byte r=RoundUpToMultipleOf(v, b); + fail = (r != 0xf8); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, byte, no overflow\n"; + + try + { + const byte v=0xf9, b=0x08; + byte r=RoundUpToMultipleOf(v, b); + CRYPTOPP_UNUSED(r); + fail = true; + } + catch(const Exception&) + { + fail = false; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, byte, overflow\n"; + + // ********** word16 **********// + try + { + const word16 v=0, b=0x08; + word16 r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word16, no overflow\n"; + + try + { + const word16 v=1, b=0x08; + word16 r=RoundUpToMultipleOf(v, b); + fail = (r != b); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word16, no overflow\n"; + + try + { + const word16 v=0x08, b=0x08; + word16 r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word16, no overflow\n"; + + try + { + const word16 v=0xfff7, b=0x08; + word16 r=RoundUpToMultipleOf(v, b); + fail = (r != 0xfff8); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word16, no overflow\n"; + + try + { + const word16 v=0xfff8, b=0x08; + word16 r=RoundUpToMultipleOf(v, b); + fail = (r != 0xfff8); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word16, no overflow\n"; + + try + { + const word16 v=0xfff9, b=0x08; + word16 r=RoundUpToMultipleOf(v, b); + CRYPTOPP_UNUSED(r); + fail = true; + } + catch(const Exception&) + { + fail = false; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word16, overflow\n"; + + // ********** word32 **********// + try + { + const word32 v=0, b=0x08; + word32 r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word32, no overflow\n"; + + try + { + const word32 v=1, b=0x08; + word32 r=RoundUpToMultipleOf(v, b); + fail = (r != b); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word32, no overflow\n"; + + try + { + const word32 v=0x08, b=0x08; + word32 r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word32, no overflow\n"; + + try + { + const word32 v=0xfffffff7, b=0x08; + word32 r=RoundUpToMultipleOf(v, b); + fail = (r != 0xfffffff8); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word32, no overflow\n"; + + try + { + const word32 v=0xfffffff8, b=0x08; + word32 r=RoundUpToMultipleOf(v, b); + fail = (r != 0xfffffff8); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word32, no overflow\n"; + + try + { + const word32 v=0xfffffff9, b=0x08; + word32 r=RoundUpToMultipleOf(v, b); + CRYPTOPP_UNUSED(r); + fail = true; + } + catch(const Exception&) + { + fail = false; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word32, overflow\n"; + + // ********** word64 **********// + try + { + const word64 v=0, b=0x08; + word64 r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word64, no overflow\n"; + + try + { + const word64 v=1, b=0x08; + word64 r=RoundUpToMultipleOf(v, b); + fail = (r != b); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word64, no overflow\n"; + + try + { + const word64 v=0x08, b=0x08; + word64 r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word64, no overflow\n"; + + try + { + const word64 v=W64LIT(0xffffffffffffff7), b=0x08; + word64 r=RoundUpToMultipleOf(v, b); + fail = (r != W64LIT(0xffffffffffffff8)); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word64, no overflow\n"; + + try + { + const word64 v=W64LIT(0xffffffffffffff8), b=0x08; + word64 r=RoundUpToMultipleOf(v, b); + fail = (r != W64LIT(0xffffffffffffff8)); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word64, no overflow\n"; + + try + { + const word64 v=W64LIT(0xfffffffffffffff9), b=0x08; + word64 r=RoundUpToMultipleOf(v, b); + CRYPTOPP_UNUSED(r); + fail = true; + } + catch(const Exception&) + { + fail = false; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word64, overflow\n"; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + // ********** word128 **********// + try + { + const word128 v=0, b=0x08; + word128 r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word128, no overflow\n"; + + try + { + const word128 v=1, b=0x08; + word128 r=RoundUpToMultipleOf(v, b); + fail = (r != b); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word128, no overflow\n"; + + try + { + const word128 v=0x08, b=0x08; + word128 r=RoundUpToMultipleOf(v, b); + fail = (r != v); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word128, no overflow\n"; + + try + { + // http://stackoverflow.com/q/31461318/608639 + const word128 h = ((word128)W64LIT(0xffffffffffffffff)) << 64U; + const word128 v = h | (word128)W64LIT(0xfffffffffffffff7), b=0x08; + word128 r=RoundUpToMultipleOf(v, b); + fail = (r != (h | (word128)W64LIT(0xfffffffffffffff8))); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word128, no overflow\n"; + + try + { + const word128 h = ((word128)W64LIT(0xffffffffffffffff)) << 64U; + const word128 v = h | (word128)W64LIT(0xfffffffffffffff8), b=0x08; + word128 r=RoundUpToMultipleOf(v, b); + fail = (r != (h | (word128)W64LIT(0xfffffffffffffff8))); + } + catch(const Exception&) + { + fail = true; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word128, no overflow\n"; + + try + { + const word128 h = ((word128)W64LIT(0xffffffffffffffff)) << 64U; + const word128 v = h | (word128)W64LIT(0xfffffffffffffff9), b=0x08; + word128 r=RoundUpToMultipleOf(v, b); + CRYPTOPP_UNUSED(r); + fail = true; + } + catch(const Exception&) + { + fail = false; + } + + pass = !fail && pass; + std::cout << (fail ? "FAILED:" : "passed:") << " RoundUpToMultipleOf, word128, overflow\n"; +#endif + + return pass; +} +#endif + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +struct ASN1_TestTuple +{ + ASN1_TestTuple(int tag, int result, const char* data, size_t len) { + m_result = result; + m_tag = tag; + m_data = std::string(data, len); + } + + std::string Name() const { + return Id2String(); + } + + const byte* Data() const { + return ConstBytePtr(m_data); + } + + size_t Size() const { + return BytePtrSize(m_data); + } + + int Tag() const { + return m_tag; + } + + int Result() const { + return m_result; + } + + std::string Id2String() const + { + switch(m_tag) + { + case BIT_STRING: + return "BIT_STRING"; + case OCTET_STRING: + return "OCTET_STRING"; + case INTEGER: + return "INTEGER"; + case UTF8_STRING: + return "UTF8_STRING"; + case PRINTABLE_STRING: + return "PRINTABLE_STRING"; + case IA5_STRING: + return "IA5_STRING"; + default: + return "Unknown"; + } + } + +protected: + std::string m_data; + int m_tag, m_result; +}; + +bool RunASN1TestSet(const ASN1_TestTuple asnTuples[], size_t count) +{ + bool pass=true, fail; + + // Disposition + enum {REJECT=3, ACCEPT=4}; + + for(size_t i=0; i(as2, unused5, byte(INTEGER), 0, W64LIT(0xffffffffffffffff)); + break; + + case UTF8_STRING: case PRINTABLE_STRING: case IA5_STRING: + BERDecodeTextString(as1, unused2, tag); + break; + + default: + BERGeneralDecoder(as1, tag); + break; + } + + fail = thisTest.Result() != ACCEPT; + } + catch(const Exception&) + { + fail = thisTest.Result() != REJECT; + } + + std::cout << (fail ? "FAILED:" : "passed:") << (thisTest.Result() == ACCEPT ? " accept " : " reject "); + std::cout << asnTuples[i].Name() << " " << val << "\n"; + pass = !fail && pass; + } + + return pass; +} + +bool TestASN1Parse() +{ + std::cout << "\nTesting ASN.1 parser...\n\n"; + + bool pass = true; + + // Disposition + enum {REJECT=3, ACCEPT=4}; + + // All the types Crypto++ recognizes. + // "C" is one content octet with value 0x43. + const ASN1_TestTuple bitStrings[] = + { + // The first "\x00" content octet is the "initial octet" representing unused bits. In the + // primitive encoding form, there may be zero, one or more contents after the initial octet. + ASN1_TestTuple(BIT_STRING, ACCEPT, "\x03\x01" "\x00", 3), // definite length, short form, initial octet, zero subsequent octets + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x01" "\x08", 3), // definite length, short form, initial octet, zero subsequent octets + ASN1_TestTuple(BIT_STRING, ACCEPT, "\x03\x02" "\x00" "C", 4), // definite length, short form, expected subsequent octets + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x02" "\x08" "C", 4), // too many unused bits + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x7F" "\x00" "C", 4), // runt or underrun + ASN1_TestTuple(BIT_STRING, ACCEPT, "\x03\x81\x01" "\x00", 4), // definite length, long form, initial octet, zero subsequent octets + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x81\x01" "\x08", 4), // definite length, long form, initial octet, zero subsequent octets + ASN1_TestTuple(BIT_STRING, ACCEPT, "\x03\x81\x02" "\x00" "C", 5), // definite length, long form + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x81\x02" "\x08" "C", 5), // too many unused bits + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x81\xff" "\x00" "C", 5), // runt or underrun + ASN1_TestTuple(BIT_STRING, ACCEPT, "\x03\x82\x00\x02" "\x00" "C", 6), // definite length, long form + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x82\x00\x02" "\x08" "C", 6), // too many unused bits + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x82\xff\xff" "\x00" "C", 6), // runt or underrun + ASN1_TestTuple(BIT_STRING, ACCEPT, "\x03\x83\x00\x00\x02" "\x00" "C", 7), // definite length, long form + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x83\x00\x00\x02" "\x08" "C", 7), // too many unused bits + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x83\xff\xff\xff" "\x00" "C", 7), // runt or underrun + ASN1_TestTuple(BIT_STRING, ACCEPT, "\x03\x84\x00\x00\x00\x02" "\x00" "C", 8), // definite length, long form + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x84\x00\x00\x00\x02" "\x08" "C", 8), // too many unused bits + ASN1_TestTuple(BIT_STRING, REJECT, "\x03\x84\xff\xff\xff\xff" "\x00" "C", 8), // <== Issue 346; requires large allocation + }; + + pass = RunASN1TestSet(bitStrings, COUNTOF(bitStrings)) && pass; + + const ASN1_TestTuple octetStrings[] = + { + // In the primitive encoding form, there may be zero, one or more contents. + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x00", 2), // definite length, short form, zero content octets + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x01" "C", 3), // definite length, short form, expected content octets + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x02" "C", 3), // runt or underrun + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x7F" "C", 3), // runt or underrun + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x81\x00", 3), // definite length, long form, zero content octets + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x81\x01" "C", 4), // definite length, long form, expected content octets + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x81\x02" "C", 4), // runt or underrun + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x81\xff" "C", 4), // runt or underrun + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x82\x00\x00", 4), // definite length, long form, zero content octets + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x82\x00\x01" "C", 5), // definite length, long form, expected content octets + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x82\x00\x02" "C", 5), // runt or underrun + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x82\xff\xff" "C", 5), // runt or underrun + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x83\x00\x00\x00", 5), // definite length, long form, zero content octets + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x83\x00\x00\x01" "C", 6), // definite length, long form, expected content octets + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x83\x00\x00\x02" "C", 6), // runt or underrun + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x83\xff\xff\xff" "C", 6), // runt or underrun + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x84\x00\x00\x00\x00", 6), // definite length, long form, zero content octets + ASN1_TestTuple(OCTET_STRING, ACCEPT, "\x04\x84\x00\x00\x00\x01" "C", 7), // definite length, long form, expected content octets + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x84\x00\x00\x00\x02" "C", 7), // runt or underrun + ASN1_TestTuple(OCTET_STRING, REJECT, "\x04\x84\xff\xff\xff\xff" "C", 7), // <== Issue 346; requires large allocation + }; + + pass = RunASN1TestSet(octetStrings, COUNTOF(octetStrings)) && pass; + + const ASN1_TestTuple utf8Strings[] = + { + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x00", 2), // definite length, short form, zero content octets + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x01" "C", 3), // definite length, short form, expected content octets + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x02" "C", 3), // runt or underrun + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x7F" "C", 3), // runt or underrun + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x81\x00", 3), // definite length, long form, zero content octets + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x81\x01" "C", 4), // definite length, long form, expected content octets + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x81\x02" "C", 4), // runt or underrun + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x81\xff" "C", 4), // runt or underrun + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x82\x00\x00", 4), // definite length, long form, zero content octets + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x82\x00\x01" "C", 5), // definite length, long form, expected content octets + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x82\x00\x02" "C", 5), // runt or underrun + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x82\xff\xff" "C", 5), // runt or underrun + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x83\x00\x00\x00", 5), // definite length, long form, zero content octets + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x83\x00\x00\x01" "C", 6), // definite length, long form, expected content octets + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x83\x00\x00\x02" "C", 6), // runt or underrun + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x83\xff\xff\xff" "C", 6), // runt or underrun + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x84\x00\x00\x00\x00", 6), // definite length, long form, zero content octets + ASN1_TestTuple(UTF8_STRING, ACCEPT, "\x0c\x84\x00\x00\x00\x01" "C", 7), // definite length, long form, expected content octets + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x84\x00\x00\x00\x02" "C", 7), // runt or underrun + ASN1_TestTuple(UTF8_STRING, REJECT, "\x0c\x84\xff\xff\xff\xff" "C", 7), // <== Issue 346; requires large allocation + }; + + pass = RunASN1TestSet(utf8Strings, COUNTOF(utf8Strings)) && pass; + + const ASN1_TestTuple printableStrings[] = + { + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x00", 2), // definite length, short form, zero content octets + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x01" "C", 3), // definite length, short form, expected content octets + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x02" "C", 3), // runt or underrun + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x7F" "C", 3), // runt or underrun + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x81\x00", 3), // definite length, long form, zero content octets + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x81\x01" "C", 4), // definite length, long form, expected content octets + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x81\x02" "C", 4), // runt or underrun + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x81\xff" "C", 4), // runt or underrun + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x82\x00\x00", 4), // definite length, long form, zero content octets + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x82\x00\x01" "C", 5), // definite length, long form, expected content octets + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x82\x00\x02" "C", 5), // runt or underrun + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x82\xff\xff" "C", 5), // runt or underrun + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x83\x00\x00\x00", 5), // definite length, long form, zero content octets + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x83\x00\x00\x01" "C", 6), // definite length, long form, expected content octets + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x83\x00\x00\x02" "C", 6), // runt or underrun + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x83\xff\xff\xff" "C", 6), // runt or underrun + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x84\x00\x00\x00\x00", 6), // definite length, long form, zero content octets + ASN1_TestTuple(PRINTABLE_STRING, ACCEPT, "\x13\x84\x00\x00\x00\x01" "C", 7), // definite length, long form, expected content octets + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x84\x00\x00\x00\x02" "C", 7), // runt or underrun + ASN1_TestTuple(PRINTABLE_STRING, REJECT, "\x13\x84\xff\xff\xff\xff" "C", 7), // <== Issue 346; requires large allocation + }; + + pass = RunASN1TestSet(printableStrings, COUNTOF(printableStrings)) && pass; + + const ASN1_TestTuple ia5Strings[] = + { + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x00", 2), // definite length, short form, zero content octets + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x01" "C", 3), // definite length, short form, expected content octets + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x02" "C", 3), // runt or underrun + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x7F" "C", 3), // runt or underrun + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x81\x00", 3), // definite length, long form, zero content octets + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x81\x01" "C", 4), // definite length, long form, expected content octets + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x81\x02" "C", 4), // runt or underrun + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x81\xff" "C", 4), // runt or underrun + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x82\x00\x00", 4), // definite length, long form, zero content octets + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x82\x00\x01" "C", 5), // definite length, long form, expected content octets + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x82\x00\x02" "C", 5), // runt or underrun + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x82\xff\xff" "C", 5), // runt or underrun + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x83\x00\x00\x00", 5), // definite length, long form, zero content octets + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x83\x00\x00\x01" "C", 6), // definite length, long form, expected content octets + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x83\x00\x00\x02" "C", 6), // runt or underrun + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x83\xff\xff\xff" "C", 6), // runt or underrun + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x84\x00\x00\x00\x00", 6), // definite length, long form, zero content octets + ASN1_TestTuple(IA5_STRING, ACCEPT, "\x16\x84\x00\x00\x00\x01" "C", 7), // definite length, long form, expected content octets + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x84\x00\x00\x00\x02" "C", 7), // runt or underrun + ASN1_TestTuple(IA5_STRING, REJECT, "\x16\x84\xff\xff\xff\xff" "C", 7), // <== Issue 346; requires large allocation + }; + + pass = RunASN1TestSet(ia5Strings, COUNTOF(ia5Strings)) && pass; + + const ASN1_TestTuple integerValues[] = + { + // 8.3.1 The encoding of an integer value shall be primitive. The contents octets shall consist of one or more octets. + ASN1_TestTuple(INTEGER, REJECT, "\x02\x00", 2), // definite length, short form, zero content octets + ASN1_TestTuple(INTEGER, ACCEPT, "\x02\x01" "C", 3), // definite length, short form, expected content octets + ASN1_TestTuple(INTEGER, REJECT, "\x02\x02" "C", 3), // runt or underrun + ASN1_TestTuple(INTEGER, REJECT, "\x02\x7F" "C", 3), // runt or underrun + ASN1_TestTuple(INTEGER, REJECT, "\x02\x81\x00", 3), // definite length, long form, zero content octets + ASN1_TestTuple(INTEGER, ACCEPT, "\x02\x81\x01" "C", 4), // definite length, long form, expected content octets + ASN1_TestTuple(INTEGER, REJECT, "\x02\x81\x02" "C", 4), // runt or underrun + ASN1_TestTuple(INTEGER, REJECT, "\x02\x81\xff" "C", 4), // runt or underrun + ASN1_TestTuple(INTEGER, REJECT, "\x02\x82\x00\x00", 4), // definite length, long form, zero content octets + ASN1_TestTuple(INTEGER, ACCEPT, "\x02\x82\x00\x01" "C", 5), // definite length, long form, expected content octets + ASN1_TestTuple(INTEGER, REJECT, "\x02\x82\x00\x02" "C", 5), // runt or underrun + ASN1_TestTuple(INTEGER, REJECT, "\x02\x82\xff\xff" "C", 5), // runt or underrun + ASN1_TestTuple(INTEGER, REJECT, "\x02\x83\x00\x00\x00", 5), // definite length, long form, zero content octets + ASN1_TestTuple(INTEGER, ACCEPT, "\x02\x83\x00\x00\x01" "C", 6), // definite length, long form, expected content octets + ASN1_TestTuple(INTEGER, REJECT, "\x02\x83\x00\x00\x02" "C", 6), // runt or underrun + ASN1_TestTuple(INTEGER, REJECT, "\x02\x83\xff\xff\xff" "C", 6), // runt or underrun + ASN1_TestTuple(INTEGER, REJECT, "\x02\x84\x00\x00\x00\x00", 6), // definite length, long form, zero content octets + ASN1_TestTuple(INTEGER, ACCEPT, "\x02\x84\x00\x00\x00\x01" "C", 7), // definite length, long form, expected content octets + ASN1_TestTuple(INTEGER, REJECT, "\x02\x84\x00\x00\x00\x02" "C", 7), // runt or underrun + ASN1_TestTuple(INTEGER, REJECT, "\x02\x84\xff\xff\xff\xff" "C", 7), // <== Issue 346; requires large allocation + }; + + pass = RunASN1TestSet(integerValues, COUNTOF(integerValues)) && pass; + + return pass; +} + +bool TestASN1Functions() +{ + std::cout << "\nTesting ASN.1 functions...\n\n"; + + bool pass = true, fail; + + { + const std::string message = "Now is the time for all good men to come to the aide of their country"; + ByteQueue encoded, reencoded, decoded; + size_t len = 0, rlen = 0; + + len = DEREncodeOctetString(encoded, ConstBytePtr(message), BytePtrSize(message)); + DERReencode(encoded, reencoded); + rlen = reencoded.MaxRetrievable(); + (void)BERDecodeOctetString(reencoded, decoded); + + std::string recovered; + StringSink sink(recovered); + decoded.TransferTo(sink); + + fail = (len != rlen || message != recovered); + pass = pass && !fail; + CRYPTOPP_ASSERT(!fail); + + std::cout << (fail ? "FAILED" : "passed") << " "; + std::cout << "DEREncodeOctetString" << "\n"; + std::cout << (fail ? "FAILED" : "passed") << " "; + std::cout << "BERDecodeOctetString" << "\n"; + } + + { + const std::string message = "Now is the time for all good men to come to the aide of their country"; + const int asnStringTypes[] = {UTF8_STRING, PRINTABLE_STRING, T61_STRING, VIDEOTEXT_STRING, IA5_STRING, VISIBLE_STRING}; + unsigned int failed = 0; + size_t len = 0, rlen = 0, i = 0; + + for (i = 0; i < COUNTOF(asnStringTypes); ++i) + { + ByteQueue encoded, reencoded, decoded; + std::string recovered; + + len = DEREncodeTextString(encoded, ConstBytePtr(message), BytePtrSize(message), asnStringTypes[i]); + DERReencode(encoded, reencoded); + rlen = reencoded.MaxRetrievable(); + (void)BERDecodeTextString(reencoded, recovered, asnStringTypes[i]); + + fail = (len != rlen || message != recovered); + if (fail) failed++; + CRYPTOPP_ASSERT(!fail); + } + + failed ? fail = true : fail = false; + pass = pass && !fail; + + std::cout << (fail ? "FAILED" : "passed") << " "; + std::cout << "DEREncodeTextString" << "\n"; + std::cout << (fail ? "FAILED" : "passed") << " "; + std::cout << "DEREncodeTextString" << "\n"; + } + + { + const byte date[] = "Sun, 21 Mar 2021 01:00:00 +0000"; + SecByteBlock message; message.Assign(date, sizeof(date)-1); + const int asnDateTypes[] = {UTC_TIME, GENERALIZED_TIME}; + unsigned int failed = 0; + size_t i = 0; + + for (i = 0; i < COUNTOF(asnDateTypes); ++i) + { + ByteQueue encoded, decoded; + SecByteBlock recovered; + + (void)DEREncodeDate(encoded, message, asnDateTypes[i]); + (void)BERDecodeDate(encoded, recovered, asnDateTypes[i]); + + fail = (message != recovered); + if (fail) failed++; + CRYPTOPP_ASSERT(!fail); + } + + failed ? fail = true : fail = false; + pass = pass && !fail; + + std::cout << (fail ? "FAILED" : "passed") << " "; + std::cout << "DEREncodeDate" << "\n"; + std::cout << (fail ? "FAILED" : "passed") << " "; + std::cout << "BERDecodeDate" << "\n"; + } + + return pass; +} + +#endif + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +bool TestStringSink() +{ + try + { + std::string in = "The quick brown fox jumps over the lazy dog"; + + std::string str; + StringSource s1(in, true, new StringSink(str)); + + std::vector vec; + StringSource s2(in, true, new VectorSink(vec)); + + std::vector vec2; + VectorSource s3(vec, true, new VectorSink(vec2)); + + return str.size() == vec.size() && + std::equal(str.begin(), str.end(), vec.begin()) && + vec.size() == vec2.size() && + std::equal(vec.begin(), vec.end(), vec2.begin()); + } + catch(const std::exception&) + { + } + return false; +} +#endif + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/validat1.cpp b/external/ours/library/crypto/src/shared/original/validat1.cpp new file mode 100755 index 000000000..db5238802 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/validat1.cpp @@ -0,0 +1,1225 @@ +// validat1.cpp - originally written and placed in the public domain by Wei Dai and Jeffrey Walton +// Routines in this source file are only tested in Debug builds. +// Source files split in July 2018 to expedite compiles. + +#include "pch.h" + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "cpu.h" +#include "validate.h" + +#include "secblock.h" +#include "gzip.h" +#include "zlib.h" + +#if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +# include "ppc_simd.h" +#endif + +#include +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +bool TestSecBlock() +{ + std::cout << "\nTesting SecBlock...\n\n"; + + bool pass1=true, pass2=true, pass3=true, pass4=true, pass5=true, pass6=true, pass7=true, temp=false; + + //************ Allocators ************// + + { + std::basic_string, AllocatorWithCleanup > s1; + std::basic_string, AllocatorWithCleanup > s2; + s1.resize(1024); s2.resize(1024); + + std::vector > v1; + std::vector > v2; + v1.resize(1024); v2.resize(1024); + } + + //********** Zeroized block **********// + + { + // NULL ptr with a size means to create a new SecBlock with all elements zero'd + SecByteBlock z1(NULLPTR, 256); + temp = true; + + for (size_t i = 0; i < z1.size(); i++) + temp &= (z1[i] == 0); + + pass1 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Zeroized byte array\n"; + + SecBlock z2(NULLPTR, 256); + temp = true; + + for (size_t i = 0; i < z2.size(); i++) + temp &= (z2[i] == 0); + + pass1 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Zeroized word32 array\n"; + + SecBlock z3(NULLPTR, 256); + temp = true; + + for (size_t i = 0; i < z3.size(); i++) + temp &= (z3[i] == 0); + + pass1 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Zeroized word64 array\n"; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + SecBlock z4(NULLPTR, 256); + temp = true; + + for (size_t i = 0; i < z4.size(); i++) + temp &= (z4[i] == 0); + + pass1 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Zeroized word128 array\n"; +#endif + } + + //********** Non-zero'd block **********// + + { + SecByteBlock z1(NULLPTR, 256); + z1.SetMark(0); + + SecBlock z2(NULLPTR, 256); + z2.SetMark(0); + + SecBlock z3(NULLPTR, 256); + z3.SetMark(0); + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + SecBlock z4(NULLPTR, 256); + z4.SetMark(0); +#endif + } + + //********** Assign **********// + + try + { + SecByteBlock a, b; + temp = true; + + a.Assign((const byte*)"a", 1); + b.Assign((const byte*)"b", 1); + + temp &= (a.SizeInBytes() == 1); + temp &= (b.SizeInBytes() == 1); + temp &= (a[0] == 'a'); + temp &= (b[0] == 'b'); + + a.Assign((const byte*)"ab", 2); + b.Assign((const byte*)"cd", 2); + + temp &= (a.SizeInBytes() == 2); + temp &= (b.SizeInBytes() == 2); + temp &= (a[0] == 'a' && a[1] == 'b'); + temp &= (b[0] == 'c' && b[1] == 'd'); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass2 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Assign byte\n"; + + try + { + SecBlock a, b; + temp = true; + + word32 one[1] = {1}, two[1] = {2}; + a.Assign(one, 1); + b.Assign(two, 1); + + temp &= (a.SizeInBytes() == 4); + temp &= (b.SizeInBytes() == 4); + temp &= (a[0] == 1); + temp &= (b[0] == 2); + + word32 three[2] = {1,2}, four[2] = {3,4}; + a.Assign(three, 2); + b.Assign(four, 2); + + temp &= (a.SizeInBytes() == 8); + temp &= (b.SizeInBytes() == 8); + temp &= (a[0] == 1 && a[1] == 2); + temp &= (b[0] == 3 && b[1] == 4); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass2 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Assign word32\n"; + + try + { + SecBlock a, b; + temp = true; + + word64 one[1] = {1}, two[1] = {2}; + a.Assign(one, 1); + b.Assign(two, 1); + + temp &= (a.SizeInBytes() == 8); + temp &= (b.SizeInBytes() == 8); + temp &= (a[0] == 1); + temp &= (b[0] == 2); + + word64 three[2] = {1,2}, four[2] = {3,4}; + a.Assign(three, 2); + b.Assign(four, 2); + + temp &= (a.SizeInBytes() == 16); + temp &= (b.SizeInBytes() == 16); + temp &= (a[0] == 1 && a[1] == 2); + temp &= (b[0] == 3 && b[1] == 4); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass2 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Assign word64\n"; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + try + { + SecBlock a, b; + temp = true; + + word128 one[1] = {1}, two[1] = {2}; + a.Assign(one, 1); + b.Assign(two, 1); + + temp &= (a.SizeInBytes() == 16); + temp &= (b.SizeInBytes() == 16); + temp &= (a[0] == 1); + temp &= (b[0] == 2); + + word128 three[2] = {1,2}, four[2] = {3,4}; + a.Assign(three, 2); + b.Assign(four, 2); + + temp &= (a.SizeInBytes() == 32); + temp &= (b.SizeInBytes() == 32); + temp &= (a[0] == 1 && a[1] == 2); + temp &= (b[0] == 3 && b[1] == 4); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass2 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Assign word128\n"; +#endif + + //********** Append **********// + + try + { + SecByteBlock a, b; + temp = true; + + a.Assign((const byte*)"a", 1); + b.Assign((const byte*)"b", 1); + + a += b; + temp &= (a.SizeInBytes() == 2); + temp &= (a[0] == 'a' && a[1] == 'b'); + + a.Assign((const byte*)"ab", 2); + b.Assign((const byte*)"cd", 2); + + a += b; + temp &= (a.SizeInBytes() == 4); + temp &= (a[0] == 'a' && a[1] == 'b' && a[2] == 'c' && a[3] == 'd'); + + a.Assign((const byte*)"a", 1); + + a += a; + temp &= (a.SizeInBytes() == 2); + temp &= (a[0] == 'a' && a[1] == 'a'); + + a.Assign((const byte*)"ab", 2); + + a += a; + temp &= (a.SizeInBytes() == 4); + temp &= (a[0] == 'a' && a[1] == 'b' && a[2] == 'a' && a[3] == 'b'); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass3 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Append byte\n"; + + try + { + SecBlock a, b; + temp = true; + + const word32 one[1] = {1}, two[1] = {2}; + a.Assign(one, 1); + b.Assign(two, 1); + + a += b; + temp &= (a.SizeInBytes() == 8); + temp &= (a[0] == 1 && a[1] == 2); + + const word32 three[2] = {1,2}, four[2] = {3,4}; + a.Assign(three, 2); + b.Assign(four, 2); + + a += b; + temp &= (a.SizeInBytes() == 16); + temp &= (a[0] == 1 && a[1] == 2 && a[2] == 3 && a[3] == 4); + + a.Assign(one, 1); + + a += a; + temp &= (a.SizeInBytes() == 8); + temp &= (a[0] == 1 && a[1] == 1); + + a.Assign(three, 2); + + a += a; + temp &= (a.SizeInBytes() == 16); + temp &= (a[0] == 1 && a[1] == 2 && a[2] == 1 && a[3] == 2); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass3 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Append word32\n"; + + try + { + SecBlock a, b; + temp = true; + + const word64 one[1] = {1}, two[1] = {2}; + a.Assign(one, 1); + b.Assign(two, 1); + + a += b; + temp &= (a.SizeInBytes() == 16); + temp &= (a[0] == 1 && a[1] == 2); + + const word64 three[2] = {1,2}, four[2] = {3,4}; + a.Assign(three, 2); + b.Assign(four, 2); + + a += b; + temp &= (a.SizeInBytes() == 32); + temp &= (a[0] == 1 && a[1] == 2 && a[2] == 3 && a[3] == 4); + + a.Assign(one, 1); + + a += a; + temp &= (a.SizeInBytes() == 16); + temp &= (a[0] == 1 && a[1] == 1); + + a.Assign(three, 2); + + a += a; + temp &= (a.SizeInBytes() == 32); + temp &= (a[0] == 1 && a[1] == 2 && a[2] == 1 && a[3] == 2); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass3 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Append word64\n"; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + try + { + SecBlock a, b; + temp = true; + + const word128 one[1] = {1}, two[1] = {2}; + a.Assign(one, 1); + b.Assign(two, 1); + + a += b; + temp &= (a.SizeInBytes() == 32); + temp &= (a[0] == 1 && a[1] == 2); + + const word128 three[2] = {1,2}, four[2] = {3,4}; + a.Assign(three, 2); + b.Assign(four, 2); + + a += b; + temp &= (a.SizeInBytes() == 64); + temp &= (a[0] == 1 && a[1] == 2 && a[2] == 3 && a[3] == 4); + + a.Assign(one, 1); + + a += a; + temp &= (a.SizeInBytes() == 32); + temp &= (a[0] == 1 && a[1] == 1); + + a.Assign(three, 2); + + a += a; + temp &= (a.SizeInBytes() == 64); + temp &= (a[0] == 1 && a[1] == 2 && a[2] == 1 && a[3] == 2); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass3 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Append word128\n"; +#endif + + //********** Concatenate **********// + + // byte + try + { + SecByteBlock a, b, c; + temp = true; + + a.Assign((const byte*)"a", 1); + b.Assign((const byte*)"b", 1); + + c = a + b; + temp &= (a[0] == 'a'); + temp &= (b[0] == 'b'); + temp &= (c.SizeInBytes() == 2); + temp &= (c[0] == 'a' && c[1] == 'b'); + + a.Assign((const byte*)"ab", 2); + b.Assign((const byte*)"cd", 2); + + c = a + b; + temp &= (a[0] == 'a' && a[1] == 'b'); + temp &= (b[0] == 'c' && b[1] == 'd'); + temp &= (c.SizeInBytes() == 4); + temp &= (c[0] == 'a' && c[1] == 'b' && c[2] == 'c' && c[3] == 'd'); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass4 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Concatenate byte\n"; + + // word32 + try + { + SecBlock a, b, c; + temp = true; + + const word32 one[1] = {1}, two[1] = {2}; + a.Assign(one, 1); + b.Assign(two, 1); + + c = a + b; + temp &= (a[0] == 1); + temp &= (b[0] == 2); + temp &= (c.SizeInBytes() == 8); + temp &= (c[0] == 1 && c[1] == 2); + + const word32 three[2] = {1,2}, four[2] = {3,4}; + a.Assign(three, 2); + b.Assign(four, 2); + + c = a + b; + temp &= (a[0] == 1 && a[1] == 2); + temp &= (b[0] == 3 && b[1] == 4); + temp &= (c.SizeInBytes() == 16); + temp &= (c[0] == 1 && c[1] == 2 && c[2] == 3 && c[3] == 4); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass4 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Concatenate word32\n"; + + // word64 + try + { + SecBlock a, b, c; + temp = true; + + const word64 one[1] = {1}, two[1] = {2}; + a.Assign(one, 1); + b.Assign(two, 1); + + c = a + b; + temp &= (a[0] == 1); + temp &= (b[0] == 2); + temp &= (c.SizeInBytes() == 16); + temp &= (c[0] == 1 && c[1] == 2); + + const word64 three[2] = {1,2}, four[2] = {3,4}; + a.Assign(three, 2); + b.Assign(four, 2); + + c = a + b; + temp &= (a[0] == 1 && a[1] == 2); + temp &= (b[0] == 3 && b[1] == 4); + temp &= (c.SizeInBytes() == 32); + temp &= (c[0] == 1 && c[1] == 2 && c[2] == 3 && c[3] == 4); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass4 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Concatenate word64\n"; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + try + { + SecBlock a, b, c; + temp = true; + + const word128 one[1] = {1}, two[1] = {2}; + a.Assign(one, 1); + b.Assign(two, 1); + + c = a + b; + temp &= (a[0] == 1); + temp &= (b[0] == 2); + temp &= (c.SizeInBytes() == 32); + temp &= (c[0] == 1 && c[1] == 2); + + const word128 three[2] = {1,2}, four[2] = {3,4}; + a.Assign(three, 2); + b.Assign(four, 2); + + c = a + b; + temp &= (a[0] == 1 && a[1] == 2); + temp &= (b[0] == 3 && b[1] == 4); + temp &= (c.SizeInBytes() == 64); + temp &= (c[0] == 1 && c[1] == 2 && c[2] == 3 && c[3] == 4); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass4 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Concatenate word128\n"; +#endif + + //********** Equality **********// + + // byte + try + { + static const byte str1[] = "abcdefghijklmnopqrstuvwxyz"; + static const byte str2[] = "zyxwvutsrqponmlkjihgfedcba"; + static const byte str3[] = "0123456789"; + + temp = true; + SecByteBlock a,b; + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str1, COUNTOF(str1)); + temp &= (a.operator==(b)); + + a.Assign(str3, COUNTOF(str3)); + b.Assign(str3, COUNTOF(str3)); + temp &= (a == b); + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str2, COUNTOF(str2)); + temp &= (a.operator!=(b)); + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str3, COUNTOF(str3)); + temp &= (a != b); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass5 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Equality byte\n"; + + // word32 + try + { + static const word32 str1[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97}; + static const word32 str2[] = {97,89,83,79,73,71,67,61,59,53,47,43,41,37,31,29,23,19,17,13,11,7,5,3,2}; + static const word32 str3[] = {0,1,2,3,4,5,6,7,8,9}; + + temp = true; + SecBlock a,b; + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str1, COUNTOF(str1)); + temp &= (a.operator==(b)); + + a.Assign(str3, COUNTOF(str3)); + b.Assign(str3, COUNTOF(str3)); + temp &= (a == b); + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str2, COUNTOF(str2)); + temp &= (a.operator!=(b)); + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str3, COUNTOF(str3)); + temp &= (a != b); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass5 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Equality word32\n"; + + // word64 + try + { + static const word64 str1[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97}; + static const word64 str2[] = {97,89,83,79,73,71,67,61,59,53,47,43,41,37,31,29,23,19,17,13,11,7,5,3,2}; + static const word64 str3[] = {0,1,2,3,4,5,6,7,8,9}; + + temp = true; + SecBlock a,b; + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str1, COUNTOF(str1)); + temp &= (a.operator==(b)); + + a.Assign(str3, COUNTOF(str3)); + b.Assign(str3, COUNTOF(str3)); + temp &= (a == b); + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str2, COUNTOF(str2)); + temp &= (a.operator!=(b)); + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str3, COUNTOF(str3)); + temp &= (a != b); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass5 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Equality word64\n"; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + // word128 + try + { + static const word128 str1[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97}; + static const word128 str2[] = {97,89,83,79,73,71,67,61,59,53,47,43,41,37,31,29,23,19,17,13,11,7,5,3,2}; + static const word128 str3[] = {0,1,2,3,4,5,6,7,8,9}; + + temp = true; + SecBlock a,b; + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str1, COUNTOF(str1)); + temp &= (a.operator==(b)); + + a.Assign(str3, COUNTOF(str3)); + b.Assign(str3, COUNTOF(str3)); + temp &= (a == b); + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str2, COUNTOF(str2)); + temp &= (a.operator!=(b)); + + a.Assign(str1, COUNTOF(str1)); + b.Assign(str3, COUNTOF(str3)); + temp &= (a != b); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + + pass5 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Equality word128\n"; +#endif + + //********** Allocator Size/Overflow **********// + + try + { + temp = false; + + AllocatorBase A; + const size_t max = A.max_size(); + SecBlock t(max+1); + } + catch(const Exception& /*ex*/) + { + temp = true; + } + catch(const std::exception& /*ex*/) + { + temp = true; + } + + pass6 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Overflow word32\n"; + + try + { + temp = false; + + AllocatorBase A; + const size_t max = A.max_size(); + SecBlock t(max+1); + } + catch(const Exception& /*ex*/) + { + temp = true; + } + catch(const std::exception& /*ex*/) + { + temp = true; + } + + pass6 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Overflow word64\n"; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + try + { + temp = false; + + AllocatorBase A; + const size_t max = A.max_size(); + SecBlock t(max+1); + } + catch(const Exception& /*ex*/) + { + temp = true; + } + catch(const std::exception& /*ex*/) + { + temp = true; + } + + pass6 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Overflow word128\n"; +#endif + + //********** FixedSizeAllocatorWithCleanup and Grow **********// + + // byte + try + { + static const unsigned int SIZE = 8; + SecBlockWithHint block(SIZE); + memset(block, 0xaa, block.SizeInBytes()); + + temp = true; + block.CleanGrow(SIZE*2); + temp &= (block.size() == SIZE*2); + + for (size_t i = 0; i < block.size()/2; i++) + temp &= (block[i] == 0xaa); + for (size_t i = block.size()/2; i < block.size(); i++) + temp &= (block[i] == 0); + + block.CleanNew(SIZE*4); + temp &= (block.size() == SIZE*4); + for (size_t i = 0; i < block.size(); i++) + temp &= (block[i] == 0); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + catch(const std::exception& /*ex*/) + { + temp = false; + } + + pass7 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " FixedSizeAllocator Grow with byte\n"; + + // word32 + try + { + static const unsigned int SIZE = 8; + SecBlockWithHint block(SIZE); + memset(block, 0xaa, block.SizeInBytes()); + + temp = true; + block.CleanGrow(SIZE*2); + temp &= (block.size() == SIZE*2); + + for (size_t i = 0; i < block.size()/2; i++) + temp &= (block[i] == 0xaaaaaaaa); + + for (size_t i = block.size()/2; i < block.size(); i++) + temp &= (block[i] == 0); + + block.CleanNew(SIZE*4); + temp &= (block.size() == SIZE*4); + for (size_t i = 0; i < block.size(); i++) + temp &= (block[i] == 0); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + catch(const std::exception& /*ex*/) + { + temp = false; + } + + pass7 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " FixedSizeAllocator Grow with word32\n"; + + // word64 + try + { + static const unsigned int SIZE = 8; + SecBlockWithHint block(SIZE); + memset(block, 0xaa, block.SizeInBytes()); + + temp = true; + block.CleanGrow(SIZE*2); + temp &= (block.size() == SIZE*2); + + for (size_t i = 0; i < block.size()/2; i++) + temp &= (block[i] == W64LIT(0xaaaaaaaaaaaaaaaa)); + + for (size_t i = block.size()/2; i < block.size(); i++) + temp &= (block[i] == 0); + + block.CleanNew(SIZE*4); + temp &= (block.size() == SIZE*4); + for (size_t i = 0; i < block.size(); i++) + temp &= (block[i] == 0); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + catch(const std::exception& /*ex*/) + { + temp = false; + } + + pass7 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " FixedSizeAllocator Grow with word64\n"; + +#if defined(CRYPTOPP_WORD128_AVAILABLE) + // word128 + try + { + static const unsigned int SIZE = 8; + SecBlock > block(SIZE); + memset(block, 0xaa, block.SizeInBytes()); + + temp = true; + block.CleanGrow(SIZE*2); + temp &= (block.size() == SIZE*2); + + for (size_t i = 0; i < block.size()/2; i++) + temp &= (block[i] == (((word128)W64LIT(0xaaaaaaaaaaaaaaaa) << 64U) | W64LIT(0xaaaaaaaaaaaaaaaa))); + + for (size_t i = block.size()/2; i < block.size(); i++) + temp &= (block[i] == 0); + + block.CleanNew(SIZE*4); + temp &= (block.size() == SIZE*4); + for (size_t i = 0; i < block.size(); i++) + temp &= (block[i] == 0); + } + catch(const Exception& /*ex*/) + { + temp = false; + } + catch(const std::exception& /*ex*/) + { + temp = false; + } + + pass7 &= temp; + if (!temp) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " FixedSizeAllocator Grow with word128\n"; +#endif + + return pass1 && pass2 && pass3 && pass4 && pass5 && pass6 && pass7; +} +#endif + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +bool TestHuffmanCodes() +{ + std::cout << "\nTesting Huffman codes...\n\n"; + bool pass=true; + + static const size_t nCodes = 30; + const unsigned int codeCounts[nCodes] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + static const unsigned int maxCodeBits = nCodes >> 1; + unsigned int codeBits[nCodes] = { + ~0u, ~0u, ~0u, ~0u, ~0u, + ~0u, ~0u, ~0u, ~0u, ~0u, + ~0u, ~0u, ~0u, ~0u, ~0u, + }; + + try + { + HuffmanEncoder::GenerateCodeLengths(codeBits, maxCodeBits, codeCounts, nCodes); + } + catch(const Exception& /*ex*/) + { + pass=false; + } + + if (!pass) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " GenerateCodeLengths" << std::endl; + + // Try to crash the HuffmanDecoder + for (unsigned int i=0; i<128; ++i) + { + try + { + byte data1[0xfff]; // Place on stack, avoid new + unsigned int data2[0xff]; + + unsigned int len1 = GlobalRNG().GenerateWord32(4, 0xfff); + GlobalRNG().GenerateBlock(data1, len1); + unsigned int len2 = GlobalRNG().GenerateWord32(4, 0xff); + GlobalRNG().GenerateBlock((byte*)data2, len2*sizeof(unsigned int)); + + ArraySource source(data1, len1, false); + HuffmanDecoder decoder(data2, len2); + + LowFirstBitReader reader(source); + unsigned int val; + for (unsigned int j=0; !source.AnyRetrievable(); ++j) + decoder.Decode(reader, val); + } + catch (const Exception&) {} + } + + std::cout << "passed: HuffmanDecoder decode" << std::endl; + + return pass; +} +#endif + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +# if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +bool TestAltivecOps() +{ + std::cout << "\nTesting Altivec operations...\n\n"; + + if (HasAltivec() == false) + { + std::cout << "\nAltivec not available, skipping test." << std::endl; + return true; + } + + // These tests may seem superflous, but we really want to test the + // Altivec/POWER4 implementation. That does not happen when POWER7 + // or POWER8 is available because we use POWER7's unaligned loads + // and stores with POWER8's AES, SHA, etc. These tests enage + // Altivec/POWER4 without POWER7, like on an old PowerMac. + + //********** Unaligned loads and stores **********// + bool pass1=true; + + CRYPTOPP_ALIGN_DATA(16) + byte dest[20], src[20] = {23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4}; + const byte st1[16] = {22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7}; + const byte st2[16] = {21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6}; + const byte st3[16] = {20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5}; + + VecStore(VecLoad(src), dest); + pass1 = (0 == std::memcmp(src, dest, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); + + VecStore(VecLoad(src+1), dest+1); + pass1 = (0 == std::memcmp(st1, dest+1, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); + + VecStore(VecLoad(src+2), dest+2); + pass1 = (0 == std::memcmp(st2, dest+2, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); + + VecStore(VecLoad(src+3), dest+3); + pass1 = (0 == std::memcmp(st3, dest+3, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); + + VecStoreBE(VecLoadBE(src), dest); + pass1 = (0 == std::memcmp(src, dest, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); + + VecStoreBE(VecLoadBE(src+1), dest+1); + pass1 = (0 == std::memcmp(st1, dest+1, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); + + VecStoreBE(VecLoadBE(src+2), dest+2); + pass1 = (0 == std::memcmp(st2, dest+2, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); + + VecStoreBE(VecLoadBE(src+3), dest+3); + pass1 = (0 == std::memcmp(st3, dest+3, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); + +#if (CRYPTOPP_LITTLE_ENDIAN) + VecStore(VecLoadBE(src), dest); + pass1 = (0 != std::memcmp(src, dest, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); + + VecStoreBE(VecLoad(src), dest); + pass1 = (0 != std::memcmp(src, dest, 16)) && pass1; + CRYPTOPP_ASSERT(pass1); +#endif + + if (!pass1) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Altivec loads and stores" << std::endl; + + //********** Shifts **********// + bool pass2=true; + + uint8x16_p val = {0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff}; + + pass2 = (VecEqual(val, VecShiftLeftOctet<0>(val))) && pass2; + CRYPTOPP_ASSERT(pass2); + pass2 = (VecEqual(val, VecShiftRightOctet<0>(val))) && pass2; + CRYPTOPP_ASSERT(pass2); + + uint8x16_p lsh1 = {0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x00}; + uint8x16_p rsh1 = {0x00,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff}; + + pass2 = (VecEqual(lsh1, VecShiftLeftOctet<1>(val))) && pass2; + CRYPTOPP_ASSERT(pass2); + pass2 = (VecEqual(rsh1, VecShiftRightOctet<1>(val))) && pass2; + CRYPTOPP_ASSERT(pass2); + + uint8x16_p lsh15 = {0xff,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}; + uint8x16_p rsh15 = {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xff}; + + pass2 = (VecEqual(lsh15, VecShiftLeftOctet<15>(val))) && pass2; + CRYPTOPP_ASSERT(pass2); + pass2 = (VecEqual(rsh15, VecShiftRightOctet<15>(val))) && pass2; + CRYPTOPP_ASSERT(pass2); + + uint8x16_p lsh16 = {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}; + uint8x16_p rsh16 = {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}; + + pass2 = (VecEqual(lsh16, VecShiftLeftOctet<16>(val))) && pass2; + CRYPTOPP_ASSERT(pass2); + pass2 = (VecEqual(rsh16, VecShiftRightOctet<16>(val))) && pass2; + CRYPTOPP_ASSERT(pass2); + + if (!pass2) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Altivec left and right shifts" << std::endl; + + //********** Extraction **********// + bool pass3=true; + + const byte bex1[] = {0x1f,0x1e,0x1d,0x1c, 0x1b,0x1a,0x19,0x18, + 0x17,0x16,0x15,0x14, 0x13,0x12,0x11,0x10}; + const byte bex2[] = {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x17,0x16,0x15,0x14, 0x13,0x12,0x11,0x10}; + const byte bex3[] = {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x1f,0x1e,0x1d,0x1c, 0x1b,0x1a,0x19,0x18}; + + const uint8x16_p ex1 = (uint8x16_p)VecLoad(bex1); + const uint8x16_p ex2 = (uint8x16_p)VecLoad(bex2); + const uint8x16_p ex3 = (uint8x16_p)VecLoad(bex3); + + pass3 = VecEqual(ex2, VecGetLow(ex1)) && pass3; + CRYPTOPP_ASSERT(pass3); + pass3 = VecEqual(ex3, VecGetHigh(ex1)) && pass3; + CRYPTOPP_ASSERT(pass3); + + uint8x16_p ex4 = VecShiftRightOctet<8>(VecShiftLeftOctet<8>(ex1)); + pass3 = VecEqual(ex4, VecGetLow(ex1)) && pass3; + CRYPTOPP_ASSERT(pass3); + uint8x16_p ex5 = VecShiftRightOctet<8>(ex1); + pass3 = VecEqual(ex5, VecGetHigh(ex1)) && pass3; + CRYPTOPP_ASSERT(pass3); + + if (!pass3) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Altivec vector extraction" << std::endl; + + return pass1 && pass2 && pass3; +} +#endif +#endif + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/validat10.cpp b/external/ours/library/crypto/src/shared/original/validat10.cpp new file mode 100755 index 000000000..4e7bf9f8e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/validat10.cpp @@ -0,0 +1,535 @@ +// validat10.cpp - written and placed in the public domain by Jeffrey Walton +// Routines in this source file test NaCl library routines. +// Source files split in July 2018 to expedite compiles. +// +// There are two types or sets of self tests. First is a known answer test, +// and second are pairwise consitency checks. The known answer tests are test +// vectors lifted from libsodium. The pairwise consitency checks are randomized +// and confirm the library can arrive at the same result or round trip data +// using it's own transformations. +// +// A link like https://github.com/jedisct1/libsodium/blob/master/test/default/box.c +// references the libsodium test data for a test. For example, box.c is one of the +// test runners for crypto_box, and there is a box.exp with the known answer. The +// glue code for box.c and box.exp is in "cmptest.h". box.c runs the test and +// generates output, while cmptest.h gathers the output and compares them. + +#include "pch.h" + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "secblock.h" +#include "integer.h" +#include "naclite.h" +#include "validate.h" + +#include +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4610 4510 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +#ifndef CRYPTOPP_DISABLE_NACL + +USING_NAMESPACE(NaCl) + +bool TestCryptoBox() +{ + // https://github.com/jedisct1/libsodium/blob/master/test/default/box.c + const byte alicesk[32] = { + 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, + 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, + 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a + }; + + const byte bobpk[32] = { + 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b, 0x61, + 0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, + 0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f + }; + + const byte small_order_p[crypto_box_PUBLICKEYBYTES] = { + 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, + 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, + 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 + }; + + const byte nonce[24] = { + 0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73, 0xcd, 0x62, 0xbd, 0xa8, + 0x75, 0xfc, 0x73, 0xd6, 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37 + }; + + /* API requires first 32 bytes to be 0 */ + const byte m[163] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0xbe, 0x07, 0x5f, 0xc5, + 0x3c, 0x81, 0xf2, 0xd5, 0xcf, 0x14, 0x13, 0x16, 0xeb, 0xeb, 0x0c, 0x7b, + 0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4, 0x4b, 0x66, 0x84, 0x9b, + 0x64, 0x24, 0x4f, 0xfc, 0xe5, 0xec, 0xba, 0xaf, 0x33, 0xbd, 0x75, 0x1a, + 0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29, 0x6c, 0xdc, 0x3c, 0x01, + 0x23, 0x35, 0x61, 0xf4, 0x1d, 0xb6, 0x6c, 0xce, 0x31, 0x4a, 0xdb, 0x31, + 0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d, 0xce, 0xea, 0x3a, 0x7f, + 0xa1, 0x34, 0x80, 0x57, 0xe2, 0xf6, 0x55, 0x6a, 0xd6, 0xb1, 0x31, 0x8a, + 0x02, 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde, 0x04, 0x89, 0x77, 0xeb, + 0x48, 0xf5, 0x9f, 0xfd, 0x49, 0x24, 0xca, 0x1c, 0x60, 0x90, 0x2e, 0x52, + 0xf0, 0xa0, 0x89, 0xbc, 0x76, 0x89, 0x70, 0x40, 0xe0, 0x82, 0xf9, 0x37, + 0x76, 0x38, 0x48, 0x64, 0x5e, 0x07, 0x05 + }; + + const byte exp1[] = { + 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9, + 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce, + 0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a, + 0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72, + 0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38, + 0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae, + 0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda, + 0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3, + 0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74, + 0xe3,0x55,0xa5 + }; + + const byte exp2[] = { + 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9, + 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce, + 0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a, + 0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72, + 0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38, + 0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae, + 0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda, + 0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3, + 0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74, + 0xe3,0x55,0xa5 + }; + + byte c[163]; + byte k[crypto_box_BEFORENMBYTES]; + + bool pass = true; int rc; + + // Reject small order elements + + rc = crypto_box(c, m, 163, nonce, bobpk, alicesk); + pass = (rc == 0) && pass; + pass = (std::memcmp(c+16, exp1, 163-16) == 0) && pass; + + rc = crypto_box(c, m, 163, nonce, small_order_p, alicesk); + pass = (rc != 0) && pass; + std::memset(c, 0, sizeof(c)); + + rc = crypto_box_beforenm(k, bobpk, alicesk); + pass = (rc == 0) && pass; + rc = crypto_box_afternm(c, m, 163, nonce, k); + pass = (rc == 0) && pass; + pass = (std::memcmp(c+16, exp2, 163-16) == 0) && pass; + + rc = crypto_box_beforenm(k, small_order_p, alicesk); + pass = (rc != 0) && pass; + + // Allow small order elements + + rc = crypto_box_unchecked(c, m, 163, nonce, bobpk, alicesk); + pass = (rc == 0) && pass; + pass = (std::memcmp(c+16, exp1, 163-16) == 0) && pass; + + rc = crypto_box_unchecked(c, m, 163, nonce, small_order_p, alicesk); + pass = (rc == 0) && pass; + std::memset(c, 0, sizeof(c)); + + rc = crypto_box_beforenm_unchecked(k, bobpk, alicesk); + pass = (rc == 0) && pass; + rc = crypto_box_afternm(c, m, 163, nonce, k); + pass = (rc == 0) && pass; + pass = (std::memcmp(c+16, exp2, 163-16) == 0) && pass; + + rc = crypto_box_beforenm_unchecked(k, small_order_p, alicesk); + pass = (rc == 0) && pass; + + return pass; +} + +bool TestCryptoBoxOpen() +{ + // https://github.com/jedisct1/libsodium/blob/master/test/default/box2.c + const byte bobsk[32] = { + 0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b, 0x79, 0xe1, 0x7f, 0x8b, 0x83, 0x80, + 0x0e, 0xe6, 0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 0xb6, 0xfd, 0x1c, 0x2f, 0x8b, 0x27, + 0xff, 0x88, 0xe0, 0xeb + }; + + const byte alicepk[32] = { + 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 0x7d, 0xdc, 0xb4, 0x3e, + 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, + 0xaa, 0x9b, 0x4e, 0x6a + }; + + static const byte small_order_p[crypto_box_PUBLICKEYBYTES] = { + 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, + 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, + 0x5f, 0x49, 0xb8, 0x00 + }; + + const byte nonce[24] = { + 0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73, 0xcd, 0x62, 0xbd, 0xa8, + 0x75, 0xfc, 0x73, 0xd6, 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37 + }; + + /* API requires first 16 bytes to be 0 */ + const byte c[163] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5, + 0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9, 0x8e, 0x99, 0x3b, 0x9f, + 0x48, 0x68, 0x12, 0x73, 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce, + 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4, 0x47, 0x6f, 0xb8, 0xc5, + 0x31, 0xa1, 0x18, 0x6a, 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b, + 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72, 0x71, 0xd2, 0xc2, 0x0f, + 0x9b, 0x92, 0x8f, 0xe2, 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38, + 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a, 0xb9, 0x32, 0x16, 0x45, + 0x48, 0xe5, 0x26, 0xae, 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea, + 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda, 0x99, 0x83, 0x2b, 0x61, + 0xca, 0x01, 0xb6, 0xde, 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3, + 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6, 0x59, 0x9b, 0x1f, 0x65, + 0x4c, 0xb4, 0x5a, 0x74, 0xe3, 0x55, 0xa5 + }; + + const byte exp1[] = { + 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5, 0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b, + 0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4, 0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc, + 0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a, 0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29, + 0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4, 0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31, + 0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d, 0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57, + 0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a, 0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde, + 0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd, 0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52, + 0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40, 0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64, + 0x5e,0x07,0x05 + }; + + const byte exp2[] = { + 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5, 0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b, + 0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4, 0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc, + 0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a, 0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29, + 0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4, 0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31, + 0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d, 0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57, + 0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a, 0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde, + 0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd, 0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52, + 0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40, 0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64, + 0x5e,0x07,0x05 + }; + + byte m[163]; + byte k[crypto_box_BEFORENMBYTES]; + + bool pass = true; int rc; + + // Reject small order elements + + rc = crypto_box_open(m, c, 163, nonce, alicepk, bobsk); + pass = (rc == 0) && pass; + pass = (std::memcmp(m+32, exp1, 163-32) == 0) && pass; + + rc = crypto_box_open(m, c, 163, nonce, small_order_p, bobsk); + pass = (rc != 0) && pass; + + rc = crypto_box_beforenm(k, small_order_p, bobsk); + pass = (rc != 0) && pass; + rc = crypto_box_beforenm(k, alicepk, bobsk); + pass = (rc == 0) && pass; + + rc = crypto_box_open_afternm(m, c, 163, nonce, k); + pass = (rc == 0) && pass; + pass = (std::memcmp(m+32, exp2, 163-32) == 0) && pass; + + // Allow small order elements + + rc = crypto_box_open_unchecked(m, c, 163, nonce, alicepk, bobsk); + pass = (rc == 0) && pass; + pass = (std::memcmp(m+32, exp1, 163-32) == 0) && pass; + + rc = crypto_box_beforenm_unchecked(k, small_order_p, bobsk); + pass = (rc == 0) && pass; + rc = crypto_box_beforenm_unchecked(k, alicepk, bobsk); + pass = (rc == 0) && pass; + + rc = crypto_box_open_afternm(m, c, 163, nonce, k); + pass = (rc == 0) && pass; + pass = (std::memcmp(m+32, exp2, 163-32) == 0) && pass; + + return pass; +} + +bool TestCryptoBoxKeys() +{ + // https://github.com/jedisct1/libsodium/blob/master/test/default/box7.c + const unsigned int MAX_TEST = 64; + const unsigned int MAX_MESSAGE = 4096; + + byte alicesk[crypto_box_SECRETKEYBYTES]; + byte alicepk[crypto_box_PUBLICKEYBYTES]; + byte bobsk[crypto_box_SECRETKEYBYTES]; + byte bobpk[crypto_box_PUBLICKEYBYTES]; + + // byte m[MAX_MESSAGE+32]; + // byte c[MAX_MESSAGE+32]; + // byte r[MAX_MESSAGE+32]; + + bool pass = true, fail; int rc; + for (unsigned int i=0; i < MAX_TEST; ++i) + { + fail = (crypto_box_keypair(alicepk, alicesk) != 0); + pass = !fail && pass; + fail = (crypto_box_keypair(bobpk, bobsk) != 0); + pass = !fail && pass; + + SecByteBlock m, c, r, n; + const word32 len = (i == 0 ? 0 : GlobalRNG().GenerateWord32(1, MAX_MESSAGE)); + + m.New(len+crypto_box_ZEROBYTES); + c.New(len+crypto_box_BOXZEROBYTES+crypto_box_MACBYTES); + r.New(len+crypto_box_ZEROBYTES); + n.New(crypto_box_NONCEBYTES); + + GlobalRNG().GenerateBlock(m+crypto_box_ZEROBYTES, len); + GlobalRNG().GenerateBlock(n, crypto_box_NONCEBYTES); + + std::memset(m, 0x00, crypto_box_ZEROBYTES); + rc = crypto_box(c, m, len + crypto_box_ZEROBYTES, n, bobpk, alicesk); + fail = (rc != 0); pass = !fail && pass; + + std::memset(c, 0x00, crypto_box_BOXZEROBYTES); + rc = crypto_box_open(r, c, len + crypto_box_BOXZEROBYTES + crypto_box_MACBYTES, n, alicepk, bobsk); + fail = (rc != 0); pass = !fail && pass; + + fail = std::memcmp(m+crypto_box_ZEROBYTES, r+crypto_box_ZEROBYTES, len) != 0; + pass = !fail && pass; + + m.SetMark(16); c.SetMark(16); r.SetMark(16); + } + + return pass; +} + +struct TestData { + const byte sk[crypto_sign_SEEDBYTES]; + const byte pk[crypto_sign_PUBLICKEYBYTES]; + const byte sig[crypto_sign_BYTES]; + const word32 len; + const char* msg; +}; + +// https://github.com/jedisct1/libsodium/blob/master/test/default/sign.c +const TestData test_data[] = { + {{0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60,0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4,0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19,0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60,},{0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7,0xd5,0x4b,0xfe,0xd3,0xc9,0x64,0x07,0x3a,0x0e,0xe1,0x72,0xf3,0xda,0xa6,0x23,0x25,0xaf,0x02,0x1a,0x68,0xf7,0x07,0x51,0x1a,},{0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72,0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a,0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74,0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55,0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac,0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b,0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24,0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b,},0,""}, + {{0x4c,0xcd,0x08,0x9b,0x28,0xff,0x96,0xda,0x9d,0xb6,0xc3,0x46,0xec,0x11,0x4e,0x0f,0x5b,0x8a,0x31,0x9f,0x35,0xab,0xa6,0x24,0xda,0x8c,0xf6,0xed,0x4f,0xb8,0xa6,0xfb,},{0x3d,0x40,0x17,0xc3,0xe8,0x43,0x89,0x5a,0x92,0xb7,0x0a,0xa7,0x4d,0x1b,0x7e,0xbc,0x9c,0x98,0x2c,0xcf,0x2e,0xc4,0x96,0x8c,0xc0,0xcd,0x55,0xf1,0x2a,0xf4,0x66,0x0c,},{0x92,0xa0,0x09,0xa9,0xf0,0xd4,0xca,0xb8,0x72,0x0e,0x82,0x0b,0x5f,0x64,0x25,0x40,0xa2,0xb2,0x7b,0x54,0x16,0x50,0x3f,0x8f,0xb3,0x76,0x22,0x23,0xeb,0xdb,0x69,0xda,0x08,0x5a,0xc1,0xe4,0x3e,0x15,0x99,0x6e,0x45,0x8f,0x36,0x13,0xd0,0xf1,0x1d,0x8c,0x38,0x7b,0x2e,0xae,0xb4,0x30,0x2a,0xee,0xb0,0x0d,0x29,0x16,0x12,0xbb,0x0c,0x00,},1,"\x72"}, + {{0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b,0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1,0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b,0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7,},{0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3,0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58,0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac,0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25,},{0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02,0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3,0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44,0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac,0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90,0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59,0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d,0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a,},2,"\xaf\x82"}, + {{0x0d,0x4a,0x05,0xb0,0x73,0x52,0xa5,0x43,0x6e,0x18,0x03,0x56,0xda,0x0a,0xe6,0xef,0xa0,0x34,0x5f,0xf7,0xfb,0x15,0x72,0x57,0x57,0x72,0xe8,0x00,0x5e,0xd9,0x78,0xe9,},{0xe6,0x1a,0x18,0x5b,0xce,0xf2,0x61,0x3a,0x6c,0x7c,0xb7,0x97,0x63,0xce,0x94,0x5d,0x3b,0x24,0x5d,0x76,0x11,0x4d,0xd4,0x40,0xbc,0xf5,0xf2,0xdc,0x1a,0xa5,0x70,0x57,},{0xd9,0x86,0x8d,0x52,0xc2,0xbe,0xbc,0xe5,0xf3,0xfa,0x5a,0x79,0x89,0x19,0x70,0xf3,0x09,0xcb,0x65,0x91,0xe3,0xe1,0x70,0x2a,0x70,0x27,0x6f,0xa9,0x7c,0x24,0xb3,0xa8,0xe5,0x86,0x06,0xc3,0x8c,0x97,0x58,0x52,0x9d,0xa5,0x0e,0xe3,0x1b,0x82,0x19,0xcb,0xa4,0x52,0x71,0xc6,0x89,0xaf,0xa6,0x0b,0x0e,0xa2,0x6c,0x99,0xdb,0x19,0xb0,0x0c,},3,"\xcb\xc7\x7b"}, + {{0x6d,0xf9,0x34,0x0c,0x13,0x8c,0xc1,0x88,0xb5,0xfe,0x44,0x64,0xeb,0xaa,0x3f,0x7f,0xc2,0x06,0xa2,0xd5,0x5c,0x34,0x34,0x70,0x7e,0x74,0xc9,0xfc,0x04,0xe2,0x0e,0xbb,},{0xc0,0xda,0xc1,0x02,0xc4,0x53,0x31,0x86,0xe2,0x5d,0xc4,0x31,0x28,0x47,0x23,0x53,0xea,0xab,0xdb,0x87,0x8b,0x15,0x2a,0xeb,0x8e,0x00,0x1f,0x92,0xd9,0x02,0x33,0xa7,},{0x12,0x4f,0x6f,0xc6,0xb0,0xd1,0x00,0x84,0x27,0x69,0xe7,0x1b,0xd5,0x30,0x66,0x4d,0x88,0x8d,0xf8,0x50,0x7d,0xf6,0xc5,0x6d,0xed,0xfd,0xb5,0x09,0xae,0xb9,0x34,0x16,0xe2,0x6b,0x91,0x8d,0x38,0xaa,0x06,0x30,0x5d,0xf3,0x09,0x56,0x97,0xc1,0x8b,0x2a,0xa8,0x32,0xea,0xa5,0x2e,0xdc,0x0a,0xe4,0x9f,0xba,0xe5,0xa8,0x5e,0x15,0x0c,0x07,},4,"\x5f\x4c\x89\x89"}, + {{0xb7,0x80,0x38,0x1a,0x65,0xed,0xf8,0xb7,0x8f,0x69,0x45,0xe8,0xdb,0xec,0x79,0x41,0xac,0x04,0x9f,0xd4,0xc6,0x10,0x40,0xcf,0x0c,0x32,0x43,0x57,0x97,0x5a,0x29,0x3c,},{0xe2,0x53,0xaf,0x07,0x66,0x80,0x4b,0x86,0x9b,0xb1,0x59,0x5b,0xe9,0x76,0x5b,0x53,0x48,0x86,0xbb,0xaa,0xb8,0x30,0x5b,0xf5,0x0d,0xbc,0x7f,0x89,0x9b,0xfb,0x5f,0x01,},{0xb2,0xfc,0x46,0xad,0x47,0xaf,0x46,0x44,0x78,0xc1,0x99,0xe1,0xf8,0xbe,0x16,0x9f,0x1b,0xe6,0x32,0x7c,0x7f,0x9a,0x0a,0x66,0x89,0x37,0x1c,0xa9,0x4c,0xaf,0x04,0x06,0x4a,0x01,0xb2,0x2a,0xff,0x15,0x20,0xab,0xd5,0x89,0x51,0x34,0x16,0x03,0xfa,0xed,0x76,0x8c,0xf7,0x8c,0xe9,0x7a,0xe7,0xb0,0x38,0xab,0xfe,0x45,0x6a,0xa1,0x7c,0x09,},5,"\x18\xb6\xbe\xc0\x97"}, + {{0x78,0xae,0x9e,0xff,0xe6,0xf2,0x45,0xe9,0x24,0xa7,0xbe,0x63,0x04,0x11,0x46,0xeb,0xc6,0x70,0xdb,0xd3,0x06,0x0c,0xba,0x67,0xfb,0xc6,0x21,0x6f,0xeb,0xc4,0x45,0x46,},{0xfb,0xcf,0xbf,0xa4,0x05,0x05,0xd7,0xf2,0xbe,0x44,0x4a,0x33,0xd1,0x85,0xcc,0x54,0xe1,0x6d,0x61,0x52,0x60,0xe1,0x64,0x0b,0x2b,0x50,0x87,0xb8,0x3e,0xe3,0x64,0x3d,},{0x6e,0xd6,0x29,0xfc,0x1d,0x9c,0xe9,0xe1,0x46,0x87,0x55,0xff,0x63,0x6d,0x5a,0x3f,0x40,0xa5,0xd9,0xc9,0x1a,0xfd,0x93,0xb7,0x9d,0x24,0x18,0x30,0xf7,0xe5,0xfa,0x29,0x85,0x4b,0x8f,0x20,0xcc,0x6e,0xec,0xbb,0x24,0x8d,0xbd,0x8d,0x16,0xd1,0x4e,0x99,0x75,0x21,0x94,0xe4,0x90,0x4d,0x09,0xc7,0x4d,0x63,0x95,0x18,0x83,0x9d,0x23,0x00,},6,"\x89\x01\x0d\x85\x59\x72"}, + {{0x69,0x18,0x65,0xbf,0xc8,0x2a,0x1e,0x4b,0x57,0x4e,0xec,0xde,0x4c,0x75,0x19,0x09,0x3f,0xaf,0x0c,0xf8,0x67,0x38,0x02,0x34,0xe3,0x66,0x46,0x45,0xc6,0x1c,0x5f,0x79,},{0x98,0xa5,0xe3,0xa3,0x6e,0x67,0xaa,0xba,0x89,0x88,0x8b,0xf0,0x93,0xde,0x1a,0xd9,0x63,0xe7,0x74,0x01,0x3b,0x39,0x02,0xbf,0xab,0x35,0x6d,0x8b,0x90,0x17,0x8a,0x63,},{0x6e,0x0a,0xf2,0xfe,0x55,0xae,0x37,0x7a,0x6b,0x7a,0x72,0x78,0xed,0xfb,0x41,0x9b,0xd3,0x21,0xe0,0x6d,0x0d,0xf5,0xe2,0x70,0x37,0xdb,0x88,0x12,0xe7,0xe3,0x52,0x98,0x10,0xfa,0x55,0x52,0xf6,0xc0,0x02,0x09,0x85,0xca,0x17,0xa0,0xe0,0x2e,0x03,0x6d,0x7b,0x22,0x2a,0x24,0xf9,0x9b,0x77,0xb7,0x5f,0xdd,0x16,0xcb,0x05,0x56,0x81,0x07,},7,"\xb4\xa8\xf3\x81\xe7\x0e\x7a"}, + {{0x3b,0x26,0x51,0x6f,0xb3,0xdc,0x88,0xeb,0x18,0x1b,0x9e,0xd7,0x3f,0x0b,0xcd,0x52,0xbc,0xd6,0xb4,0xc7,0x88,0xe4,0xbc,0xaf,0x46,0x05,0x7f,0xd0,0x78,0xbe,0xe0,0x73,},{0xf8,0x1f,0xb5,0x4a,0x82,0x5f,0xce,0xd9,0x5e,0xb0,0x33,0xaf,0xcd,0x64,0x31,0x40,0x75,0xab,0xfb,0x0a,0xbd,0x20,0xa9,0x70,0x89,0x25,0x03,0x43,0x6f,0x34,0xb8,0x63,},{0xd6,0xad,0xde,0xc5,0xaf,0xb0,0x52,0x8a,0xc1,0x7b,0xb1,0x78,0xd3,0xe7,0xf2,0x88,0x7f,0x9a,0xdb,0xb1,0xad,0x16,0xe1,0x10,0x54,0x5e,0xf3,0xbc,0x57,0xf9,0xde,0x23,0x14,0xa5,0xc8,0x38,0x8f,0x72,0x3b,0x89,0x07,0xbe,0x0f,0x3a,0xc9,0x0c,0x62,0x59,0xbb,0xe8,0x85,0xec,0xc1,0x76,0x45,0xdf,0x3d,0xb7,0xd4,0x88,0xf8,0x05,0xfa,0x08,},8,"\x42\x84\xab\xc5\x1b\xb6\x72\x35"}, + {{0xed,0xc6,0xf5,0xfb,0xdd,0x1c,0xee,0x4d,0x10,0x1c,0x06,0x35,0x30,0xa3,0x04,0x90,0xb2,0x21,0xbe,0x68,0xc0,0x36,0xf5,0xb0,0x7d,0x0f,0x95,0x3b,0x74,0x5d,0xf1,0x92,},{0xc1,0xa4,0x9c,0x66,0xe6,0x17,0xf9,0xef,0x5e,0xc6,0x6b,0xc4,0xc6,0x56,0x4c,0xa3,0x3d,0xe2,0xa5,0xfb,0x5e,0x14,0x64,0x06,0x2e,0x6d,0x6c,0x62,0x19,0x15,0x5e,0xfd,},{0x2c,0x76,0xa0,0x4a,0xf2,0x39,0x1c,0x14,0x70,0x82,0xe3,0x3f,0xaa,0xcd,0xbe,0x56,0x64,0x2a,0x1e,0x13,0x4b,0xd3,0x88,0x62,0x0b,0x85,0x2b,0x90,0x1a,0x6b,0xc1,0x6f,0xf6,0xc9,0xcc,0x94,0x04,0xc4,0x1d,0xea,0x12,0xed,0x28,0x1d,0xa0,0x67,0xa1,0x51,0x38,0x66,0xf9,0xd9,0x64,0xf8,0xbd,0xd2,0x49,0x53,0x85,0x6c,0x50,0x04,0x29,0x01,},9,"\x67\x2b\xf8\x96\x5d\x04\xbc\x51\x46"}, + {{0x4e,0x7d,0x21,0xfb,0x3b,0x18,0x97,0x57,0x1a,0x44,0x58,0x33,0xbe,0x0f,0x9f,0xd4,0x1c,0xd6,0x2b,0xe3,0xaa,0x04,0x04,0x0f,0x89,0x34,0xe1,0xfc,0xbd,0xca,0xcd,0x45,},{0x31,0xb2,0x52,0x4b,0x83,0x48,0xf7,0xab,0x1d,0xfa,0xfa,0x67,0x5c,0xc5,0x38,0xe9,0xa8,0x4e,0x3f,0xe5,0x81,0x9e,0x27,0xc1,0x2a,0xd8,0xbb,0xc1,0xa3,0x6e,0x4d,0xff,},{0x28,0xe4,0x59,0x8c,0x41,0x5a,0xe9,0xde,0x01,0xf0,0x3f,0x9f,0x3f,0xab,0x4e,0x91,0x9e,0x8b,0xf5,0x37,0xdd,0x2b,0x0c,0xdf,0x6e,0x79,0xb9,0xe6,0x55,0x9c,0x94,0x09,0xd9,0x15,0x1a,0x4c,0x40,0xf0,0x83,0x19,0x39,0x37,0x62,0x7c,0x36,0x94,0x88,0x25,0x9e,0x99,0xda,0x5a,0x9f,0x0a,0x87,0x49,0x7f,0xa6,0x69,0x6a,0x5d,0xd6,0xce,0x08,},10,"\x33\xd7\xa7\x86\xad\xed\x8c\x1b\xf6\x91"}, + {{0xa9,0x80,0xf8,0x92,0xdb,0x13,0xc9,0x9a,0x3e,0x89,0x71,0xe9,0x65,0xb2,0xff,0x3d,0x41,0xea,0xfd,0x54,0x09,0x3b,0xc9,0xf3,0x4d,0x1f,0xd2,0x2d,0x84,0x11,0x5b,0xb6,},{0x44,0xb5,0x7e,0xe3,0x0c,0xdb,0x55,0x82,0x9d,0x0a,0x5d,0x4f,0x04,0x6b,0xae,0xf0,0x78,0xf1,0xe9,0x7a,0x7f,0x21,0xb6,0x2d,0x75,0xf8,0xe9,0x6e,0xa1,0x39,0xc3,0x5f,},{0x77,0xd3,0x89,0xe5,0x99,0x63,0x0d,0x93,0x40,0x76,0x32,0x95,0x83,0xcd,0x41,0x05,0xa6,0x49,0xa9,0x29,0x2a,0xbc,0x44,0xcd,0x28,0xc4,0x00,0x00,0xc8,0xe2,0xf5,0xac,0x76,0x60,0xa8,0x1c,0x85,0xb7,0x2a,0xf8,0x45,0x2d,0x7d,0x25,0xc0,0x70,0x86,0x1d,0xae,0x91,0x60,0x1c,0x78,0x03,0xd6,0x56,0x53,0x16,0x50,0xdd,0x4e,0x5c,0x41,0x00,},11,"\x34\x86\xf6\x88\x48\xa6\x5a\x0e\xb5\x50\x7d"}, + {{0x5b,0x5a,0x61,0x9f,0x8c,0xe1,0xc6,0x6d,0x7c,0xe2,0x6e,0x5a,0x2a,0xe7,0xb0,0xc0,0x4f,0xeb,0xcd,0x34,0x6d,0x28,0x6c,0x92,0x9e,0x19,0xd0,0xd5,0x97,0x3b,0xfe,0xf9,},{0x6f,0xe8,0x36,0x93,0xd0,0x11,0xd1,0x11,0x13,0x1c,0x4f,0x3f,0xba,0xaa,0x40,0xa9,0xd3,0xd7,0x6b,0x30,0x01,0x2f,0xf7,0x3b,0xb0,0xe3,0x9e,0xc2,0x7a,0xb1,0x82,0x57,},{0x0f,0x9a,0xd9,0x79,0x30,0x33,0xa2,0xfa,0x06,0x61,0x4b,0x27,0x7d,0x37,0x38,0x1e,0x6d,0x94,0xf6,0x5a,0xc2,0xa5,0xa9,0x45,0x58,0xd0,0x9e,0xd6,0xce,0x92,0x22,0x58,0xc1,0xa5,0x67,0x95,0x2e,0x86,0x3a,0xc9,0x42,0x97,0xae,0xc3,0xc0,0xd0,0xc8,0xdd,0xf7,0x10,0x84,0xe5,0x04,0x86,0x0b,0xb6,0xba,0x27,0x44,0x9b,0x55,0xad,0xc4,0x0e,},12,"\x5a\x8d\x9d\x0a\x22\x35\x7e\x66\x55\xf9\xc7\x85"}, + {{0x94,0x0c,0x89,0xfe,0x40,0xa8,0x1d,0xaf,0xbd,0xb2,0x41,0x6d,0x14,0xae,0x46,0x91,0x19,0x86,0x97,0x44,0x41,0x0c,0x33,0x03,0xbf,0xaa,0x02,0x41,0xda,0xc5,0x78,0x00,},{0xa2,0xeb,0x8c,0x05,0x01,0xe3,0x0b,0xae,0x0c,0xf8,0x42,0xd2,0xbd,0xe8,0xde,0xc7,0x38,0x6f,0x6b,0x7f,0xc3,0x98,0x1b,0x8c,0x57,0xc9,0x79,0x2b,0xb9,0x4c,0xf2,0xdd,},{0xd8,0xbb,0x64,0xaa,0xd8,0xc9,0x95,0x5a,0x11,0x5a,0x79,0x3a,0xdd,0xd2,0x4f,0x7f,0x2b,0x07,0x76,0x48,0x71,0x4f,0x49,0xc4,0x69,0x4e,0xc9,0x95,0xb3,0x30,0xd0,0x9d,0x64,0x0d,0xf3,0x10,0xf4,0x47,0xfd,0x7b,0x6c,0xb5,0xc1,0x4f,0x9f,0xe9,0xf4,0x90,0xbc,0xf8,0xcf,0xad,0xbf,0xd2,0x16,0x9c,0x8a,0xc2,0x0d,0x3b,0x8a,0xf4,0x9a,0x0c,},13,"\xb8\x7d\x38\x13\xe0\x3f\x58\xcf\x19\xfd\x0b\x63\x95"}, + {{0x9a,0xca,0xd9,0x59,0xd2,0x16,0x21,0x2d,0x78,0x9a,0x11,0x92,0x52,0xeb,0xfe,0x0c,0x96,0x51,0x2a,0x23,0xc7,0x3b,0xd9,0xf3,0xb2,0x02,0x29,0x2d,0x69,0x16,0xa7,0x38,},{0xcf,0x3a,0xf8,0x98,0x46,0x7a,0x5b,0x7a,0x52,0xd3,0x3d,0x53,0xbc,0x03,0x7e,0x26,0x42,0xa8,0xda,0x99,0x69,0x03,0xfc,0x25,0x22,0x17,0xe9,0xc0,0x33,0xe2,0xf2,0x91,},{0x6e,0xe3,0xfe,0x81,0xe2,0x3c,0x60,0xeb,0x23,0x12,0xb2,0x00,0x6b,0x3b,0x25,0xe6,0x83,0x8e,0x02,0x10,0x66,0x23,0xf8,0x44,0xc4,0x4e,0xdb,0x8d,0xaf,0xd6,0x6a,0xb0,0x67,0x10,0x87,0xfd,0x19,0x5d,0xf5,0xb8,0xf5,0x8a,0x1d,0x6e,0x52,0xaf,0x42,0x90,0x80,0x53,0xd5,0x5c,0x73,0x21,0x01,0x00,0x92,0x74,0x87,0x95,0xef,0x94,0xcf,0x06,},14,"\x55\xc7\xfa\x43\x4f\x5e\xd8\xcd\xec\x2b\x7a\xea\xc1\x73"}, + {{0xd5,0xae,0xee,0x41,0xee,0xb0,0xe9,0xd1,0xbf,0x83,0x37,0xf9,0x39,0x58,0x7e,0xbe,0x29,0x61,0x61,0xe6,0xbf,0x52,0x09,0xf5,0x91,0xec,0x93,0x9e,0x14,0x40,0xc3,0x00,},{0xfd,0x2a,0x56,0x57,0x23,0x16,0x3e,0x29,0xf5,0x3c,0x9d,0xe3,0xd5,0xe8,0xfb,0xe3,0x6a,0x7a,0xb6,0x6e,0x14,0x39,0xec,0x4e,0xae,0x9c,0x0a,0x60,0x4a,0xf2,0x91,0xa5,},{0xf6,0x8d,0x04,0x84,0x7e,0x5b,0x24,0x97,0x37,0x89,0x9c,0x01,0x4d,0x31,0xc8,0x05,0xc5,0x00,0x7a,0x62,0xc0,0xa1,0x0d,0x50,0xbb,0x15,0x38,0xc5,0xf3,0x55,0x03,0x95,0x1f,0xbc,0x1e,0x08,0x68,0x2f,0x2c,0xc0,0xc9,0x2e,0xfe,0x8f,0x49,0x85,0xde,0xc6,0x1d,0xcb,0xd5,0x4d,0x4b,0x94,0xa2,0x25,0x47,0xd2,0x44,0x51,0x27,0x1c,0x8b,0x00,},15,"\x0a\x68\x8e\x79\xbe\x24\xf8\x66\x28\x6d\x46\x46\xb5\xd8\x1c"}, + {{0x0a,0x47,0xd1,0x04,0x52,0xae,0x2f,0xeb,0xec,0x51,0x8a,0x1c,0x7c,0x36,0x28,0x90,0xc3,0xfc,0x1a,0x49,0xd3,0x4b,0x03,0xb6,0x46,0x7d,0x35,0xc9,0x04,0xa8,0x36,0x2d,},{0x34,0xe5,0xa8,0x50,0x8c,0x47,0x43,0x74,0x69,0x62,0xc0,0x66,0xe4,0xba,0xde,0xa2,0x20,0x1b,0x8a,0xb4,0x84,0xde,0x5c,0x4f,0x94,0x47,0x6c,0xcd,0x21,0x43,0x95,0x5b,},{0x2a,0x3d,0x27,0xdc,0x40,0xd0,0xa8,0x12,0x79,0x49,0xa3,0xb7,0xf9,0x08,0xb3,0x68,0x8f,0x63,0xb7,0xf1,0x4f,0x65,0x1a,0xac,0xd7,0x15,0x94,0x0b,0xdb,0xe2,0x7a,0x08,0x09,0xaa,0xc1,0x42,0xf4,0x7a,0xb0,0xe1,0xe4,0x4f,0xa4,0x90,0xba,0x87,0xce,0x53,0x92,0xf3,0x3a,0x89,0x15,0x39,0xca,0xf1,0xef,0x4c,0x36,0x7c,0xae,0x54,0x50,0x0c,},16,"\xc9\x42\xfa\x7a\xc6\xb2\x3a\xb7\xff\x61\x2f\xdc\x8e\x68\xef\x39"}, + {{0xf8,0x14,0x8f,0x75,0x06,0xb7,0x75,0xef,0x46,0xfd,0xc8,0xe8,0xc7,0x56,0x51,0x68,0x12,0xd4,0x7d,0x6c,0xfb,0xfa,0x31,0x8c,0x27,0xc9,0xa2,0x26,0x41,0xe5,0x6f,0x17,},{0x04,0x45,0xe4,0x56,0xda,0xcc,0x7d,0x5b,0x0b,0xbe,0xd2,0x3c,0x82,0x00,0xcd,0xb7,0x4b,0xdc,0xb0,0x3e,0x4c,0x7b,0x73,0xf0,0xa2,0xb9,0xb4,0x6e,0xac,0x5d,0x43,0x72,},{0x36,0x53,0xcc,0xb2,0x12,0x19,0x20,0x2b,0x84,0x36,0xfb,0x41,0xa3,0x2b,0xa2,0x61,0x8c,0x4a,0x13,0x34,0x31,0xe6,0xe6,0x34,0x63,0xce,0xb3,0xb6,0x10,0x6c,0x4d,0x56,0xe1,0xd2,0xba,0x16,0x5b,0xa7,0x6e,0xaa,0xd3,0xdc,0x39,0xbf,0xfb,0x13,0x0f,0x1d,0xe3,0xd8,0xe6,0x42,0x7d,0xb5,0xb7,0x19,0x38,0xdb,0x4e,0x27,0x2b,0xc3,0xe2,0x0b,},17,"\x73\x68\x72\x4a\x5b\x0e\xfb\x57\xd2\x8d\x97\x62\x2d\xbd\xe7\x25\xaf"}, + {{0x77,0xf8,0x86,0x91,0xc4,0xef,0xf2,0x3e,0xbb,0x73,0x64,0x94,0x70,0x92,0x95,0x1a,0x5f,0xf3,0xf1,0x07,0x85,0xb4,0x17,0xe9,0x18,0x82,0x3a,0x55,0x2d,0xab,0x7c,0x75,},{0x74,0xd2,0x91,0x27,0xf1,0x99,0xd8,0x6a,0x86,0x76,0xae,0xc3,0x3b,0x4c,0xe3,0xf2,0x25,0xcc,0xb1,0x91,0xf5,0x2c,0x19,0x1c,0xcd,0x1e,0x8c,0xca,0x65,0x21,0x3a,0x6b,},{0xfb,0xe9,0x29,0xd7,0x43,0xa0,0x3c,0x17,0x91,0x05,0x75,0x49,0x2f,0x30,0x92,0xee,0x2a,0x2b,0xf1,0x4a,0x60,0xa3,0xfc,0xac,0xec,0x74,0xa5,0x8c,0x73,0x34,0x51,0x0f,0xc2,0x62,0xdb,0x58,0x27,0x91,0x32,0x2d,0x6c,0x8c,0x41,0xf1,0x70,0x0a,0xdb,0x80,0x02,0x7e,0xca,0xbc,0x14,0x27,0x0b,0x70,0x34,0x44,0xae,0x3e,0xe7,0x62,0x3e,0x0a,},18,"\xbd\x8e\x05\x03\x3f\x3a\x8b\xcd\xcb\xf4\xbe\xce\xb7\x09\x01\xc8\x2e\x31"}, + {{0xab,0x6f,0x7a,0xee,0x6a,0x08,0x37,0xb3,0x34,0xba,0x5e,0xb1,0xb2,0xad,0x7f,0xce,0xcf,0xab,0x7e,0x32,0x3c,0xab,0x18,0x7f,0xe2,0xe0,0xa9,0x5d,0x80,0xef,0xf1,0x32,},{0x5b,0x96,0xdc,0xa4,0x97,0x87,0x5b,0xf9,0x66,0x4c,0x5e,0x75,0xfa,0xcf,0x3f,0x9b,0xc5,0x4b,0xae,0x91,0x3d,0x66,0xca,0x15,0xee,0x85,0xf1,0x49,0x1c,0xa2,0x4d,0x2c,},{0x73,0xbc,0xa6,0x4e,0x9d,0xd0,0xdb,0x88,0x13,0x8e,0xed,0xfa,0xfc,0xea,0x8f,0x54,0x36,0xcf,0xb7,0x4b,0xfb,0x0e,0x77,0x33,0xcf,0x34,0x9b,0xaa,0x0c,0x49,0x77,0x5c,0x56,0xd5,0x93,0x4e,0x1d,0x38,0xe3,0x6f,0x39,0xb7,0xc5,0xbe,0xb0,0xa8,0x36,0x51,0x0c,0x45,0x12,0x6f,0x8e,0xc4,0xb6,0x81,0x05,0x19,0x90,0x5b,0x0c,0xa0,0x7c,0x09,},19,"\x81\x71\x45\x6f\x8b\x90\x71\x89\xb1\xd7\x79\xe2\x6b\xc5\xaf\xbb\x08\xc6\x7a"}, + {{0x8d,0x13,0x5d,0xe7,0xc8,0x41,0x1b,0xbd,0xbd,0x1b,0x31,0xe5,0xdc,0x67,0x8f,0x2a,0xc7,0x10,0x9e,0x79,0x2b,0x60,0xf3,0x8c,0xd2,0x49,0x36,0xe8,0xa8,0x98,0xc3,0x2d,},{0x1c,0xa2,0x81,0x93,0x85,0x29,0x89,0x65,0x35,0xa7,0x71,0x4e,0x35,0x84,0x08,0x5b,0x86,0xef,0x9f,0xec,0x72,0x3f,0x42,0x81,0x9f,0xc8,0xdd,0x5d,0x8c,0x00,0x81,0x7f,},{0xa1,0xad,0xc2,0xbc,0x6a,0x2d,0x98,0x06,0x62,0x67,0x7e,0x7f,0xdf,0xf6,0x42,0x4d,0xe7,0xdb,0xa5,0x0f,0x57,0x95,0xca,0x90,0xfd,0xf3,0xe9,0x6e,0x25,0x6f,0x32,0x85,0xca,0xc7,0x1d,0x33,0x60,0x48,0x2e,0x99,0x3d,0x02,0x94,0xba,0x4e,0xc7,0x44,0x0c,0x61,0xaf,0xfd,0xf3,0x5f,0xe8,0x3e,0x6e,0x04,0x26,0x39,0x37,0xdb,0x93,0xf1,0x05,},20,"\x8b\xa6\xa4\xc9\xa1\x5a\x24\x4a\x9c\x26\xbb\x2a\x59\xb1\x02\x6f\x21\x34\x8b\x49"}, + {{0x0e,0x76,0x5d,0x72,0x0e,0x70,0x5f,0x93,0x66,0xc1,0xab,0x8c,0x3f,0xa8,0x4c,0x9a,0x44,0x37,0x0c,0x06,0x96,0x9f,0x80,0x32,0x96,0x88,0x4b,0x28,0x46,0xa6,0x52,0xa4,},{0x7f,0xae,0x45,0xdd,0x0a,0x05,0x97,0x10,0x26,0xd4,0x10,0xbc,0x49,0x7a,0xf5,0xbe,0x7d,0x08,0x27,0xa8,0x2a,0x14,0x5c,0x20,0x3f,0x62,0x5d,0xfc,0xb8,0xb0,0x3b,0xa8,},{0xbb,0x61,0xcf,0x84,0xde,0x61,0x86,0x22,0x07,0xc6,0xa4,0x55,0x25,0x8b,0xc4,0xdb,0x4e,0x15,0xee,0xa0,0x31,0x7f,0xf8,0x87,0x18,0xb8,0x82,0xa0,0x6b,0x5c,0xf6,0xec,0x6f,0xd2,0x0c,0x5a,0x26,0x9e,0x5d,0x5c,0x80,0x5b,0xaf,0xbc,0xc5,0x79,0xe2,0x59,0x0a,0xf4,0x14,0xc7,0xc2,0x27,0x27,0x3c,0x10,0x2a,0x10,0x07,0x0c,0xdf,0xe8,0x0f,},21,"\x1d\x56\x6a\x62\x32\xbb\xaa\xb3\xe6\xd8\x80\x4b\xb5\x18\xa4\x98\xed\x0f\x90\x49\x86"}, + {{0xdb,0x36,0xe3,0x26,0xd6,0x76,0xc2,0xd1,0x9c,0xc8,0xfe,0x0c,0x14,0xb7,0x09,0x20,0x2e,0xcf,0xc7,0x61,0xd2,0x70,0x89,0xeb,0x6e,0xa4,0xb1,0xbb,0x02,0x1e,0xcf,0xa7,},{0x48,0x35,0x9b,0x85,0x0d,0x23,0xf0,0x71,0x5d,0x94,0xbb,0x8b,0xb7,0x5e,0x7e,0x14,0x32,0x2e,0xaf,0x14,0xf0,0x6f,0x28,0xa8,0x05,0x40,0x3f,0xbd,0xa0,0x02,0xfc,0x85,},{0xb6,0xdc,0xd0,0x99,0x89,0xdf,0xba,0xc5,0x43,0x22,0xa3,0xce,0x87,0x87,0x6e,0x1d,0x62,0x13,0x4d,0xa9,0x98,0xc7,0x9d,0x24,0xb5,0x0b,0xd7,0xa6,0xa7,0x97,0xd8,0x6a,0x0e,0x14,0xdc,0x9d,0x74,0x91,0xd6,0xc1,0x4a,0x67,0x3c,0x65,0x2c,0xfb,0xec,0x9f,0x96,0x2a,0x38,0xc9,0x45,0xda,0x3b,0x2f,0x08,0x79,0xd0,0xb6,0x8a,0x92,0x13,0x00,},22,"\x1b\x0a\xfb\x0a\xc4\xba\x9a\xb7\xb7\x17\x2c\xdd\xc9\xeb\x42\xbb\xa1\xa6\x4b\xce\x47\xd4"}, + {{0xc8,0x99,0x55,0xe0,0xf7,0x74,0x1d,0x90,0x5d,0xf0,0x73,0x0b,0x3d,0xc2,0xb0,0xce,0x1a,0x13,0x13,0x4e,0x44,0xfe,0xf3,0xd4,0x0d,0x60,0xc0,0x20,0xef,0x19,0xdf,0x77,},{0xfd,0xb3,0x06,0x73,0x40,0x2f,0xaf,0x1c,0x80,0x33,0x71,0x4f,0x35,0x17,0xe4,0x7c,0xc0,0xf9,0x1f,0xe7,0x0c,0xf3,0x83,0x6d,0x6c,0x23,0x63,0x6e,0x3f,0xd2,0x28,0x7c,},{0x7e,0xf6,0x6e,0x5e,0x86,0xf2,0x36,0x08,0x48,0xe0,0x01,0x4e,0x94,0x88,0x0a,0xe2,0x92,0x0a,0xd8,0xa3,0x18,0x5a,0x46,0xb3,0x5d,0x1e,0x07,0xde,0xa8,0xfa,0x8a,0xe4,0xf6,0xb8,0x43,0xba,0x17,0x4d,0x99,0xfa,0x79,0x86,0x65,0x4a,0x08,0x91,0xc1,0x2a,0x79,0x44,0x55,0x66,0x93,0x75,0xbf,0x92,0xaf,0x4c,0xc2,0x77,0x0b,0x57,0x9e,0x0c,},23,"\x50\x7c\x94\xc8\x82\x0d\x2a\x57\x93\xcb\xf3\x44\x2b\x3d\x71\x93\x6f\x35\xfe\x3a\xfe\xf3\x16"}, + {{0x4e,0x62,0x62,0x7f,0xc2,0x21,0x14,0x24,0x78,0xae,0xe7,0xf0,0x07,0x81,0xf8,0x17,0xf6,0x62,0xe3,0xb7,0x5d,0xb2,0x9b,0xb1,0x4a,0xb4,0x7c,0xf8,0xe8,0x41,0x04,0xd6,},{0xb1,0xd3,0x98,0x01,0x89,0x20,0x27,0xd5,0x8a,0x8c,0x64,0x33,0x51,0x63,0x19,0x58,0x93,0xbf,0xc1,0xb6,0x1d,0xbe,0xca,0x32,0x60,0x49,0x7e,0x1f,0x30,0x37,0x11,0x07,},{0x83,0x6a,0xfa,0x76,0x4d,0x9c,0x48,0xaa,0x47,0x70,0xa4,0x38,0x8b,0x65,0x4e,0x97,0xb3,0xc1,0x6f,0x08,0x29,0x67,0xfe,0xbc,0xa2,0x7f,0x2f,0xc4,0x7d,0xdf,0xd9,0x24,0x4b,0x03,0xcf,0xc7,0x29,0x69,0x8a,0xcf,0x51,0x09,0x70,0x43,0x46,0xb6,0x0b,0x23,0x0f,0x25,0x54,0x30,0x08,0x9d,0xdc,0x56,0x91,0x23,0x99,0xd1,0x12,0x2d,0xe7,0x0a,},24,"\xd3\xd6\x15\xa8\x47\x2d\x99\x62\xbb\x70\xc5\xb5\x46\x6a\x3d\x98\x3a\x48\x11\x04\x6e\x2a\x0e\xf5"}, + {{0x6b,0x83,0xd7,0xda,0x89,0x08,0xc3,0xe7,0x20,0x5b,0x39,0x86,0x4b,0x56,0xe5,0xf3,0xe1,0x71,0x96,0xa3,0xfc,0x9c,0x2f,0x58,0x05,0xaa,0xd0,0xf5,0x55,0x4c,0x14,0x2d,},{0xd0,0xc8,0x46,0xf9,0x7f,0xe2,0x85,0x85,0xc0,0xee,0x15,0x90,0x15,0xd6,0x4c,0x56,0x31,0x1c,0x88,0x6e,0xdd,0xcc,0x18,0x5d,0x29,0x6d,0xbb,0x16,0x5d,0x26,0x25,0xd6,},{0x16,0xe4,0x62,0xa2,0x9a,0x6d,0xd4,0x98,0x68,0x5a,0x37,0x18,0xb3,0xee,0xd0,0x0c,0xc1,0x59,0x86,0x01,0xee,0x47,0x82,0x04,0x86,0x03,0x2d,0x6b,0x9a,0xcc,0x9b,0xf8,0x9f,0x57,0x68,0x4e,0x08,0xd8,0xc0,0xf0,0x55,0x89,0xcd,0xa2,0x88,0x2a,0x05,0xdc,0x4c,0x63,0xf9,0xd0,0x43,0x1d,0x65,0x52,0x71,0x08,0x12,0x43,0x30,0x03,0xbc,0x08,},25,"\x6a\xda\x80\xb6\xfa\x84\xf7\x03\x49\x20\x78\x9e\x85\x36\xb8\x2d\x5e\x46\x78\x05\x9a\xed\x27\xf7\x1c"}, + {{0x19,0xa9,0x1f,0xe2,0x3a,0x4e,0x9e,0x33,0xec,0xc4,0x74,0x87,0x8f,0x57,0xc6,0x4c,0xf1,0x54,0xb3,0x94,0x20,0x34,0x87,0xa7,0x03,0x5e,0x1a,0xd9,0xcd,0x69,0x7b,0x0d,},{0x2b,0xf3,0x2b,0xa1,0x42,0xba,0x46,0x22,0xd8,0xf3,0xe2,0x9e,0xcd,0x85,0xee,0xa0,0x7b,0x9c,0x47,0xbe,0x9d,0x64,0x41,0x2c,0x9b,0x51,0x0b,0x27,0xdd,0x21,0x8b,0x23,},{0x88,0x1f,0x5b,0x8c,0x5a,0x03,0x0d,0xf0,0xf7,0x5b,0x66,0x34,0xb0,0x70,0xdd,0x27,0xbd,0x1e,0xe3,0xc0,0x87,0x38,0xae,0x34,0x93,0x38,0xb3,0xee,0x64,0x69,0xbb,0xf9,0x76,0x0b,0x13,0x57,0x8a,0x23,0x7d,0x51,0x82,0x53,0x5e,0xde,0x12,0x12,0x83,0x02,0x7a,0x90,0xb5,0xf8,0x65,0xd6,0x3a,0x65,0x37,0xdc,0xa0,0x7b,0x44,0x04,0x9a,0x0f,},26,"\x82\xcb\x53\xc4\xd5\xa0\x13\xba\xe5\x07\x07\x59\xec\x06\xc3\xc6\x95\x5a\xb7\xa4\x05\x09\x58\xec\x32\x8c"}, + {{0x1d,0x5b,0x8c,0xb6,0x21,0x5c,0x18,0x14,0x16,0x66,0xba,0xee,0xfc,0xf5,0xd6,0x9d,0xad,0x5b,0xea,0x9a,0x34,0x93,0xdd,0xda,0xa3,0x57,0xa4,0x39,0x7a,0x13,0xd4,0xde,},{0x94,0xd2,0x3d,0x97,0x7c,0x33,0xe4,0x9e,0x5e,0x49,0x92,0xc6,0x8f,0x25,0xec,0x99,0xa2,0x7c,0x41,0xce,0x6b,0x91,0xf2,0xbf,0xa0,0xcd,0x82,0x92,0xfe,0x96,0x28,0x35,},{0x3a,0xcd,0x39,0xbe,0xc8,0xc3,0xcd,0x2b,0x44,0x29,0x97,0x22,0xb5,0x85,0x0a,0x04,0x00,0xc1,0x44,0x35,0x90,0xfd,0x48,0x61,0xd5,0x9a,0xae,0x74,0x96,0xac,0xb3,0xdf,0x73,0xfc,0x3f,0xdf,0x79,0x69,0xae,0x5f,0x50,0xba,0x47,0xdd,0xdc,0x43,0x52,0x46,0xe5,0xfd,0x37,0x6f,0x6b,0x89,0x1c,0xd4,0xc2,0xca,0xf5,0xd6,0x14,0xb6,0x17,0x0c,},27,"\xa9\xa8\xcb\xb0\xad\x58\x51\x24\xe5\x22\xab\xbf\xb4\x05\x33\xbd\xd6\xf4\x93\x47\xb5\x5b\x18\xe8\x55\x8c\xb0"}, + {{0x6a,0x91,0xb3,0x22,0x7c,0x47,0x22,0x99,0x08,0x9b,0xdc,0xe9,0x35,0x6e,0x72,0x6a,0x40,0xef,0xd8,0x40,0xf1,0x10,0x02,0x70,0x8b,0x7e,0xe5,0x5b,0x64,0x10,0x5a,0xc2,},{0x9d,0x08,0x4a,0xa8,0xb9,0x7a,0x6b,0x9b,0xaf,0xa4,0x96,0xdb,0xc6,0xf7,0x6f,0x33,0x06,0xa1,0x16,0xc9,0xd9,0x17,0xe6,0x81,0x52,0x0a,0x0f,0x91,0x43,0x69,0x42,0x7e,},{0xf5,0x87,0x54,0x23,0x78,0x1b,0x66,0x21,0x6c,0xb5,0xe8,0x99,0x8d,0xe5,0xd9,0xff,0xc2,0x9d,0x1d,0x67,0x10,0x70,0x54,0xac,0xe3,0x37,0x45,0x03,0xa9,0xc3,0xef,0x81,0x15,0x77,0xf2,0x69,0xde,0x81,0x29,0x67,0x44,0xbd,0x70,0x6f,0x1a,0xc4,0x78,0xca,0xf0,0x9b,0x54,0xcd,0xf8,0x71,0xb3,0xf8,0x02,0xbd,0x57,0xf9,0xa6,0xcb,0x91,0x01,},28,"\x5c\xb6\xf9\xaa\x59\xb8\x0e\xca\x14\xf6\xa6\x8f\xb4\x0c\xf0\x7b\x79\x4e\x75\x17\x1f\xba\x96\x26\x2c\x1c\x6a\xdc"}, + {{0x93,0xea,0xa8,0x54,0xd7,0x91,0xf0,0x53,0x72,0xce,0x72,0xb9,0x4f,0xc6,0x50,0x3b,0x2f,0xf8,0xae,0x68,0x19,0xe6,0xa2,0x1a,0xfe,0x82,0x5e,0x27,0xad,0xa9,0xe4,0xfb,},{0x16,0xce,0xe8,0xa3,0xf2,0x63,0x18,0x34,0xc8,0x8b,0x67,0x08,0x97,0xff,0x0b,0x08,0xce,0x90,0xcc,0x14,0x7b,0x45,0x93,0xb3,0xf1,0xf4,0x03,0x72,0x7f,0x7e,0x7a,0xd5,},{0xd8,0x34,0x19,0x7c,0x1a,0x30,0x80,0x61,0x4e,0x0a,0x5f,0xa0,0xaa,0xaa,0x80,0x88,0x24,0xf2,0x1c,0x38,0xd6,0x92,0xe6,0xff,0xbd,0x20,0x0f,0x7d,0xfb,0x3c,0x8f,0x44,0x40,0x2a,0x73,0x82,0x18,0x0b,0x98,0xad,0x0a,0xfc,0x8e,0xec,0x1a,0x02,0xac,0xec,0xf3,0xcb,0x7f,0xde,0x62,0x7b,0x9f,0x18,0x11,0x1f,0x26,0x0a,0xb1,0xdb,0x9a,0x07,},29,"\x32\xfe\x27\x99\x41\x24\x20\x21\x53\xb5\xc7\x0d\x38\x13\xfd\xee\x9c\x2a\xa6\xe7\xdc\x74\x3d\x4d\x53\x5f\x18\x40\xa5"}, + {{0x94,0x1c,0xac,0x69,0xfb,0x7b,0x18,0x15,0xc5,0x7b,0xb9,0x87,0xc4,0xd6,0xc2,0xad,0x2c,0x35,0xd5,0xf9,0xa3,0x18,0x2a,0x79,0xd4,0xba,0x13,0xea,0xb2,0x53,0xa8,0xad,},{0x23,0xbe,0x32,0x3c,0x56,0x2d,0xfd,0x71,0xce,0x65,0xf5,0xbb,0xa5,0x6a,0x74,0xa3,0xa6,0xdf,0xc3,0x6b,0x57,0x3d,0x2f,0x94,0xf6,0x35,0xc7,0xf9,0xb4,0xfd,0x5a,0x5b,},{0x0f,0x8f,0xad,0x1e,0x6b,0xde,0x77,0x1b,0x4f,0x54,0x20,0xea,0xc7,0x5c,0x37,0x8b,0xae,0x6d,0xb5,0xac,0x66,0x50,0xcd,0x2b,0xc2,0x10,0xc1,0x82,0x3b,0x43,0x2b,0x48,0xe0,0x16,0xb1,0x05,0x95,0x45,0x8f,0xfa,0xb9,0x2f,0x7a,0x89,0x89,0xb2,0x93,0xce,0xb8,0xdf,0xed,0x6c,0x24,0x3a,0x20,0x38,0xfc,0x06,0x65,0x2a,0xaa,0xf1,0x6f,0x02,},30,"\xbb\x31\x72\x79\x57\x10\xfe\x00\x05\x4d\x3b\x5d\xfe\xf8\xa1\x16\x23\x58\x2d\xa6\x8b\xf8\xe4\x6d\x72\xd2\x7c\xec\xe2\xaa"}, + {{0x1a,0xcd,0xbb,0x79,0x3b,0x03,0x84,0x93,0x46,0x27,0x47,0x0d,0x79,0x5c,0x3d,0x1d,0xd4,0xd7,0x9c,0xea,0x59,0xef,0x98,0x3f,0x29,0x5b,0x9b,0x59,0x17,0x9c,0xbb,0x28,},{0x3f,0x60,0xc7,0x54,0x1a,0xfa,0x76,0xc0,0x19,0xcf,0x5a,0xa8,0x2d,0xcd,0xb0,0x88,0xed,0x9e,0x4e,0xd9,0x78,0x05,0x14,0xae,0xfb,0x37,0x9d,0xab,0xc8,0x44,0xf3,0x1a,},{0xbe,0x71,0xef,0x48,0x06,0xcb,0x04,0x1d,0x88,0x5e,0xff,0xd9,0xe6,0xb0,0xfb,0xb7,0x3d,0x65,0xd7,0xcd,0xec,0x47,0xa8,0x9c,0x8a,0x99,0x48,0x92,0xf4,0xe5,0x5a,0x56,0x8c,0x4c,0xc7,0x8d,0x61,0xf9,0x01,0xe8,0x0d,0xbb,0x62,0x8b,0x86,0xa2,0x3c,0xcd,0x59,0x4e,0x71,0x2b,0x57,0xfa,0x94,0xc2,0xd6,0x7e,0xc2,0x66,0x34,0x87,0x85,0x07,},31,"\x7c\xf3\x4f\x75\xc3\xda\xc9\xa8\x04\xd0\xfc\xd0\x9e\xba\x9b\x29\xc9\x48\x4e\x8a\x01\x8f\xa9\xe0\x73\x04\x2d\xf8\x8e\x3c\x56"}, + {{0x8e,0xd7,0xa7,0x97,0xb9,0xce,0xa8,0xa8,0x37,0x0d,0x41,0x91,0x36,0xbc,0xdf,0x68,0x3b,0x75,0x9d,0x2e,0x3c,0x69,0x47,0xf1,0x7e,0x13,0xe2,0x48,0x5a,0xa9,0xd4,0x20,},{0xb4,0x9f,0x3a,0x78,0xb1,0xc6,0xa7,0xfc,0xa8,0xf3,0x46,0x6f,0x33,0xbc,0x0e,0x92,0x9f,0x01,0xfb,0xa0,0x43,0x06,0xc2,0xa7,0x46,0x5f,0x46,0xc3,0x75,0x93,0x16,0xd9,},{0x04,0x26,0x6c,0x03,0x3b,0x91,0xc1,0x32,0x2c,0xeb,0x34,0x46,0xc9,0x01,0xff,0xcf,0x3c,0xc4,0x0c,0x40,0x34,0xe8,0x87,0xc9,0x59,0x7c,0xa1,0x89,0x3b,0xa7,0x33,0x0b,0xec,0xbb,0xd8,0xb4,0x81,0x42,0xef,0x35,0xc0,0x12,0xc6,0xba,0x51,0xa6,0x6d,0xf9,0x30,0x8c,0xb6,0x26,0x8a,0xd6,0xb1,0xe4,0xb0,0x3e,0x70,0x10,0x24,0x95,0x79,0x0b,},32,"\xa7\x50\xc2\x32\x93\x3d\xc1\x4b\x11\x84\xd8\x6d\x8b\x4c\xe7\x2e\x16\xd6\x97\x44\xba\x69\x81\x8b\x6a\xc3\x3b\x1d\x82\x3b\xb2\xc3"}, + {{0xf2,0xab,0x39,0x6f,0xe8,0x90,0x6e,0x3e,0x56,0x33,0xe9,0x9c,0xab,0xcd,0x5b,0x09,0xdf,0x08,0x59,0xb5,0x16,0x23,0x0b,0x1e,0x04,0x50,0xb5,0x80,0xb6,0x5f,0x61,0x6c,},{0x8e,0xa0,0x74,0x24,0x51,0x59,0xa1,0x16,0xaa,0x71,0x22,0xa2,0x5e,0xc1,0x6b,0x89,0x1d,0x62,0x5a,0x68,0xf3,0x36,0x60,0x42,0x39,0x08,0xf6,0xbd,0xc4,0x4f,0x8c,0x1b,},{0xa0,0x6a,0x23,0xd9,0x82,0xd8,0x1a,0xb8,0x83,0xaa,0xe2,0x30,0xad,0xbc,0x36,0x8a,0x6a,0x99,0x77,0xf0,0x03,0xce,0xbb,0x00,0xd4,0xc2,0xe4,0x01,0x84,0x90,0x19,0x1a,0x84,0xd3,0xa2,0x82,0xfd,0xbf,0xb2,0xfc,0x88,0x04,0x6e,0x62,0xde,0x43,0xe1,0x5f,0xb5,0x75,0x33,0x6b,0x3c,0x8b,0x77,0xd1,0x9c,0xe6,0xa0,0x09,0xce,0x51,0xf5,0x0c,},33,"\x5a\x44\xe3\x4b\x74\x6c\x5f\xd1\x89\x8d\x55\x2a\xb3\x54\xd2\x8f\xb4\x71\x38\x56\xd7\x69\x7d\xd6\x3e\xb9\xbd\x6b\x99\xc2\x80\xe1\x87"}, + {{0x55,0x0a,0x41,0xc0,0x13,0xf7,0x9b,0xab,0x8f,0x06,0xe4,0x3a,0xd1,0x83,0x6d,0x51,0x31,0x27,0x36,0xa9,0x71,0x38,0x06,0xfa,0xfe,0x66,0x45,0x21,0x9e,0xaa,0x1f,0x9d,},{0xaf,0x6b,0x71,0x45,0x47,0x4d,0xc9,0x95,0x4b,0x9a,0xf9,0x3a,0x9c,0xdb,0x34,0x44,0x9d,0x5b,0x7c,0x65,0x1c,0x82,0x4d,0x24,0xe2,0x30,0xb9,0x00,0x33,0xce,0x59,0xc0,},{0x16,0xdc,0x1e,0x2b,0x9f,0xa9,0x09,0xee,0xfd,0xc2,0x77,0xba,0x16,0xeb,0xe2,0x07,0xb8,0xda,0x5e,0x91,0x14,0x3c,0xde,0x78,0xc5,0x04,0x7a,0x89,0xf6,0x81,0xc3,0x3c,0x4e,0x4e,0x34,0x28,0xd5,0xc9,0x28,0x09,0x59,0x03,0xa8,0x11,0xec,0x00,0x2d,0x52,0xa3,0x9e,0xd7,0xf8,0xb3,0xfe,0x19,0x27,0x20,0x0c,0x6d,0xd0,0xb9,0xab,0x3e,0x04,},34,"\x8b\xc4\x18\x5e\x50\xe5\x7d\x5f\x87\xf4\x75\x15\xfe\x2b\x18\x37\xd5\x85\xf0\xaa\xe9\xe1\xca\x38\x3b\x3e\xc9\x08\x88\x4b\xb9\x00\xff\x27"}, + {{0x19,0xac,0x3e,0x27,0x24,0x38,0xc7,0x2d,0xdf,0x7b,0x88,0x19,0x64,0x86,0x7c,0xb3,0xb3,0x1f,0xf4,0xc7,0x93,0xbb,0x7e,0xa1,0x54,0x61,0x3c,0x1d,0xb0,0x68,0xcb,0x7e,},{0xf8,0x5b,0x80,0xe0,0x50,0xa1,0xb9,0x62,0x0d,0xb1,0x38,0xbf,0xc9,0xe1,0x00,0x32,0x7e,0x25,0xc2,0x57,0xc5,0x92,0x17,0xb6,0x01,0xf1,0xf6,0xac,0x9a,0x41,0x3d,0x3f,},{0xea,0x85,0x5d,0x78,0x1c,0xbe,0xa4,0x68,0x2e,0x35,0x01,0x73,0xcb,0x89,0xe8,0x61,0x9c,0xcf,0xdd,0xb9,0x7c,0xdc,0xe1,0x6f,0x9a,0x2f,0x6f,0x68,0x92,0xf4,0x6d,0xbe,0x68,0xe0,0x4b,0x12,0xb8,0xd8,0x86,0x89,0xa7,0xa3,0x16,0x70,0xcd,0xff,0x40,0x9a,0xf9,0x8a,0x93,0xb4,0x9a,0x34,0x53,0x7b,0x6a,0xa0,0x09,0xd2,0xeb,0x8b,0x47,0x01,},35,"\x95\x87\x2d\x5f\x78\x9f\x95\x48\x4e\x30\xcb\xb0\xe1\x14\x02\x89\x53\xb1\x6f\x5c\x6a\x8d\x9f\x65\xc0\x03\xa8\x35\x43\xbe\xaa\x46\xb3\x86\x45"}, + {{0xca,0x26,0x7d,0xe9,0x6c,0x93,0xc2,0x38,0xfa,0xfb,0x12,0x79,0x81,0x20,0x59,0xab,0x93,0xac,0x03,0x05,0x96,0x57,0xfd,0x99,0x4f,0x8f,0xa5,0xa0,0x92,0x39,0xc8,0x21,},{0x01,0x73,0x70,0xc8,0x79,0x09,0x0a,0x81,0xc7,0xf2,0x72,0xc2,0xfc,0x80,0xe3,0xaa,0xc2,0xbc,0x60,0x3f,0xcb,0x37,0x9a,0xfc,0x98,0x69,0x11,0x60,0xab,0x74,0x5b,0x26,},{0xac,0x95,0x7f,0x82,0x33,0x5a,0xa7,0x14,0x1e,0x96,0xb5,0x9d,0x63,0xe3,0xcc,0xee,0x95,0xc3,0xa2,0xc4,0x7d,0x02,0x65,0x40,0xc2,0xaf,0x42,0xdc,0x95,0x33,0xd5,0xfd,0x81,0x82,0x7d,0x16,0x79,0xad,0x18,0x7a,0xea,0xf3,0x78,0x34,0x91,0x5e,0x75,0xb1,0x47,0xa9,0x28,0x68,0x06,0xc8,0x01,0x75,0x16,0xba,0x43,0xdd,0x05,0x1a,0x5e,0x0c,},36,"\xe0\x5f\x71\xe4\xe4\x9a\x72\xec\x55\x0c\x44\xa3\xb8\x5a\xca\x8f\x20\xff\x26\xc3\xee\x94\xa8\x0f\x1b\x43\x1c\x7d\x15\x4e\xc9\x60\x3e\xe0\x25\x31"}, + {{0x3d,0xff,0x5e,0x89,0x94,0x75,0xe7,0xe9,0x1d,0xd2,0x61,0x32,0x2f,0xab,0x09,0x98,0x0c,0x52,0x97,0x0d,0xe1,0xda,0x6e,0x2e,0x20,0x16,0x60,0xcc,0x4f,0xce,0x70,0x32,},{0xf3,0x01,0x62,0xba,0xc9,0x84,0x47,0xc4,0x04,0x2f,0xac,0x05,0xda,0x44,0x80,0x34,0x62,0x9b,0xe2,0xc6,0xa5,0x8d,0x30,0xdf,0xd5,0x78,0xba,0x9f,0xb5,0xe3,0x93,0x0b,},{0x5e,0xfe,0x7a,0x92,0xff,0x96,0x23,0x08,0x9b,0x3e,0x3b,0x78,0xf3,0x52,0x11,0x53,0x66,0xe2,0x6b,0xa3,0xfb,0x1a,0x41,0x62,0x09,0xbc,0x02,0x9e,0x9c,0xad,0xcc,0xd9,0xf4,0xaf,0xfa,0x33,0x35,0x55,0xa8,0xf3,0xa3,0x5a,0x9d,0x0f,0x7c,0x34,0xb2,0x92,0xca,0xe7,0x7e,0xc9,0x6f,0xa3,0xad,0xfc,0xaa,0xde,0xe2,0xd9,0xce,0xd8,0xf8,0x05,},37,"\x93\x8f\x0e\x77\x62\x1b\xf3\xea\x52\xc7\xc4\x91\x1c\x51\x57\xc2\xd8\xa2\xa8\x58\x09\x3e\xf1\x6a\xa9\xb1\x07\xe6\x9d\x98\x03\x7b\xa1\x39\xa3\xc3\x82"}, + {{0x9a,0x6b,0x84,0x78,0x64,0xe7,0x0c,0xfe,0x8b,0xa6,0xab,0x22,0xfa,0x0c,0xa3,0x08,0xc0,0xcc,0x8b,0xec,0x71,0x41,0xfb,0xca,0xa3,0xb8,0x1f,0x5d,0x1e,0x1c,0xfc,0xfc,},{0x34,0xad,0x0f,0xbd,0xb2,0x56,0x65,0x07,0xa8,0x1c,0x2b,0x1f,0x8a,0xa8,0xf5,0x3d,0xcc,0xaa,0x64,0xcc,0x87,0xad,0xa9,0x1b,0x90,0x3e,0x90,0x0d,0x07,0xee,0xe9,0x30,},{0x2a,0xb2,0x55,0x16,0x9c,0x48,0x9c,0x54,0xc7,0x32,0x23,0x2e,0x37,0xc8,0x73,0x49,0xd4,0x86,0xb1,0xeb,0xa2,0x05,0x09,0xdb,0xab,0xe7,0xfe,0xd3,0x29,0xef,0x08,0xfd,0x75,0xba,0x1c,0xd1,0x45,0xe6,0x7b,0x2e,0xa2,0x6c,0xb5,0xcc,0x51,0xca,0xb3,0x43,0xee,0xb0,0x85,0xfe,0x1f,0xd7,0xb0,0xec,0x4c,0x6a,0xfc,0xd9,0xb9,0x79,0xf9,0x05,},38,"\x83\x83\x67\x47\x11\x83\xc7\x1f\x7e\x71\x77\x24\xf8\x9d\x40\x1c\x3a\xd9\x86\x3f\xd9\xcc\x7a\xa3\xcf\x33\xd3\xc5\x29\x86\x0c\xb5\x81\xf3\x09\x3d\x87\xda"}, + {{0x57,0x5b,0xe0,0x7a,0xfc,0xa5,0xd0,0x63,0xc2,0x38,0xcd,0x9b,0x80,0x28,0x77,0x2c,0xc4,0x9c,0xda,0x34,0x47,0x14,0x32,0xa2,0xe1,0x66,0xe0,0x96,0xe2,0x21,0x9e,0xfc,},{0x94,0xe5,0xeb,0x4d,0x50,0x24,0xf4,0x9d,0x7e,0xbf,0x79,0x81,0x7c,0x8d,0xe1,0x14,0x97,0xdc,0x2b,0x55,0x62,0x2a,0x51,0xae,0x12,0x3f,0xfc,0x74,0x9d,0xbb,0x16,0xe0,},{0x58,0x27,0x1d,0x44,0x23,0x6f,0x3b,0x98,0xc5,0x8f,0xd7,0xae,0x0d,0x2f,0x49,0xef,0x2b,0x6e,0x3a,0xff,0xdb,0x22,0x5a,0xa3,0xba,0x55,0x5f,0x0e,0x11,0xcc,0x53,0xc2,0x3a,0xd1,0x9b,0xaf,0x24,0x34,0x65,0x90,0xd0,0x5d,0x7d,0x53,0x90,0x58,0x20,0x82,0xcf,0x94,0xd3,0x9c,0xad,0x65,0x30,0xab,0x93,0xd1,0x3e,0xfb,0x39,0x27,0x95,0x06,},39,"\x33\xe5\x91\x8b\x66\xd3\x3d\x55\xfe\x71\x7c\xa3\x43\x83\xea\xe7\x8f\x0a\xf8\x28\x89\xca\xf6\x69\x6e\x1a\xc9\xd9\x5d\x1f\xfb\x32\xcb\xa7\x55\xf9\xe3\x50\x3e"}, + {{0x15,0xff,0xb4,0x55,0x14,0xd4,0x34,0x44,0xd6,0x1f,0xcb,0x10,0x5e,0x30,0xe1,0x35,0xfd,0x26,0x85,0x23,0xdd,0xa2,0x0b,0x82,0x75,0x8b,0x17,0x94,0x23,0x11,0x04,0x41,},{0x17,0x72,0xc5,0xab,0xc2,0xd2,0x3f,0xd2,0xf9,0xd1,0xc3,0x25,0x7b,0xe7,0xbc,0x3c,0x1c,0xd7,0x9c,0xee,0x40,0x84,0x4b,0x74,0x9b,0x3a,0x77,0x43,0xd2,0xf9,0x64,0xb8,},{0x68,0x28,0xcd,0x76,0x24,0xe7,0x93,0xb8,0xa4,0xce,0xb9,0x6d,0x3c,0x2a,0x97,0x5b,0xf7,0x73,0xe5,0xff,0x66,0x45,0xf3,0x53,0x61,0x40,0x58,0x62,0x1e,0x58,0x83,0x52,0x89,0xe7,0xf3,0x1f,0x42,0xdf,0xe6,0xaf,0x6d,0x73,0x6f,0x26,0x44,0x51,0x1e,0x32,0x0c,0x0f,0xa6,0x98,0x58,0x2a,0x79,0x77,0x8d,0x18,0x73,0x0e,0xd3,0xe8,0xcb,0x08,},40,"\xda\x9c\x55\x59\xd0\xea\x51\xd2\x55\xb6\xbd\x9d\x76\x38\xb8\x76\x47\x2f\x94\x2b\x33\x0f\xc0\xe2\xb3\x0a\xea\x68\xd7\x73\x68\xfc\xe4\x94\x82\x72\x99\x1d\x25\x7e"}, + {{0xfe,0x05,0x68,0x64,0x29,0x43,0xb2,0xe1,0xaf,0xbf,0xd1,0xf1,0x0f,0xe8,0xdf,0x87,0xa4,0x23,0x6b,0xea,0x40,0xdc,0xe7,0x42,0x07,0x2c,0xb2,0x18,0x86,0xee,0xc1,0xfa,},{0x29,0x9e,0xbd,0x1f,0x13,0x17,0x7d,0xbd,0xb6,0x6a,0x91,0x2b,0xbf,0x71,0x20,0x38,0xfd,0xf7,0x3b,0x06,0xc3,0xac,0x02,0x0c,0x7b,0x19,0x12,0x67,0x55,0xd4,0x7f,0x61,},{0xd5,0x9e,0x6d,0xfc,0xc6,0xd7,0xe3,0xe2,0xc5,0x8d,0xec,0x81,0xe9,0x85,0xd2,0x45,0xe6,0x81,0xac,0xf6,0x59,0x4a,0x23,0xc5,0x92,0x14,0xf7,0xbe,0xd8,0x01,0x5d,0x81,0x3c,0x76,0x82,0xb6,0x0b,0x35,0x83,0x44,0x03,0x11,0xe7,0x2a,0x86,0x65,0xba,0x2c,0x96,0xde,0xc2,0x3c,0xe8,0x26,0xe1,0x60,0x12,0x7e,0x18,0x13,0x2b,0x03,0x04,0x04,},41,"\xc5\x9d\x08\x62\xec\x1c\x97\x46\xab\xcc\x3c\xf8\x3c\x9e\xeb\xa2\xc7\x08\x2a\x03\x6a\x8c\xb5\x7c\xe4\x87\xe7\x63\x49\x27\x96\xd4\x7e\x6e\x06\x3a\x0c\x1f\xec\xcc\x2d"}, + {{0x5e,0xcb,0x16,0xc2,0xdf,0x27,0xc8,0xcf,0x58,0xe4,0x36,0xa9,0xd3,0xaf,0xfb,0xd5,0x8e,0x95,0x38,0xa9,0x26,0x59,0xa0,0xf9,0x7c,0x4c,0x4f,0x99,0x46,0x35,0xa8,0xca,},{0xda,0x76,0x8b,0x20,0xc4,0x37,0xdd,0x3a,0xa5,0xf8,0x4b,0xb6,0xa0,0x77,0xff,0xa3,0x4a,0xb6,0x85,0x01,0xc5,0x35,0x2b,0x5c,0xc3,0xfd,0xce,0x7f,0xe6,0xc2,0x39,0x8d,},{0x1c,0x72,0x3a,0x20,0xc6,0x77,0x24,0x26,0xa6,0x70,0xe4,0xd5,0xc4,0xa9,0x7c,0x6e,0xbe,0x91,0x47,0xf7,0x1b,0xb0,0xa4,0x15,0x63,0x1e,0x44,0x40,0x6e,0x29,0x03,0x22,0xe4,0xca,0x97,0x7d,0x34,0x8f,0xe7,0x85,0x6a,0x8e,0xdc,0x23,0x5d,0x0f,0xe9,0x5f,0x7e,0xd9,0x1a,0xef,0xdd,0xf2,0x8a,0x77,0xe2,0xc7,0xdb,0xfd,0x8f,0x55,0x2f,0x0a,},42,"\x56\xf1\x32\x9d\x9a\x6b\xe2\x5a\x61\x59\xc7\x2f\x12\x68\x8d\xc8\x31\x4e\x85\xdd\x9e\x7e\x4d\xc0\x5b\xbe\xcb\x77\x29\xe0\x23\xc8\x6f\x8e\x09\x37\x35\x3f\x27\xc7\xed\xe9"}, + {{0xd5,0x99,0xd6,0x37,0xb3,0xc3,0x0a,0x82,0xa9,0x98,0x4e,0x2f,0x75,0x84,0x97,0xd1,0x44,0xde,0x6f,0x06,0xb9,0xfb,0xa0,0x4d,0xd4,0x0f,0xd9,0x49,0x03,0x9d,0x7c,0x84,},{0x67,0x91,0xd8,0xce,0x50,0xa4,0x46,0x89,0xfc,0x17,0x87,0x27,0xc5,0xc3,0xa1,0xc9,0x59,0xfb,0xee,0xd7,0x4e,0xf7,0xd8,0xe7,0xbd,0x3c,0x1a,0xb4,0xda,0x31,0xc5,0x1f,},{0xeb,0xf1,0x0d,0x9a,0xc7,0xc9,0x61,0x08,0x14,0x0e,0x7d,0xef,0x6f,0xe9,0x53,0x3d,0x72,0x76,0x46,0xff,0x5b,0x3a,0xf2,0x73,0xc1,0xdf,0x95,0x76,0x2a,0x66,0xf3,0x2b,0x65,0xa0,0x96,0x34,0xd0,0x13,0xf5,0x4b,0x5d,0xd6,0x01,0x1f,0x91,0xbc,0x33,0x6c,0xa8,0xb3,0x55,0xce,0x33,0xf8,0xcf,0xbe,0xc2,0x53,0x5a,0x4c,0x42,0x7f,0x82,0x05,},43,"\xa7\xc0\x4e\x8b\xa7\x5d\x0a\x03\xd8\xb1\x66\xad\x7a\x1d\x77\xe1\xb9\x1c\x7a\xaf\x7b\xef\xdd\x99\x31\x1f\xc3\xc5\x4a\x68\x4d\xdd\x97\x1d\x5b\x32\x11\xc3\xee\xaf\xf1\xe5\x4e"}, + {{0x30,0xab,0x82,0x32,0xfa,0x70,0x18,0xf0,0xce,0x6c,0x39,0xbd,0x8f,0x78,0x2f,0xe2,0xe1,0x59,0x75,0x8b,0xb0,0xf2,0xf4,0x38,0x6c,0x7f,0x28,0xcf,0xd2,0xc8,0x58,0x98,},{0xec,0xfb,0x6a,0x2b,0xd4,0x2f,0x31,0xb6,0x12,0x50,0xba,0x5d,0xe7,0xe4,0x6b,0x47,0x19,0xaf,0xdf,0xbc,0x66,0x0d,0xb7,0x1a,0x7b,0xd1,0xdf,0x7b,0x0a,0x3a,0xbe,0x37,},{0x9a,0xf8,0x85,0x34,0x4c,0xc7,0x23,0x94,0x98,0xf7,0x12,0xdf,0x80,0xbc,0x01,0xb8,0x06,0x38,0x29,0x1e,0xd4,0xa1,0xd2,0x8b,0xaa,0x55,0x45,0x01,0x7a,0x72,0xe2,0xf6,0x56,0x49,0xcc,0xf9,0x60,0x3d,0xa6,0xeb,0x5b,0xfa,0xb9,0xf5,0x54,0x3a,0x6c,0xa4,0xa7,0xaf,0x38,0x66,0x15,0x3c,0x76,0xbf,0x66,0xbf,0x95,0xde,0xf6,0x15,0xb0,0x0c,},44,"\x63\xb8\x0b\x79\x56\xac\xbe\xcf\x0c\x35\xe9\xab\x06\xb9\x14\xb0\xc7\x01\x4f\xe1\xa4\xbb\xc0\x21\x72\x40\xc1\xa3\x30\x95\xd7\x07\x95\x3e\xd7\x7b\x15\xd2\x11\xad\xaf\x9b\x97\xdc"}, + {{0x0d,0xdc,0xdc,0x87,0x2c,0x7b,0x74,0x8d,0x40,0xef,0xe9,0x6c,0x28,0x81,0xae,0x18,0x9d,0x87,0xf5,0x61,0x48,0xed,0x8a,0xf3,0xeb,0xbb,0xc8,0x03,0x24,0xe3,0x8b,0xdd,},{0x58,0x8d,0xda,0xdc,0xbc,0xed,0xf4,0x0d,0xf0,0xe9,0x69,0x7d,0x8b,0xb2,0x77,0xc7,0xbb,0x14,0x98,0xfa,0x1d,0x26,0xce,0x0a,0x83,0x5a,0x76,0x0b,0x92,0xca,0x7c,0x85,},{0xc1,0x79,0xc0,0x94,0x56,0xe2,0x35,0xfe,0x24,0x10,0x5a,0xfa,0x6e,0x8e,0xc0,0x46,0x37,0xf8,0xf9,0x43,0x81,0x7c,0xd0,0x98,0xba,0x95,0x38,0x7f,0x96,0x53,0xb2,0xad,0xd1,0x81,0xa3,0x14,0x47,0xd9,0x2d,0x1a,0x1d,0xdf,0x1c,0xeb,0x0d,0xb6,0x21,0x18,0xde,0x9d,0xff,0xb7,0xdc,0xd2,0x42,0x40,0x57,0xcb,0xdf,0xf5,0xd4,0x1d,0x04,0x03,},45,"\x65\x64\x1c\xd4\x02\xad\xd8\xbf\x3d\x1d\x67\xdb\xeb\x6d\x41\xde\xbf\xbe\xf6\x7e\x43\x17\xc3\x5b\x0a\x6d\x5b\xbb\xae\x0e\x03\x4d\xe7\xd6\x70\xba\x14\x13\xd0\x56\xf2\xd6\xf1\xde\x12"}, + {{0x89,0xf0,0xd6,0x82,0x99,0xba,0x0a,0x5a,0x83,0xf2,0x48,0xae,0x0c,0x16,0x9f,0x8e,0x38,0x49,0xa9,0xb4,0x7b,0xd4,0x54,0x98,0x84,0x30,0x5c,0x99,0x12,0xb4,0x66,0x03,},{0xab,0xa3,0xe7,0x95,0xaa,0xb2,0x01,0x2a,0xcc,0xea,0xdd,0x7b,0x3b,0xd9,0xda,0xee,0xed,0x6f,0xf5,0x25,0x8b,0xdc,0xd7,0xc9,0x36,0x99,0xc2,0xa3,0x83,0x6e,0x38,0x32,},{0x2c,0x69,0x1f,0xa8,0xd4,0x87,0xce,0x20,0xd5,0xd2,0xfa,0x41,0x55,0x91,0x16,0xe0,0xbb,0xf4,0x39,0x7c,0xf5,0x24,0x0e,0x15,0x25,0x56,0x18,0x35,0x41,0xd6,0x6c,0xf7,0x53,0x58,0x24,0x01,0xa4,0x38,0x8d,0x39,0x03,0x39,0xdb,0xef,0x4d,0x38,0x47,0x43,0xca,0xa3,0x46,0xf5,0x5f,0x8d,0xab,0xa6,0x8b,0xa7,0xb9,0x13,0x1a,0x8a,0x6e,0x0b,},46,"\x4f\x18\x46\xdd\x7a\xd5\x0e\x54\x5d\x4c\xfb\xff\xbb\x1d\xc2\xff\x14\x5d\xc1\x23\x75\x4d\x08\xaf\x4e\x44\xec\xc0\xbc\x8c\x91\x41\x13\x88\xbc\x76\x53\xe2\xd8\x93\xd1\xea\xc2\x10\x7d\x05"}, + {{0x0a,0x3c,0x18,0x44,0xe2,0xdb,0x07,0x0f,0xb2,0x4e,0x3c,0x95,0xcb,0x1c,0xc6,0x71,0x4e,0xf8,0x4e,0x2c,0xcd,0x2b,0x9d,0xd2,0xf1,0x46,0x0e,0xbf,0x7e,0xcf,0x13,0xb1,},{0x72,0xe4,0x09,0x93,0x7e,0x06,0x10,0xeb,0x5c,0x20,0xb3,0x26,0xdc,0x6e,0xa1,0xbb,0xbc,0x04,0x06,0x70,0x1c,0x5c,0xd6,0x7d,0x1f,0xbd,0xe0,0x91,0x92,0xb0,0x7c,0x01,},{0x87,0xf7,0xfd,0xf4,0x60,0x95,0x20,0x1e,0x87,0x7a,0x58,0x8f,0xe3,0xe5,0xaa,0xf4,0x76,0xbd,0x63,0x13,0x8d,0x8a,0x87,0x8b,0x89,0xd6,0xac,0x60,0x63,0x1b,0x34,0x58,0xb9,0xd4,0x1a,0x3c,0x61,0xa5,0x88,0xe1,0xdb,0x8d,0x29,0xa5,0x96,0x89,0x81,0xb0,0x18,0x77,0x6c,0x58,0x87,0x80,0x92,0x2f,0x5a,0xa7,0x32,0xba,0x63,0x79,0xdd,0x05,},47,"\x4c\x82\x74\xd0\xed\x1f\x74\xe2\xc8\x6c\x08\xd9\x55\xbd\xe5\x5b\x2d\x54\x32\x7e\x82\x06\x2a\x1f\x71\xf7\x0d\x53\x6f\xdc\x87\x22\xcd\xea\xd7\xd2\x2a\xae\xad\x2b\xfa\xa1\xad\x00\xb8\x29\x57"}, + {{0xc8,0xd7,0xa8,0x81,0x8b,0x98,0xdf,0xdb,0x20,0x83,0x9c,0x87,0x1c,0xb5,0xc4,0x8e,0x9e,0x94,0x70,0xca,0x3a,0xd3,0x5b,0xa2,0x61,0x3a,0x5d,0x31,0x99,0xc8,0xab,0x23,},{0x90,0xd2,0xef,0xbb,0xa4,0xd4,0x3e,0x6b,0x2b,0x99,0x2c,0xa1,0x60,0x83,0xdb,0xcf,0xa2,0xb3,0x22,0x38,0x39,0x07,0xb0,0xee,0x75,0xf3,0xe9,0x58,0x45,0xd3,0xc4,0x7f,},{0xfa,0x2e,0x99,0x44,0x21,0xae,0xf1,0xd5,0x85,0x66,0x74,0x81,0x3d,0x05,0xcb,0xd2,0xcf,0x84,0xef,0x5e,0xb4,0x24,0xaf,0x6e,0xcd,0x0d,0xc6,0xfd,0xbd,0xc2,0xfe,0x60,0x5f,0xe9,0x85,0x88,0x33,0x12,0xec,0xf3,0x4f,0x59,0xbf,0xb2,0xf1,0xc9,0x14,0x9e,0x5b,0x9c,0xc9,0xec,0xda,0x05,0xb2,0x73,0x11,0x30,0xf3,0xed,0x28,0xdd,0xae,0x0b,},48,"\x78\x3e\x33\xc3\xac\xbd\xbb\x36\xe8\x19\xf5\x44\xa7\x78\x1d\x83\xfc\x28\x3d\x33\x09\xf5\xd3\xd1\x2c\x8d\xcd\x6b\x0b\x3d\x0e\x89\xe3\x8c\xfd\x3b\x4d\x08\x85\x66\x1c\xa5\x47\xfb\x97\x64\xab\xff"}, + {{0xb4,0x82,0x70,0x36,0x12,0xd0,0xc5,0x86,0xf7,0x6c,0xfc,0xb2,0x1c,0xfd,0x21,0x03,0xc9,0x57,0x25,0x15,0x04,0xa8,0xc0,0xac,0x4c,0x86,0xc9,0xc6,0xf3,0xe4,0x29,0xff,},{0xfd,0x71,0x1d,0xc7,0xdd,0x3b,0x1d,0xfb,0x9d,0xf9,0x70,0x4b,0xe3,0xe6,0xb2,0x6f,0x58,0x7f,0xe7,0xdd,0x7b,0xa4,0x56,0xa9,0x1b,0xa4,0x3f,0xe5,0x1a,0xec,0x09,0xad,},{0x58,0x83,0x2b,0xde,0xb2,0x6f,0xea,0xfc,0x31,0xb4,0x62,0x77,0xcf,0x3f,0xb5,0xd7,0xa1,0x7d,0xfb,0x7c,0xcd,0x9b,0x1f,0x58,0xec,0xbe,0x6f,0xeb,0x97,0x96,0x66,0x82,0x8f,0x23,0x9b,0xa4,0xd7,0x52,0x19,0x26,0x0e,0xca,0xc0,0xac,0xf4,0x0f,0x0e,0x5e,0x25,0x90,0xf4,0xca,0xa1,0x6b,0xbb,0xcd,0x8a,0x15,0x5d,0x34,0x79,0x67,0xa6,0x07,},49,"\x29\xd7\x7a\xcf\xd9\x9c\x7a\x00\x70\xa8\x8f\xeb\x62\x47\xa2\xbc\xe9\x98\x4f\xe3\xe6\xfb\xf1\x9d\x40\x45\x04\x2a\x21\xab\x26\xcb\xd7\x71\xe1\x84\xa9\xa7\x5f\x31\x6b\x64\x8c\x69\x20\xdb\x92\xb8\x7b"}, + {{0x84,0xe5,0x0d,0xd9,0xa0,0xf1,0x97,0xe3,0x89,0x3c,0x38,0xdb,0xd9,0x1f,0xaf,0xc3,0x44,0xc1,0x77,0x6d,0x3a,0x40,0x0e,0x2f,0x0f,0x0e,0xe7,0xaa,0x82,0x9e,0xb8,0xa2,},{0x2c,0x50,0xf8,0x70,0xee,0x48,0xb3,0x6b,0x0a,0xc2,0xf8,0xa5,0xf3,0x36,0xfb,0x09,0x0b,0x11,0x30,0x50,0xdb,0xcc,0x25,0xe0,0x78,0x20,0x0a,0x6e,0x16,0x15,0x3e,0xea,},{0x69,0xe6,0xa4,0x49,0x1a,0x63,0x83,0x73,0x16,0xe8,0x6a,0x5f,0x4b,0xa7,0xcd,0x0d,0x73,0x1e,0xcc,0x58,0xf1,0xd0,0xa2,0x64,0xc6,0x7c,0x89,0xbe,0xfd,0xd8,0xd3,0x82,0x9d,0x8d,0xe1,0x3b,0x33,0xcc,0x0b,0xf5,0x13,0x93,0x17,0x15,0xc7,0x80,0x96,0x57,0xe2,0xbf,0xb9,0x60,0xe5,0xc7,0x64,0xc9,0x71,0xd7,0x33,0x74,0x60,0x93,0xe5,0x00,},50,"\xf3\x99\x2c\xde\x64\x93\xe6\x71\xf1\xe1\x29\xdd\xca\x80\x38\xb0\xab\xdb\x77\xbb\x90\x35\xf9\xf8\xbe\x54\xbd\x5d\x68\xc1\xae\xff\x72\x4f\xf4\x7d\x29\x34\x43\x91\xdc\x53\x61\x66\xb8\x67\x1c\xbb\xf1\x23"}, + {{0xb3,0x22,0xd4,0x65,0x77,0xa2,0xa9,0x91,0xa4,0xd1,0x69,0x82,0x87,0x83,0x2a,0x39,0xc4,0x87,0xef,0x77,0x6b,0x4b,0xff,0x03,0x7a,0x05,0xc7,0xf1,0x81,0x2b,0xde,0xec,},{0xeb,0x2b,0xca,0xdf,0xd3,0xee,0xc2,0x98,0x6b,0xaf,0xf3,0x2b,0x98,0xe7,0xc4,0xdb,0xf0,0x3f,0xf9,0x5d,0x8a,0xd5,0xff,0x9a,0xa9,0x50,0x6e,0x54,0x72,0xff,0x84,0x5f,},{0xc7,0xb5,0x51,0x37,0x31,0x7c,0xa2,0x1e,0x33,0x48,0x9f,0xf6,0xa9,0xbf,0xab,0x97,0xc8,0x55,0xdc,0x6f,0x85,0x68,0x4a,0x70,0xa9,0x12,0x5a,0x26,0x1b,0x56,0xd5,0xe6,0xf1,0x49,0xc5,0x77,0x4d,0x73,0x4f,0x2d,0x8d,0xeb,0xfc,0x77,0xb7,0x21,0x89,0x6a,0x82,0x67,0xc2,0x37,0x68,0xe9,0xba,0xdb,0x91,0x0e,0xef,0x83,0xec,0x25,0x88,0x02,},51,"\x19\xf1\xbf\x5d\xcf\x17\x50\xc6\x11\xf1\xc4\xa2\x86\x52\x00\x50\x4d\x82\x29\x8e\xdd\x72\x67\x1f\x62\xa7\xb1\x47\x1a\xc3\xd4\xa3\x0f\x7d\xe9\xe5\xda\x41\x08\xc5\x2a\x4c\xe7\x0a\x3e\x11\x4a\x52\xa3\xb3\xc5"}, + {{0x96,0x0c,0xab,0x50,0x34,0xb9,0x83,0x8d,0x09,0x8d,0x2d,0xcb,0xf4,0x36,0x4b,0xec,0x16,0xd3,0x88,0xf6,0x37,0x6d,0x73,0xa6,0x27,0x3b,0x70,0xf8,0x2b,0xbc,0x98,0xc0,},{0x5e,0x3c,0x19,0xf2,0x41,0x5a,0xcf,0x72,0x9f,0x82,0x9a,0x4e,0xbd,0x5c,0x40,0xe1,0xa6,0xbc,0x9f,0xbc,0xa9,0x57,0x03,0xa9,0x37,0x60,0x87,0xed,0x09,0x37,0xe5,0x1a,},{0x27,0xd4,0xc3,0xa1,0x81,0x1e,0xf9,0xd4,0x36,0x0b,0x3b,0xdd,0x13,0x3c,0x2c,0xcc,0x30,0xd0,0x2c,0x2f,0x24,0x82,0x15,0x77,0x6c,0xb0,0x7e,0xe4,0x17,0x7f,0x9b,0x13,0xfc,0x42,0xdd,0x70,0xa6,0xc2,0xfe,0xd8,0xf2,0x25,0xc7,0x66,0x3c,0x7f,0x18,0x2e,0x7e,0xe8,0xec,0xcf,0xf2,0x0d,0xc7,0xb0,0xe1,0xd5,0x83,0x4e,0xc5,0xb1,0xea,0x01,},52,"\xf8\xb2\x19\x62\x44\x7b\x0a\x8f\x2e\x42\x79\xde\x41\x1b\xea\x12\x8e\x0b\xe4\x4b\x69\x15\xe6\xcd\xa8\x83\x41\xa6\x8a\x0d\x81\x83\x57\xdb\x93\x8e\xac\x73\xe0\xaf\x6d\x31\x20\x6b\x39\x48\xf8\xc4\x8a\x44\x73\x08"}, + {{0xeb,0x77,0xb2,0x63,0x8f,0x23,0xee,0xbc,0x82,0xef,0xe4,0x5e,0xe9,0xe5,0xa0,0x32,0x66,0x37,0x40,0x1e,0x66,0x3e,0xd0,0x29,0x69,0x9b,0x21,0xe6,0x44,0x3f,0xb4,0x8e,},{0x9e,0xf2,0x76,0x08,0x96,0x1a,0xc7,0x11,0xde,0x71,0xa6,0xe2,0xd4,0xd4,0x66,0x3e,0xa3,0xec,0xd4,0x2f,0xb7,0xe4,0xe8,0x62,0x7c,0x39,0x62,0x2d,0xf4,0xaf,0x0b,0xbc,},{0x18,0xdc,0x56,0xd7,0xbd,0x9a,0xcd,0x4f,0x4d,0xaa,0x78,0x54,0x0b,0x4a,0xc8,0xff,0x7a,0xa9,0x81,0x5f,0x45,0xa0,0xbb,0xa3,0x70,0x73,0x1a,0x14,0xea,0xab,0xe9,0x6d,0xf8,0xb5,0xf3,0x7d,0xbf,0x8e,0xae,0x4c,0xb1,0x5a,0x64,0xb2,0x44,0x65,0x1e,0x59,0xd6,0xa3,0xd6,0x76,0x1d,0x9e,0x3c,0x50,0xf2,0xd0,0xcb,0xb0,0x9c,0x05,0xec,0x06,},53,"\x99\xe3\xd0\x09\x34\x00\x3e\xba\xfc\x3e\x9f\xdb\x68\x7b\x0f\x5f\xf9\xd5\x78\x2a\x4b\x1f\x56\xb9\x70\x00\x46\xc0\x77\x91\x56\x02\xc3\x13\x4e\x22\xfc\x90\xed\x7e\x69\x0f\xdd\xd4\x43\x3e\x20\x34\xdc\xb2\xdc\x99\xab"}, + {{0xb6,0x25,0xaa,0x89,0xd3,0xf7,0x30,0x87,0x15,0x42,0x7b,0x6c,0x39,0xbb,0xac,0x58,0xef,0xfd,0x3a,0x0f,0xb7,0x31,0x6f,0x7a,0x22,0xb9,0x9e,0xe5,0x92,0x2f,0x2d,0xc9,},{0x65,0xa9,0x9c,0x3e,0x16,0xfe,0xa8,0x94,0xec,0x33,0xc6,0xb2,0x0d,0x91,0x05,0xe2,0xa0,0x4e,0x27,0x64,0xa4,0x76,0x9d,0x9b,0xbd,0x4d,0x8b,0xac,0xfe,0xab,0x4a,0x2e,},{0x01,0xbb,0x90,0x1d,0x83,0xb8,0xb6,0x82,0xd3,0x61,0x4a,0xf4,0x6a,0x80,0x7b,0xa2,0x69,0x13,0x58,0xfe,0xb7,0x75,0x32,0x5d,0x34,0x23,0xf5,0x49,0xff,0x0a,0xa5,0x75,0x7e,0x4e,0x1a,0x74,0xe9,0xc7,0x0f,0x97,0x21,0xd8,0xf3,0x54,0xb3,0x19,0xd4,0xf4,0xa1,0xd9,0x14,0x45,0xc8,0x70,0xfd,0x0f,0xfb,0x94,0xfe,0xd6,0x46,0x64,0x73,0x0d,},54,"\xe0\x72\x41\xdb\xd3\xad\xbe\x61\x0b\xbe\x4d\x00\x5d\xd4\x67\x32\xa4\xc2\x50\x86\xec\xb8\xec\x29\xcd\x7b\xca\x11\x6e\x1b\xf9\xf5\x3b\xfb\xf3\xe1\x1f\xa4\x90\x18\xd3\x9f\xf1\x15\x4a\x06\x66\x8e\xf7\xdf\x5c\x67\x8e\x6a"}, + {{0xb1,0xc9,0xf8,0xbd,0x03,0xfe,0x82,0xe7,0x8f,0x5c,0x0f,0xb0,0x64,0x50,0xf2,0x7d,0xac,0xdf,0x71,0x64,0x34,0xdb,0x26,0x82,0x75,0xdf,0x3e,0x1d,0xc1,0x77,0xaf,0x42,},{0x7f,0xc8,0x8b,0x1f,0x7b,0x3f,0x11,0xc6,0x29,0xbe,0x67,0x1c,0x21,0x62,0x1f,0x5c,0x10,0x67,0x2f,0xaf,0xc8,0x49,0x2d,0xa8,0x85,0x74,0x20,0x59,0xee,0x67,0x74,0xcf,},{0x4b,0x22,0x99,0x51,0xef,0x26,0x2f,0x16,0x97,0x8f,0x79,0x14,0xbc,0x67,0x2e,0x72,0x26,0xc5,0xf8,0x37,0x9d,0x27,0x78,0xc5,0xa2,0xdc,0x0a,0x26,0x50,0x86,0x9f,0x7a,0xcf,0xbd,0x0b,0xcd,0x30,0xfd,0xb0,0x61,0x9b,0xb4,0x4f,0xc1,0xae,0x59,0x39,0xb8,0x7c,0xc3,0x18,0x13,0x30,0x09,0xc2,0x03,0x95,0xb6,0xc7,0xeb,0x98,0x10,0x77,0x01,},55,"\x33\x1d\xa7\xa9\xc1\xf8\x7b\x2a\xc9\x1e\xe3\xb8\x6d\x06\xc2\x91\x63\xc0\x5e\xd6\xf8\xd8\xa9\x72\x5b\x47\x1b\x7d\xb0\xd6\xac\xec\x7f\x0f\x70\x24\x87\x16\x3f\x5e\xda\x02\x0c\xa5\xb4\x93\xf3\x99\xe1\xc8\xd3\x08\xc3\xc0\xc2"}, + {{0x6d,0x8c,0xdb,0x2e,0x07,0x5f,0x3a,0x2f,0x86,0x13,0x72,0x14,0xcb,0x23,0x6c,0xeb,0x89,0xa6,0x72,0x8b,0xb4,0xa2,0x00,0x80,0x6b,0xf3,0x55,0x7f,0xb7,0x8f,0xac,0x69,},{0x57,0xa0,0x4c,0x7a,0x51,0x13,0xcd,0xdf,0xe4,0x9a,0x4c,0x12,0x46,0x91,0xd4,0x6c,0x1f,0x9c,0xdc,0x8f,0x34,0x3f,0x9d,0xcb,0x72,0xa1,0x33,0x0a,0xec,0xa7,0x1f,0xda,},{0xa6,0xcb,0xc9,0x47,0xf9,0xc8,0x7d,0x14,0x55,0xcf,0x1a,0x70,0x85,0x28,0xc0,0x90,0xf1,0x1e,0xce,0xe4,0x85,0x5d,0x1d,0xba,0xad,0xf4,0x74,0x54,0xa4,0xde,0x55,0xfa,0x4c,0xe8,0x4b,0x36,0xd7,0x3a,0x5b,0x5f,0x8f,0x59,0x29,0x8c,0xcf,0x21,0x99,0x2d,0xf4,0x92,0xef,0x34,0x16,0x3d,0x87,0x75,0x3b,0x7e,0x9d,0x32,0xf2,0xc3,0x66,0x0b,},56,"\x7f\x31\x8d\xbd\x12\x1c\x08\xbf\xdd\xfe\xff\x4f\x6a\xff\x4e\x45\x79\x32\x51\xf8\xab\xf6\x58\x40\x33\x58\x23\x89\x84\x36\x00\x54\xf2\xa8\x62\xc5\xbb\x83\xed\x89\x02\x5d\x20\x14\xa7\xa0\xce\xe5\x0d\xa3\xcb\x0e\x76\xbb\xb6\xbf"}, + {{0x47,0xad,0xc6,0xd6,0xbf,0x57,0x1e,0xe9,0x57,0x0c,0xa0,0xf7,0x5b,0x60,0x4a,0xc4,0x3e,0x30,0x3e,0x4a,0xb3,0x39,0xca,0x9b,0x53,0xca,0xcc,0x5b,0xe4,0x5b,0x2c,0xcb,},{0xa3,0xf5,0x27,0xa1,0xc1,0xf1,0x7d,0xfe,0xed,0x92,0x27,0x73,0x47,0xc9,0xf9,0x8a,0xb4,0x75,0xde,0x17,0x55,0xb0,0xab,0x54,0x6b,0x8a,0x15,0xd0,0x1b,0x9b,0xd0,0xbe,},{0x4e,0x8c,0x31,0x83,0x43,0xc3,0x06,0xad,0xbb,0xa6,0x0c,0x92,0xb7,0x5c,0xb0,0x56,0x9b,0x92,0x19,0xd8,0xa8,0x6e,0x5d,0x57,0x75,0x2e,0xd2,0x35,0xfc,0x10,0x9a,0x43,0xc2,0xcf,0x4e,0x94,0x2c,0xac,0xf2,0x97,0x27,0x9f,0xbb,0x28,0x67,0x53,0x47,0xe0,0x80,0x27,0x72,0x2a,0x4e,0xb7,0x39,0x5e,0x00,0xa1,0x74,0x95,0xd3,0x2e,0xdf,0x0b,},57,"\xce\x49\x7c\x5f\xf5\xa7\x79\x90\xb7\xd8\xf8\x69\x9e\xb1\xf5\xd8\xc0\x58\x2f\x70\xcb\x7a\xc5\xc5\x4d\x9d\x92\x49\x13\x27\x8b\xc6\x54\xd3\x7e\xa2\x27\x59\x0e\x15\x20\x22\x17\xfc\x98\xda\xc4\xc0\xf3\xbe\x21\x83\xd1\x33\x31\x57\x39"}, + {{0x3c,0x19,0xb5,0x0b,0x0f,0xe4,0x79,0x61,0x71,0x9c,0x38,0x1d,0x0d,0x8d,0xa9,0xb9,0x86,0x9d,0x31,0x2f,0x13,0xe3,0x29,0x8b,0x97,0xfb,0x22,0xf0,0xaf,0x29,0xcb,0xbe,},{0x0f,0x7e,0xda,0x09,0x14,0x99,0x62,0x5e,0x2b,0xae,0x85,0x36,0xea,0x35,0xcd,0xa5,0x48,0x3b,0xd1,0x6a,0x9c,0x7e,0x41,0x6b,0x34,0x1d,0x6f,0x2c,0x83,0x34,0x36,0x12,},{0xef,0xbd,0x41,0xf2,0x6a,0x5d,0x62,0x68,0x55,0x16,0xf8,0x82,0xb6,0xec,0x74,0xe0,0xd5,0xa7,0x18,0x30,0xd2,0x03,0xc2,0x31,0x24,0x8f,0x26,0xe9,0x9a,0x9c,0x65,0x78,0xec,0x90,0x0d,0x68,0xcd,0xb8,0xfa,0x72,0x16,0xad,0x0d,0x24,0xf9,0xec,0xbc,0x9f,0xfa,0x65,0x53,0x51,0x66,0x65,0x82,0xf6,0x26,0x64,0x53,0x95,0xa3,0x1f,0xa7,0x04,},58,"\x8d\xdc\xd6\x30\x43\xf5\x5e\xc3\xbf\xc8\x3d\xce\xae\x69\xd8\xf8\xb3\x2f\x4c\xdb\x6e\x2a\xeb\xd9\x4b\x43\x14\xf8\xfe\x72\x87\xdc\xb6\x27\x32\xc9\x05\x2e\x75\x57\xfe\x63\x53\x43\x38\xef\xb5\xb6\x25\x4c\x5d\x41\xd2\x69\x0c\xf5\x14\x4f"}, + {{0x34,0xe1,0xe9,0xd5,0x39,0x10,0x7e,0xb8,0x6b,0x39,0x3a,0x5c,0xce,0xa1,0x49,0x6d,0x35,0xbc,0x7d,0x5e,0x9a,0x8c,0x51,0x59,0xd9,0x57,0xe4,0xe5,0x85,0x2b,0x3e,0xb0,},{0x0e,0xcb,0x26,0x01,0xd5,0xf7,0x04,0x74,0x28,0xe9,0xf9,0x09,0x88,0x3a,0x12,0x42,0x00,0x85,0xf0,0x4e,0xe2,0xa8,0x8b,0x6d,0x95,0xd3,0xd7,0xf2,0xc9,0x32,0xbd,0x76,},{0x32,0xd2,0x29,0x04,0xd3,0xe7,0x01,0x2d,0x6f,0x5a,0x44,0x1b,0x0b,0x42,0x28,0x06,0x4a,0x5c,0xf9,0x5b,0x72,0x3a,0x66,0xb0,0x48,0xa0,0x87,0xec,0xd5,0x59,0x20,0xc3,0x1c,0x20,0x4c,0x3f,0x20,0x06,0x89,0x1a,0x85,0xdd,0x19,0x32,0xe3,0xf1,0xd6,0x14,0xcf,0xd6,0x33,0xb5,0xe6,0x32,0x91,0xc6,0xd8,0x16,0x6f,0x30,0x11,0x43,0x1e,0x09,},59,"\xa6\xd4\xd0\x54\x2c\xfe\x0d\x24\x0a\x90\x50\x7d\xeb\xac\xab\xce\x7c\xbb\xd4\x87\x32\x35\x3f\x4f\xad\x82\xc7\xbb\x7d\xbd\x9d\xf8\xe7\xd9\xa1\x69\x80\xa4\x51\x86\xd8\x78\x6c\x5e\xf6\x54\x45\xbc\xc5\xb2\xad\x5f\x66\x0f\xfc\x7c\x8e\xaa\xc0"}, + {{0x49,0xdd,0x47,0x3e,0xde,0x6a,0xa3,0xc8,0x66,0x82,0x4a,0x40,0xad,0xa4,0x99,0x6c,0x23,0x9a,0x20,0xd8,0x4c,0x93,0x65,0xe4,0xf0,0xa4,0x55,0x4f,0x80,0x31,0xb9,0xcf,},{0x78,0x8d,0xe5,0x40,0x54,0x4d,0x3f,0xeb,0x0c,0x91,0x92,0x40,0xb3,0x90,0x72,0x9b,0xe4,0x87,0xe9,0x4b,0x64,0xad,0x97,0x3e,0xb6,0x5b,0x46,0x69,0xec,0xf2,0x35,0x01,},{0xd2,0xfd,0xe0,0x27,0x91,0xe7,0x20,0x85,0x25,0x07,0xfa,0xa7,0xc3,0x78,0x90,0x40,0xd9,0xef,0x86,0x64,0x63,0x21,0xf3,0x13,0xac,0x55,0x7f,0x40,0x02,0x49,0x15,0x42,0xdd,0x67,0xd0,0x5c,0x69,0x90,0xcd,0xb0,0xd4,0x95,0x50,0x1f,0xbc,0x5d,0x51,0x88,0xbf,0xbb,0x84,0xdc,0x1b,0xf6,0x09,0x8b,0xee,0x06,0x03,0xa4,0x7f,0xc2,0x69,0x0f,},60,"\x3a\x53\x59\x4f\x3f\xba\x03\x02\x93\x18\xf5\x12\xb0\x84\xa0\x71\xeb\xd6\x0b\xae\xc7\xf5\x5b\x02\x8d\xc7\x3b\xfc\x9c\x74\xe0\xca\x49\x6b\xf8\x19\xdd\x92\xab\x61\xcd\x8b\x74\xbe\x3c\x0d\x6d\xcd\x12\x8e\xfc\x5e\xd3\x34\x2c\xba\x12\x4f\x72\x6c"}, + {{0x33,0x1c,0x64,0xda,0x48,0x2b,0x6b,0x55,0x13,0x73,0xc3,0x64,0x81,0xa0,0x2d,0x81,0x36,0xec,0xad,0xbb,0x01,0xab,0x11,0x4b,0x44,0x70,0xbf,0x41,0x60,0x7a,0xc5,0x71,},{0x52,0xa0,0x0d,0x96,0xa3,0x14,0x8b,0x47,0x26,0x69,0x2d,0x9e,0xff,0x89,0x16,0x0e,0xa9,0xf9,0x9a,0x5c,0xc4,0x38,0x9f,0x36,0x1f,0xed,0x0b,0xb1,0x6a,0x42,0xd5,0x21,},{0x22,0xc9,0x9a,0xa9,0x46,0xea,0xd3,0x9a,0xc7,0x99,0x75,0x62,0x81,0x0c,0x01,0xc2,0x0b,0x46,0xbd,0x61,0x06,0x45,0xbd,0x2d,0x56,0xdc,0xdc,0xba,0xac,0xc5,0x45,0x2c,0x74,0xfb,0xf4,0xb8,0xb1,0x81,0x3b,0x0e,0x94,0xc3,0x0d,0x80,0x8c,0xe5,0x49,0x8e,0x61,0xd4,0xf7,0xcc,0xbb,0x4c,0xc5,0xf0,0x4d,0xfc,0x61,0x40,0x82,0x5a,0x96,0x00,},61,"\x20\xe1\xd0\x5a\x0d\x5b\x32\xcc\x81\x50\xb8\x11\x6c\xef\x39\x65\x9d\xd5\xfb\x44\x3a\xb1\x56\x00\xf7\x8e\x5b\x49\xc4\x53\x26\xd9\x32\x3f\x28\x50\xa6\x3c\x38\x08\x85\x94\x95\xae\x27\x3f\x58\xa5\x1e\x9d\xe9\xa1\x45\xd7\x74\xb4\x0b\xa9\xd7\x53\xd3"}, + {{0x5c,0x0b,0x96,0xf2,0xaf,0x87,0x12,0x12,0x2c,0xf7,0x43,0xc8,0xf8,0xdc,0x77,0xb6,0xcd,0x55,0x70,0xa7,0xde,0x13,0x29,0x7b,0xb3,0xdd,0xe1,0x88,0x62,0x13,0xcc,0xe2,},{0x05,0x10,0xea,0xf5,0x7d,0x73,0x01,0xb0,0xe1,0xd5,0x27,0x03,0x9b,0xf4,0xc6,0xe2,0x92,0x30,0x0a,0x3a,0x61,0xb4,0x76,0x54,0x34,0xf3,0x20,0x3c,0x10,0x03,0x51,0xb1,},{0x06,0xe5,0xd8,0x43,0x6a,0xc7,0x70,0x5b,0x3a,0x90,0xf1,0x63,0x1c,0xdd,0x38,0xec,0x1a,0x3f,0xa4,0x97,0x78,0xa9,0xb9,0xf2,0xfa,0x5e,0xbe,0xa4,0xe7,0xd5,0x60,0xad,0xa7,0xdd,0x26,0xff,0x42,0xfa,0xfa,0x8b,0xa4,0x20,0x32,0x37,0x42,0x76,0x1a,0xca,0x69,0x04,0x94,0x0d,0xc2,0x1b,0xbe,0xf6,0x3f,0xf7,0x2d,0xaa,0xb4,0x5d,0x43,0x0b,},62,"\x54\xe0\xca\xa8\xe6\x39\x19\xca\x61\x4b\x2b\xfd\x30\x8c\xcf\xe5\x0c\x9e\xa8\x88\xe1\xee\x44\x46\xd6\x82\xcb\x50\x34\x62\x7f\x97\xb0\x53\x92\xc0\x4e\x83\x55\x56\xc3\x1c\x52\x81\x6a\x48\xe4\xfb\x19\x66\x93\x20\x6b\x8a\xfb\x44\x08\x66\x2b\x3c\xb5\x75"}, + {{0xde,0x84,0xf2,0x43,0x5f,0x78,0xde,0xdb,0x87,0xda,0x18,0x19,0x4f,0xf6,0xa3,0x36,0xf0,0x81,0x11,0x15,0x0d,0xef,0x90,0x1c,0x1a,0xc4,0x18,0x14,0x6e,0xb7,0xb5,0x4a,},{0xd3,0xa9,0x2b,0xba,0xa4,0xd6,0x3a,0xf7,0x9c,0x22,0x26,0xa7,0x23,0x6e,0x64,0x27,0x42,0x8d,0xf8,0xb3,0x62,0x42,0x7f,0x87,0x30,0x23,0xb2,0x2d,0x2f,0x5e,0x03,0xf2,},{0x47,0x1e,0xbc,0x97,0x3c,0xfd,0xac,0xee,0xc0,0x72,0x79,0x30,0x73,0x68,0xb7,0x3b,0xe3,0x5b,0xc6,0xf8,0xd8,0x31,0x2b,0x70,0x15,0x05,0x67,0x36,0x90,0x96,0x70,0x6d,0xc4,0x71,0x12,0x6c,0x35,0x76,0xf9,0xf0,0xeb,0x55,0x0d,0xf5,0xac,0x6a,0x52,0x51,0x81,0x11,0x00,0x29,0xdd,0x1f,0xc1,0x11,0x74,0xd1,0xaa,0xce,0xd4,0x8d,0x63,0x0f,},63,"\x20\x51\x35\xec\x7f\x41\x7c\x85\x80\x72\xd5\x23\x3f\xb3\x64\x82\xd4\x90\x6a\xbd\x60\xa7\x4a\x49\x8c\x34\x7f\xf2\x48\xdf\xa2\x72\x2c\xa7\x4e\x87\x9d\xe3\x31\x69\xfa\xdc\x7c\xd4\x4d\x6c\x94\xa1\x7d\x16\xe1\xe6\x30\x82\x4b\xa3\xe0\xdf\x22\xed\x68\xea\xab"}, + {{0xba,0x4d,0x6e,0x67,0xb2,0xce,0x67,0xa1,0xe4,0x43,0x26,0x49,0x40,0x44,0xf3,0x7a,0x44,0x2f,0x3b,0x81,0x72,0x5b,0xc1,0xf9,0x34,0x14,0x62,0x71,0x8b,0x55,0xee,0x20,},{0xf7,0x3f,0xa0,0x76,0xf8,0x4b,0x6d,0xb6,0x75,0xa5,0xfd,0xa5,0xad,0x67,0xe3,0x51,0xa4,0x1e,0x8e,0x7f,0x29,0xad,0xd1,0x68,0x09,0xca,0x01,0x03,0x87,0xe9,0xc6,0xcc,},{0x57,0xb9,0xd2,0xa7,0x11,0x20,0x7f,0x83,0x74,0x21,0xba,0xe7,0xdd,0x48,0xea,0xa1,0x8e,0xab,0x1a,0x9a,0x70,0xa0,0xf1,0x30,0x58,0x06,0xfe,0xe1,0x7b,0x45,0x8f,0x3a,0x09,0x64,0xb3,0x02,0xd1,0x83,0x4d,0x3e,0x0a,0xc9,0xe8,0x49,0x6f,0x00,0x0b,0x77,0xf0,0x08,0x3b,0x41,0xf8,0xa9,0x57,0xe6,0x32,0xfb,0xc7,0x84,0x0e,0xee,0x6a,0x06,},64,"\x4b\xaf\xda\xc9\x09\x9d\x40\x57\xed\x6d\xd0\x8b\xca\xee\x87\x56\xe9\xa4\x0f\x2c\xb9\x59\x80\x20\xeb\x95\x01\x95\x28\x40\x9b\xbe\xa3\x8b\x38\x4a\x59\xf1\x19\xf5\x72\x97\xbf\xb2\xfa\x14\x2f\xc7\xbb\x1d\x90\xdb\xdd\xde\x77\x2b\xcd\xe4\x8c\x56\x70\xd5\xfa\x13"}, + {{0x0d,0x13,0x1c,0x45,0xae,0xa6,0xf3,0xa4,0xe1,0xb9,0xa2,0xcf,0x60,0xc5,0x51,0x04,0x58,0x7e,0xfa,0xa8,0x46,0xb2,0x22,0xbf,0x0a,0x7b,0x74,0xce,0x7a,0x3f,0x63,0xb6,},{0x3c,0x67,0x29,0xdb,0xe9,0x3b,0x49,0x9c,0x4e,0x61,0x4a,0x2f,0x21,0xbe,0xb7,0x29,0x43,0x8d,0x49,0x8e,0x1a,0xc8,0xd1,0x4c,0xba,0xd9,0x71,0x7a,0x5d,0xbd,0x97,0xcd,},{0xa9,0xc5,0xee,0x86,0xfb,0x06,0xd9,0xe4,0x6b,0x37,0x9c,0x32,0xdd,0xa7,0xc9,0x2c,0x9c,0x13,0xdb,0x27,0x4d,0xc2,0x41,0x16,0xfb,0xdd,0x87,0x86,0x96,0x04,0x54,0x88,0xcc,0x75,0xa5,0x2f,0xff,0x67,0xd1,0xa5,0x11,0x3d,0x06,0xe3,0x33,0xac,0x67,0xff,0x66,0x4b,0x3f,0x2a,0x40,0x5f,0xa1,0xd1,0x4d,0xd5,0xbb,0xb9,0x74,0x09,0xb6,0x06,},65,"\xb4\x29\x1d\x08\xb8\x8f\xb2\xf7\xb8\xf9\x9d\x0d\xce\x40\x07\x9f\xcb\xab\x71\x8b\xbd\x8f\x4e\x8e\xab\xc3\xc1\x42\x8b\x6a\x07\x1f\xb2\xa3\xc8\xeb\xa1\xca\xcc\xcf\xa8\x71\xb3\x65\xc7\x08\xbe\xf2\x68\x5b\xc1\x3e\x6b\x80\xbc\x14\xa5\xf2\x49\x17\x0f\xfc\x56\xd0\x14"}, +}; + +bool TestCryptoSign() +{ + // https://github.com/jedisct1/libsodium/blob/master/test/default/sign.c + const unsigned int MAX_MESSAGE = 65; // Sync with test data + + byte pk[crypto_sign_PUBLICKEYBYTES]; + byte sk[crypto_sign_SECRETKEYBYTES]; + SecByteBlock sm(MAX_MESSAGE+crypto_sign_BYTES); + SecByteBlock rm(MAX_MESSAGE+crypto_sign_BYTES); + + bool pass = true, fail; int rc; + + for (unsigned int i=0; i(data.msg); + const word64 l = data.len; + word64 smlen; + + rc = crypto_sign(sm, &smlen, m, l, sk); + fail = (rc != 0); pass = !fail && pass; + + word64 s = STDMIN(smlen, (word64)crypto_sign_BYTES); + pass = (s >= crypto_sign_BYTES) && pass; + + fail = std::memcmp(sm, data.sig, (size_t)s) != 0; + pass = !fail && pass; + + word64 rmlen; + rc = crypto_sign_open(rm, &rmlen, sm, smlen, pk); + fail = (rc != 0); pass = !fail && pass; + + pass = (l == rmlen) && pass; + fail = std::memcmp(m, rm, (size_t)STDMIN(l, rmlen)) != 0; + pass = !fail && pass; + } + + return pass; +} + +bool TestCryptoSignKeys() +{ + // https://github.com/jedisct1/libsodium/blob/master/test/default/sign.c + const unsigned int MAX_TEST = 64; + const unsigned int MAX_MESSAGE = 4096; + + byte pk[crypto_sign_PUBLICKEYBYTES]; + byte sk[crypto_sign_SECRETKEYBYTES]; + + bool pass = true, fail; int rc; + + for (unsigned int i=0; i +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +bool TestIntegerBitops() +{ + std::cout << "\nTesting Integer bit operations...\n\n"; + + struct Bitops_TestTuple + { + // m,n are operands; a,o,x are and,or,xor results + const char *m, *n, *a, *o, *x; + }; + static const Bitops_TestTuple tests[] = { + { + "0xc2cea8a4", "0xb36e5794", "0x824e0084", "0xf3eeffb4", "0x71a0ff30" + }, + { + "0x436eb828", "0x1b375cb4", "0x3261820", "0x5b7ffcbc", "0x5859e49c" + }, + { + "0x1e5c0b28", "0x4fded465", "0xe5c0020", "0x5fdedf6d", "0x5182df4d" + }, + { + "0xeb71fde7", "0xf7bb47cf", "0xe33145c7", "0xfffbffef", "0x1ccaba28" + }, + { + "0xa6b0f01f", "0x8a8ca98", "0xa0c018", "0xaeb8fa9f", "0xae183a87" + }, + { + "0xa70bd8b7", "0x5c758cf5", "0x40188b5", "0xff7fdcf7", "0xfb7e5442" + }, + { + "0xf91af382", "0x718a9995", "0x710a9180", "0xf99afb97", "0x88906a17" + }, + { + "0xbd2a76ad", "0xddd8dfeb", "0x9d0856a9", "0xfdfaffef", "0x60f2a946" + }, + { + "0xd4b559cc", "0x91a53295", "0x90a51084", "0xd5b57bdd", "0x45106b59" + }, + { + "0x89434e9e", "0xa42fdaf9", "0x80034a98", "0xad6fdeff", "0x2d6c9467" + }, + { + "0xb947ac04", "0xd4201e52", "0x90000c00", "0xfd67be56", "0x6d67b256" + }, + { + "0xa83945c1", "0x3a9c5dba", "0x28184580", "0xbabd5dfb", "0x92a5187b" + }, + { + "0xbca38ffa", "0x881ba9fd", "0x880389f8", "0xbcbbafff", "0x34b82607" + }, + { + "0xfcd0b92", "0xeaad8534", "0xa8d0110", "0xefed8fb6", "0xe5608ea6" + }, + { + "0x50d160d0", "0x64646f75", "0x40406050", "0x74f56ff5", "0x34b50fa5" + }, + { + "0x165ccff8", "0x67d49127", "0x6548120", "0x77dcdfff", "0x71885edf" + }, + { + "0x8c4f4bbb7adaacb5", "0x2566b7a909b24aa9", "0x44603a9089208a1", "0xad6fffbb7bfaeebd", "0xa929fc127368e61c" + }, + { + "0x6f9ef50aafb31e8d", "0x7a93b2ccd1bbbff2", "0x6a92b00881b31e80", "0x7f9ff7ceffbbbfff", "0x150d47c67e08a17f" + }, + { + "0x4c99e967f8de5294", "0x1f4699e0c14e6974", "0xc008960c04e4014", "0x5fdff9e7f9de7bf4", "0x53df708739903be0" + }, + { + "0xcc55f5d6d3ea45c", "0x6805b4ddb6390c2f", "0x805145d2438040c", "0x6cc5ffddff3fac7f", "0x64c0eb80db07a873" + }, + { + "0x90620d1a012459e7", "0x89d31098ce3fed42", "0x8042001800244942", "0x99f31d9acf3ffde7", "0x19b11d82cf1bb4a5" + }, + { + "0xb87d1674e90a935a", "0x75ea466cbb782ac4", "0x30680664a9080240", "0xfdff567cfb7abbde", "0xcd9750185272b99e" + }, + { + "0x1f135732240701f0", "0x6aa09a1614bf4dd4", "0xa001212040701d0", "0x7fb3df3634bf4df4", "0x75b3cd2430b84c24" + }, + { + "0xc9a88d8300099a31", "0xdc8e91df745169ee", "0xc888818300010820", "0xddae9ddf7459fbff", "0x15261c5c7458f3df" + }, + { + "0xc8c828d15228b562", "0x43f86cffa3d15d80", "0x40c828d102001500", "0xcbf86cfff3f9fde2", "0x8b30442ef1f9e8e2" + }, + { + "0x41fdc0bc2009563f", "0x59dd1c417e3c07bc", "0x41dd00002008063c", "0x59fddcfd7e3d57bf", "0x1820dcfd5e355183" + }, + { + "0x9e2f78600c3a84e7", "0xac69a0e1fe7887b0", "0x8c2920600c3884a0", "0xbe6ff8e1fe7a87f7", "0x3246d881f2420357" + }, + { + "0xd424d1d9a955f617", "0x9608f5bde1c4d893", "0x9400d199a144d013", "0xd62cf5fde9d5fe97", "0x422c246448912e84" + }, + { + "0x1aa8b60a0627719a", "0x5b26e6aca95f5f60", "0x1a20a60800075100", "0x5baef6aeaf7f7ffa", "0x418e50a6af782efa" + }, + { + "0xcf5db499233fac00", "0xf33e7a29c3c33da8", "0xc31c300903032c00", "0xff7ffeb9e3ffbda8", "0x3c63ceb0e0fc91a8" + }, + { + "0x6b47c03d576e878d", "0x2032d13574d67da4", "0x2002c03554460584", "0x6b77d13d77feffad", "0x4b75110823b8fa29" + }, + { + "0xd47eeb3aefebf074", "0x6d7ba17a42c66b89", "0x447aa13a42c26000", "0xfd7feb7aefeffbfd", "0xb9054a40ad2d9bfd" + }, + { + "0x33ad9c5d20b03f5c05535f20a2941c8f4ae0f1f19500759151060dce39e5dfed41ec4f", + "0x277401dc000fde7eda4d60a5698935f7febd8fbe49e5d6f56ca2e7f6118380d3cd655da392df3ba6c1b13dc0119af34cfa1d18a65", + "0x10a9841c002016480453410020041c8640c0312191006411110401082924cfa1418845", + "0x277401dc000fde7eda4d60a5698935f7febfbfffcdf7dff7fde2f7f7f38ba9d3cdf5ffaf9fdf7ba7d9b53de0ddfbff5dfedd1ee6f", + "0x277401dc000fde7eda4d60a5698935f7febeb5678c37ddf69962b2c3e389a9920591f3ac8dc66ba198a42da0cd796d1104c90662a" + }, + { + "0xb6ea335c13111216862e370d12fb9c761a6266617f62a1904b0d7944ab3cddc71f11752ad9424b0", + "0xa6b380f048a9cbe45ff4ea824064c831eb03ff875e1e3e", + "0xa62200104028090410d480020044c831e1035285140430", + "0xb6ea335c13111216862e370d12fb9c761a6b7e6f7feabdbe4fff7fecaf3eddc71fb17ffafde3ebe", + "0xb6ea335c13111216862e370d12fb9c7610095e6e7be83d2e0ef237ec8f3a914401a14ad2aca3a8e" + }, + { + "0x8fb9486ad1f89ca5b3f6da9f0d5ef9ec328b8cc3e5122afbd8a67bd1b2b4ab5c548b90cf9fe1933a0362922f1e84ef0", + "0x10615f963dffc13718ed1ecdb9cfbef33148befeb91b190dc7e7d28d8821ff248ab26a34e1b89885c643e447c72", + "0x6051901ca58136188d0c4cb9cc32830040a412281b180443c192848800540080820a208138000082030404c70", + "0x8fb9586bdffebdfff3f7daff1fdff9efbefbbdcbfffebbfbd9affff7f2bdab7dffaf9afffff5f3ba9be7d66ffec7ef2", + "0x8fb9580b8e6ea15a72c1c272139340238c78bd8b5bec93e0c1abbc366039237dabaf1a7df5d572829be7546cfac3282" + }, + { + "0x10af96443b186faf790279bf3bbe0517d56ffc01e7fec8c88e765d48cc32333390224f4d762d1ba788c50801cba02524cb49", + "0x95d44e7344fb1701bace3ae83affbb6290bf282f7565b9a82c386823f5f213a53eccb2cfe5deb4dd040067a64ada8c1b6828599b96cc70647e7d19dc7dfba393addabe689ffbe1a36642bc9844b81c6c4c2e178", + "0x2c96442b084000000260ad288004028509b800c70640c080144548883032118022094d3608122408c1000181800400c148", + "0x95d44e7344fb1701bace3ae83affbb6290bf282f7565b9a82c386823f5f213a53ecdbaffe5dfb5dffef7f7a7dbfbbffb797d5fffd6de7fecfefdfffdfdffe3b3bffbbe6cffffe3f3fe7abcd8c4bcbe6e5e6eb79", + "0x95d44e7344fb1701bace3ae83affbb6290bf282f7565b9a82c386823f5f213a53ecdb836819d055bfef7f781d12937fb39550f6456d20f88f2f5feb9a97760b09ee3bc4c6b2c8372dc3a30c8c4a4a66e1e62a31" + }, + { + "0x5fc77dab8cd9c1da8c91eb7ba9c23ce85375b61bf3b9a8c4e4df7bc917aa8a14e747888c9756a2be2fd2e256e44194ce093a0185594de0dcf8340c45b6af7dbdc7682fbef6313f9f1cb234689d9f1ff603e1273faad89d0fe1ab57fbc7c32d29dce125fafc973754464b55ae5de58a8a5661c2065b95c2c94d7ec34", + "0xd4a9158961d4c11258cd047eda13d6804c16c3a374b7f4115bd835bde0b5", + "0x1080158800548100504504649012c480480081221420641158081495e034", + "0x5fc77dab8cd9c1da8c91eb7ba9c23ce85375b61bf3b9a8c4e4df7bc917aa8a14e747888c9756a2be2fd2e256e44194ce093a0185594de0dcf8340c45b6af7dbdc7682fbef6313f9f1cb234689d9f1ff603e1273faad89d0fe1ab57fbc7cf6fb9dcf73dfefdb7bfd447eff5bf7de5cbee7e77cb7f5b95ffcb5ffecb5", + "0x5fc77dab8cd9c1da8c91eb7ba9c23ce85375b61bf3b9a8c4e4df7bc917aa8a14e747888c9756a2be2fd2e256e44194ce093a0185594de0dcf8340c45b6af7dbdc7682fbef6313f9f1cb234689d9f1ff603e1273faad89d0fe1ab57fbc7ce67b8847738b6edb2bb8401a6f49335e14be66c5689791a807f4a16a0c81" + }, + { + "0x52cbea1f4d78445fb8f9267203f0f04bddf65b69b1acb0877143e77317f2d9679cb", + "0x331e156a1e1daa0039926a08ec80c2d7c1500bc435a53ebfc32fa398a3304fcd79d90725528e320add050da666b9de42b8307b", + "0x88421a41684412b839023200f0d00990725128a120a0805042666315e0090304b", + "0x331e156a1e1daa0039926a08ec80c2d7c1552ffeb5f5ffbfc7ffaf9ae7307fcf7dfddf65f69f3acbdd771dbe77b9ff6fbe79fb", + "0x331e156a1e1daa0039926a08ec80c2d7c155277a9451e93b86d42c0ac41070c27d64d840e41528c1d57219981188a16f2e49b0" + }, + { + "0xbde7e20f37c3ed822555d36050240dcfb5a9a3867d149cffe78e92b95573cbdde33a8c9495148e04cafa1325aae058b4a98c50f7019de1345de6dce12436bed4b86eca2d", + "0xee480b4096f0c1ac565d623dd53b62dba81c507d3c8e15372396fa49de0ecf074fb0ed1785f00f8094022ff50fc436a7cbd18de8ff317c33ea9bdbd8814a7658fcd1fd10b2ed10eaf7e4c2b8f409df3c36f1f0c986a49805a9ed08bbcd603e2eec9e18", + "0x547a00d1781e0020014022050040406a58981846814107c238a929950014a544038809410108c00caf20000a8e00894280450f00184a01005a0cc0020042014286c8a08", + "0xee480b4096f0c1ac565d623dd53b62dba81c507d3c8e15372396fa49de0ecfbfeff2ef37c7fd8fa5d5d36ff52fcdffb7ebf38ffdffbdfff7ee9bfbddf3cbfffbfeddfd95b6ef14eafff7e7baf459ffbdbef1f7c99fe5bc5deffde9bffffefebeeede3d", + "0xee480b4096f0c1ac565d623dd53b62dba81c507d3c8e15372396fa49de0ecfbaa852e220461d8da5c1d14fa52bc9f91262720b95ebad83d46409628df281abbbc65d6985a66314200df7e71214516b95baa107c81b45ac584f31e99ffbdeea96825435" + }, + { + "0x17ed0a1aa80542396e82ab79f6d4dda731d10f9487467fcfa5c8b501fa86488fbe268605c01beb257c9e301a42833d22965ea2ff0eda5f18427481a300a8f9aa81e76d774ea1dbed40268eca094bef627d2c206f6885fc12f71557bfda836", + "0x422340e8ff3b4177efa5f58111fe306aa602d8020164fa34c12acdb3de81e", + "0x2340604e21416540248480014a2062240000020004f810c10045b3da816", + "0x17ed0a1aa80542396e82ab79f6d4dda731d10f9487467fcfa5c8b501fa86488fbe268605c01beb257c9e301a42833d22965ea2ff0eda5f18427481a300a8f9aac3e76dffffbbdbffefa7ffcb19ffff6aff2ef86f69e5fe36f73fdfbfde83e", + "0x17ed0a1aa80542396e82ab79f6d4dda731d10f9487467fcfa5c8b501fa86488fbe268605c01beb257c9e301a42833d22965ea2ff0eda5f18427481a300a8f9aac3c42d9fb19a9a9aaf837b4b18b5df08db2ef86d69e10626363f9a0c04028" + }, + { + "0x290796408a0b8baa742b9d466afc4958528f7976fdce50caa83ed63285f58d200e4c65842ea24c3d4a3850a1824b61d25af9d3b41b9e64407a5262a75d9efd08481cfbc339ae26b0755438894b9e2298a35ed9", + "0x4cb6f7935f5cc586320c6ce957f82cff774cde7d4201735a5acd22190fcb1c9c16d1887a", + "0x4012f193141884040008406007580cfd00481c794201220210450018094b1c0010810858", + "0x290796408a0b8baa742b9d466afc4958528f7976fdce50caa83ed63285f58d200e4c65842ea24c3d4a3850a1824b61defeffd3ff5fdfe6727e7eebf7fdbeff7f4cdeffc339ff7efafd76398fcb9ebe9ef3defb", + "0x290796408a0b8baa742b9d466afc4958528f7976fdce50caa83ed63285f58d200e4c65842ea24c3d4a3850a1824b619eec0e40eb475be272763e8bf0a5b2027f04c2868138dd7ceab87621868082be8e72d6a3" + }, + { + "0x14e55ecb09d8c6827022df7c713c05a5d882e25782", + "0x2dbdb54cb6341fcea6f67cfaa5186aa0a91b9782e362cbb0dd0ef3cbc130ce0cb2ce7232c0562", + "0x10600e020898048060209c1000200124c002200502", + "0x2dbdb54cb6341fcea6f67cfaa5186aa0a91bdfd7eff2dfbcfd2ff3eff7f7dfccfadffa3ee57e2", + "0x2dbdb54cb6341fcea6f67cfaa5186aa0a91ad9d70fd2563cb529f1e636f7ddcce893fa1ce52e0" + }, + { + "0x2b0dfd23fc740e1759697bcba800aa1be7df28c59fe72b9869766ac34ecb4e5d0dbc74c2cbb5f734bb8d38dab59c3f22cdc706c657839580c2793c4c7660606548c048a697db3dfbad82e695c605", + "0x33080f6fd52aeca572f24a98ff19b9e7327c3b951ccfd8c9a6b9bd6f7c940079e4be88178a2a6d5a2b17", + "0x30007249108288030900a00cd0100c612001180004918482620206548800020849a0813880264100205", + "0x2b0dfd23fc740e1759697bcba800aa1be7df28c59fe72b9869766ac34ecb4e5d0dbc74c2fbbdff7fffaffcfff7fe7fbaffdfbfe777ffbf95defffccdf6f9fd6f7cd448fff7ffbdffafaaefdfef17", + "0x2b0dfd23fc740e1759697bcba800aa1be7df28c59fe72b9869766ac34ecb4e5d0dbc74c2f8bdf85b6ea7d47fc76e75ba32debf2165ffae15deb6e485d0d9dd0a345448df7365b5ec27a88bcfed12" + }, + { + "0xc0cc21922748d7626df1ab92b4ad4df1861050ca7de74adb92a140", + "0x3531a6880ccc47bc3826056efe912f3db02df9c0b6931e253ab9248f472359fe59218690f6781f35da89b8f1ff45cd5a1db9a414c9d7ec62ff5859a1572b1c1880a99aa74ebe8b12c68e791c11dd6cc0e5ed5", + "0xc40192054091400800898234a948b104004080410542c8020040", + "0x3531a6880ccc47bc3826056efe912f3db02df9c0b6931e253ab9248f472359fe59218690f6781f35da89b8f1ff45cd5a1db9a414c9d7ec6effda59a377af7e3edfbbbbaf4efedf1ae78f7dbfdffdedf9effd5", + "0x3531a6880ccc47bc3826056efe912f3db02df9c0b6931e253ab9248f472359fe59218690f6781f35da89b8f1ff45cd5a1db9a414c9d7ec6ef39a408323a66a3e5fb3238c046a540aa78b75bbcfa9c179cff95" + }, + { + "0x68cbb0a526d1fa61003e12401db51090fa4649b00b7be7465d0eb18f74c86157a919", + "0x1ca7d6f9bc3e11d3c365af63bf9499b6c7e9c569da7361f0214b8d", + "0x1610001c111080600641b00019a6464904218a704060010909", + "0x68cbb0a526d1fa7da7fefbfc3fb5d3d3ffef6bbf9ffbf7c7fdcff9df77e9f177eb9d", + "0x68cbb0a526d1fa7da7e8ebfc23a4c3539fe92a0f9fe25181b4cbd85507a99176e294" + }, + { + "0x210bef18d384992c5eb72e2b362c7296d9810f5ba9fd25e2d5648989d65095e45d1478f2a83140a0f68033a08fa3d7c392a3dc77e8e6aeba9ed76038e9e7825255fac990bf1098e6f9cba0", + "0xdb48641b3f63e5f1f41ff3b1578c4b190de42379d45cba03c4c6f34b1b14ea930fdff90dca53116710228e45b081fbddc9273a542e6f689642453adb91086bdb99681342113262d67f5517f2691024fe367459b01872549211067798063cc00b16c883b8cd2ffaa6d6116863f204bb23ce26c5bcdaf3e1b816dcf65ca", + "0x21014200d280002452a52800062c309681000113202d25e051640081024081644510008220010000660000208c00914080238c52e8a22c201686202049a20042445ac9803e108064c94180", + "0xdb48641b3f63e5f1f41ff3b1578c4b190de42379d45cba03c4c6f34b1b14ea930fdff90dca53116710228e45b081fbddc9273afeffef78dfd2c5fbfbf3bb6bdfb96d9b52f5baffd67f7d57faf99d65ff7e75d9f79f7ad7961b0f7f9b3e3cfa3f7ef9abbdcf7ffeeeffb9ed77f38ebf7bef27dfbcdbfbf1b99efffefea", + "0xdb48641b3f63e5f1f41ff3b1578c4b190de42379d45cba03c4c6f34b1b14ea930fdff90dca53116710228e45b081fbddc9252aeadfe250dfd080d1a973bb091cb0058b52e488fd04217841baf18d41f7683188f79758d7861b091f9b3c343a366af1a9850a5174cc3db88515f18a255beb039a1043f810b198b36ae6a" + }, + { + "0x143143205d76a7287d48be24db8fbfe37c291d82e103aa05cfc172fb920f0e8cc15c47de948b964e39be34a5b8a2610198c0c5b98543e6e727be153cfff0338f229cc22f029e04f766c62988634fee1a0a16880c93e5b10bada4018b6765b54c08f5710344dbfb9e9ad5dd7914cab496b22a6", + "0x2d58b8b513f4bceb8300f8b978e31c163f36155e9678bb0f221ee7cbcf7262b9d53c7a395ea916218fa2478baada74f3e69df63a7be0c9554c07004f9e4d869642bbd63a9fe07138a6aef7ad14c74231cf6401c597f9b6d15c266c42c28613838609bd4f4522c9eb65fc8456acc339c641ac7d7b7bc2c48c8f2", + "0x100201970a308140836045a8638a30c201c82c103220089c1307a100e0804010c0246808a924431a614a4382260011040050005024486060211143a902001208482270014044220c620004107e8120014000c02c080038184018947452048086570004488c31882418c79104a8084800a2", + "0x2d58b8b513f4bcffb343f8fd7ee73c7f7fbe35df9ffffb7f2b1fe7ebcffa67ffd57efbbb5faf9ee1dfe7df9fabde7efbfebdf7bafbe1c9ddccc7b9cfdfefe7b7febffefffff3ff3abeeeffaf9ec7f777cf6d89e7dfffbedb5eae6cd3e7b71bafa609bf6f65b7cdebf5fd8756fffbbfded5fd7d7ffbf6d6beaf6", + "0x2d58b8b513f4bcffb243d8e40e44346b7788318519c758730b03652accd86776144e81ab51a79ae0d3e5991f214c3aca58a95382d981c8cd8cc2b9caddab61b1fcaeeac56fd3fe1a3a6cd8af8ac3b557094d89a6d817acdb4aae60d12737182e22083628209785e3908d87127738a75c9471046fb176523ea54" + }, + { + "0x258e988b847b06b73462629161e28517f7b9ad7b5c19a9ad2c07f9a66f33fb2220fddb5a33b9cd5c2d63fd543efa1bef16e26b95484d70d0d7cfce28491ace0a608fb6cf9e97cb88d73c96c9150f9ef53c5e75bd68805fdce891e5935e9428ca67eba1e345148fcf2", + "0x1857c0e26e0476169cf804c8d5a431022cce0da75d7642a2414a900370f201f5073c7e700ff6626fbd8a104182954fa9f23a45474af5456a00e36f6a6c8162afdf7492d387a455dd8506167d5cc24e6861d7b480b1458230", + "0x1812c0a04000121280780040d12430020ccc05a319144082400a900360a000f10624385004d6000d3c880000808440a0003a44414874000800c16c0040816203c56412d2800455cc8106103548420c206092140011408030", + "0x258e988b847b06b73462629161e28517f7bdfd7f7ef9efed6dcff9eeef7bfb3222fdfbda77ffed7e2d77fd543fff3bff56f3eff748ff76f6ffdfef2c593bdefaffafb6dffebfdfdef73eb6ffb7cf9efffdff7dbd78fa5fddf8d1e5f7dfdc2ceee7fffbeb4f14dfef2", + "0x258e988b847b06b73462629161e28517f63cd1757af9eecc45c879eae269b83202313b80466ea9760977545409f53bf04691ac7248b216f62c176f2c51339af0ffac129bea389fde7732a03fb3c788dfc1a93c9050fa1a8130c184f48b580c2ce1f6daab4e00d7ec2" + }, + { + "0x328edc02c67d84bf095ac048e50c2dc29cffc08184b11e4da02904be14eccd317e9f6bdd6fe2b8233e8928d65d4ad434ef8a629cae6013bfb3c54be167e16371dc6412b62c2b1213424dfb7d391cea8a7494a28576ce823d8e111994182909efba7dd3533dbbe510dab4ac5ef", + "0x61a1365a1226597896c514f5bb16a064f6ff6982ac91ea568daa43e473aa63867bdb628e92e97ebd4f2091", + "0x4121224210201020968510918a00a04042284100a801c84001884180108a63865911228a92410ca94a0081", + "0x328edc02c67d84bf095ac048e50c2dc29cffc08184b11e4da02904be14eccd317e9f6bdd6fe2b8233e8928d65d4ad434ef8a629cae6013bfb3c54be167e16371dc661ab76dab3277d7cdff7d7f5ffbea76dfeff7feeecb3faf79dbb43e6f3befba7ffff73dfbef97fbf4fe5ff", + "0x328edc02c67d84bf095ac048e50c2dc29cffc08184b11e4da02904be14eccd317e9f6bdd6fe2b8233e8928d65d4ad434ef8a629cae6013bfb3c54be167e16371dc6208a5498a3076d5c4972c76475be072dbcd73eee44b232b79c330266e3349821a6ee51552cb8731605e57e" + }, + { + "0x37a92944b67fae733d201c024838975531bc3f748d98089eed38faed40c9463441cf48ac40e98097ce75db2bf0120ef69087a176d31d562cc99137c67e4a659cbb1298ba150aa191ced4089deee7048511de602414936af93cb2cef1b7ee801d9b75d961d33bb2958669b16193abf7b55ccfebac3a490415128dac92", + "0x6fb8d83d986c4604db1b9396493a0a68270806cdbcc3299a049ebe77bd6891258e6313c720fb1b30ae9c4387ba51db3325e15033d9e01d499707c138b4cf4b85032da65e9ce3aabc5effbf7003771476ff71e86f665d2d3e7578dfcbb8f08c1619f609ec147f0", + "0x88c811882c440490030014400a0008000804c51c822900008e2800380001218462008100780320a6184381280181102001102140801c4810004118a4024101022d824a0ce30a3c4801993001161432bb2148660214093a357855c8b8b080041040012810490", + "0x37a92944b67fae733d201c024838975531bc3f748d9efb9feff9feed60cdf7bd79efdbace6ebf097eeffdf3bf9b24ffff7fff7ffd35df63dfdf33ff7ff4aeddcbb7bbdbfb73aff95cffd9e9dfeff74fd13df6cf4bcd37afb7dfbcefbbfefefffff75ff71d77ff79f86fff5f3d3eff7bdfcffefacfb699f759ecdeff2", + "0x37a92944b67fae733d201c024838975531bc3f748d9ef3136ee17c292084f78d78abdb0ce66bf017a2ae171969b2471d77fc77ffc145b01df5e33877cd408c5883693da7a638ff84cde9969c3a7e74f902552cd0acc35823595b00cb1c2b6fe66c75ee109454458b009fd4b3404ca038a07464a4fb289b758c4ceb62" + }, + { + "0x1ab020d8beb54c354411f3a5658b5e5e87a896d7049c5eab20a302b6e35ca98364d7edd00eb3e209dcb035fe4b6eeace4e525229bf790c67bae63821e1282712d7c624efa64b3e5ad1a73aeb1033d4cd5949d63183173632445c9f488e74cd", + "0x4d706a200a7a70e0b6eeef2dbdb88779dd50af16e6405c17fd2c2efb5493cf13b730207a009a14ca150042af3e6b7f05230161a10073f87a56afede3c2cfd09857f78d7913cdd966e9a2e6e6e3", + "0x45000000a2a20a002a6e30ca9800451cd500e12e2005c10352c0a6a40824e1212202078000210c21000402826025704200120010052d02212ab0023c0cd5008563181111200404489008664c1", + "0x1ab020d8beb54c354411f3a5658b5e5e87a8dff76ebc5efb70e3b6feef7dbdbbe7fffdd0afb7e649dcb7fdfe6ffffedfcf53f739bf7b0cffbeee3d21e3af3f7bffc727efe7eb3e7bf9ff7eeffdf3d6cfd9d9d7f78f7f37ffdd7effeaeef6ef", + "0x1ab020d8beb54c354411f3a5658b5e5e87a8dba76ebc54d15043b4580c71143be3ae3080a1a5044980a7c8d26595be5d8141e5199f030cfdae2c2d21a3871979a8c307eec7ea3e2929dd6c44fdd0160289d181c60e6e25ff9d3a76ea68922e" + }, + { + "0x85993ec08ac960d46bcba87136f24042485c6d3e0a9973e828df60e537860d6bc83dafa7fb292beef466d0a939ab9da2b", + "0x4c9a310b11d6e4b4d29d7ede30fb42161fd6a58792440f416abda6df55913a8a26c35140524de5dd9519c30f19641f4f0863bfefc2ae6c89333dd77d6f688cffcbde281772cee0dac9bb0dd16b6c1d33fa7e39b2e781896dcc2b0aba3abedf1381f9f38eb210f5bd2001ea8453ceb136dc3915fabdc30709db0b1a07ec40be", + "0x811926c08a08601002c8803022a2004040180d1e0889210808d2000420040c6b002d83815b290820700490a1202a8402a", + "0x4c9a310b11d6e4b4d29d7ede30fb42161fd6a58792440f416abda6df55913a8a26c35140524de5dd9519c30f19641f4f0863bfefc2ae6c89333dd77d6f688cffcbde281772cee0dac9bb0dd16b6c1d7bfbfe39bef78dcffdfeaf1bff3ebeff97c7fbf3afb73ef7bdf60ffbfc73debdb7defb7ffabfffef4fff0b9b9ffddabf", + "0x4c9a310b11d6e4b4d29d7ede30fb42161fd6a58792440f416abda6df55913a8a26c35140524de5dd9519c30f19641f4f0863bfefc2ae6c89333dd77d6f688cffcbde281772cee0dac9bb0dd16b6c156a6992311e718ccfd176ac19d51ebafb96472a1327252e7730d60fb9fc33180db506c36a482f7de84fb601899d559a95" + }, + { + "0x4d9f3e8aae22123e382e7835d3d9d7e944a5c81cab3415fda40d0ec8fde8a50d8b21b2298f83a65bbdb10d120d302d8db4e9807715be0e", + "0x4dacc1a6f2cecd4179556cbbdfe1cedbc952de5232ff1fe1ae9c0c3bbfcd9087e4ed5bcd1f8c289b1456ef032d888", + "0xa48104308c4c004854008a93414eda4050cc02128a10c0a2180018b8080083c00051001300089b0410070109808", + "0x4d9f3e8aae22123e3cfefc3ffffdfffd57b5dedfbffe1dfdbc9d2fedffeff5ff9be9f2ebbfffff5bffffddbeddf8ef8db5edeef737fe8e", + "0x4d9f3e8aae22123e3cf4b42fbcf53b3d53309ed716ca09101898232ddec754f391c872ea347f7f53c3ffd8aedcc8ef0405acee87276686" + }, + { + "0x28d61d5ca1f56b4d3134009f478b17ac208a5b559d9c3726a7a16919e3b12ec6d61a142dc04d834141a9a4", + "0xb444947aba00d50e10326ebea7a2618a10144dde07c15c685d4785eae16d232eb741bc2a09b7cf794a33ed3598803ad61af", + "0xc00104a1e06a041020000445801404008050501c8c160222a16019c2a00a44d610002cc04980010121a4", + "0xb444947aba00d78f71f7eebff7b6f39b501dfdfeb7fbde68fdf7ddfbe37f6b7eb7d1be3b1bffef79eb73fd35d8b43ede9af", + "0xb444947aba00d78371e7a4a1f116b299501db9a6b6bb9e60f8f2dc33221f4954a1d022111b5ba218eb71313140b42ecc80b" + }, + { + "0x1b9a0b9c87fa234d05d06e18171cce3f8fc4adf7f75a402c4c5a281f46e714b96badab2184546aa11a7be482616cbb973da00e329628d3e692b69b43d34391884d87fcd64e2339fbb30044a370fffde97a128d1e5", + "0x7d641e556550c3ddb89ee553cbc0d8d92cdaec6519a2ff3bd792e0b309c24cb49056fb219ef4dfb2a72e76ac7df3407a44e55af5689e9c85c87e74d542dfb445f56a0a518c", + "0x78640a55655080008084a001c0405049049ac8201800462a1182a000000248b01052002108608d32212a60a43d30001804c05ac56082108588300440020fb4449520085184", + "0x1b9a0b9c87fa234d05d06e18171cce3fdfc5edf7f75e7dffcdfe7d3ffeef9dbbefafef719e7ffbbd7b7fefb2fd6cfbdf3defbe3bff6dfbeef2f7fbc7df7797ac4fd7ffd6cfebf9ffb7e74df77dfffdff7eb2ad1ed", + "0x1b9a0b9c87fa234d05d06e18171cce38598548a1a2567df7c5b47d23faea992ba6036d701e7b991c6355efb2fd4870de38cfbc2b796528cce051f1840c77962c03d25380c7caf1a734e709f75d04b9b62cb228069" + }, + { + "0x142cd4c71f04927a526ca430e542cd9432860", + "0x1337869f6c145daf15b226485ef3c48b8037bf7cb2cc9834153b90f55d4217a5e4a9ea133", + "0x142c90c41804103a106404000500c48022020", + "0x1337869f6c145daf15b226485ef3c48b8037bf7cf6cf9f34977bd2fdfd72f7e7edbdfa973", + "0x1337869f6c145daf15b226485ef3c48b8037ab50660b87308741c299f972f2e7293dd8953" + }, + { + "0x4f517f63e95a08284faaf4d4a290c334fc5d039e386727ddbb5d0a6d5fbb5540e97767023d60bedd158ed25051a6c56", + "0x9e2c9c6d2e3be2ad25733871aeba4ba64081294478f936f9c4fc45ada6bb2c098c98f21e709a88995cc3b0cf7e693f8e73f58f8f4735c81e8421182fc15426174f3b6da7b493135c", + "0x4f405a4269120008498a20c400808114cc190096200320c53b5808645318014040110200154020541186d2504120054", + "0x9e2c9c6d2e3be2ad25733871aeba4ba64081294478f936f9c4fd57ffbebfac8b8cfaff5f7abb8cbb5fc7f0ffffef7ffffbf5dfafd7fffd5e8eb77e7fe3d62fffdf7beda7b59b7f5e", + "0x9e2c9c6d2e3be2ad25733871aeba4ba64081294478f936f9c009525b982e8c8b08625d533ab384aa130660f69def4df3a8405f2992ce7d4a8ab66e5fe2822dfa9e638082b1897f0a" + }, + { + "0x1713f8f439c07e35b741ec9b0bca80149a7ef129c73c23c34b4515d29dc7dec711007fa395ced70f3bebc6d229edb75bf04231f2414e0a826f3edae4edcf770d59650cc252c6a2eff07fda9baa70938085d1e15144a451d26304d8f3df2406b8eb40f4fae3666780d2e54cd93a5f17439a4d3656dc5d48", + "0x328df4b64b0bd0fbea359666904ea4aa215b03727a70bda853b6cf612b12c3d56ee93b003bd00a7b9c1d6755f580b467deba33bf7f33da4c37fffe79e73e4381ad4bf1306d1b58f5eb276cae813d6f9153d1294c51098d37b3b80154da", + "0x108094864a0310006a219446900e20aa005201603250b00011b241400a0243144ae02900330008610c004244a080b067da9a22301300804021514420411243008843d12004184840e02260260100428140d1284c110188053210005448", + "0x1713f8f439c07e35b741ec9b0bca80149a7ef129c73c23c34b4537dffdf7dfcfd1fbffb797eed74fbfebe7db2bffff7bfdea73f6cf6f2b92effffeedffcf7fdd5b7f9cdf77d7f7eff47fdebbbbffffb3dfddf7fffefdf7fe6385fdfbff346fbbfbf5ffffefeee7bdfff55fd93b5f574b9f7fb7fedd5dda", + "0x1713f8f439c07e35b741ec9b0bca80149a7ef129c73c23c34b45275f697195ccc1fb959603a847419f41e7892a9fcd2b4dea62448e2f2190acebb40dd6cf4cdd531e90df3593576f4418042199cfecb35f9dd6aebaddb6ec208575b82e146ba3b3b51fdd8fc8e6bdbd741f081313464a177a85eedd0992" + }, + { + "0x68bc9c8f8257c6c88c0b2d46defc4539748fb906140acbf1a68820d1748bfc13ec84619f2b495d1ce74e0ca441a246497", + "0x2d30db90794c4b611858b19c973ea865904346738291751ba5fccc5cbf02c09876aca6bf23289174f545ad8039e0fbcefe359521dfc9681a7715e672fdc23cc446c7900851d2ed09568729c88bf9653c63f7e229893f31059e8b51924a54968d44e5bb26decae3159ce786d9b3a1454c6d6cb8108d22bd5111d2cc7eddb", + "0x68241c03824200880c0105068a50000854868904040a02d0828000906482d813a004400d2808100c220c0000408046493", + "0x2d30db90794c4b611858b19c973ea865904346738291751ba5fccc5cbf02c09876aca6bf23289174f545ad8039e0fbcefe359521dfc9681a7715e672fdc23cc446c7900851d2ed09568729c88bf9fdbceff7f7efc9bf3b2ddedffdd77b749fbd46f5bbefffeeeb35ddf78ffdb3edc56dff6ff95d9de7ff5db5d3ee7eddf", + "0x2d30db90794c4b611858b19c973ea865904346738291751ba5fccc5cbf02c09876aca6bf23289174f545ad8039e0fbcefe359521dfc9681a7715e672fdc23cc446c7900851d2ed09568729c88b91d9a0ec75b5ef41b33a28d855add77320193442f1b1ed2f6c6b354d930d25a04dc12df247f14d91c5f35db5936e3894c" + }, + { + "0x6eef644a36b1e052a413160909a537f81d46b2d330981f507d84737065541b5bb5faebfa8491dcd0347fbe498a501e254b91f6d82d6771a69d0aee5a490e2a44a8ba4f5da963d70b486f36f4a65f372a6a60522cac6e6a01d1a2da8743d5381", + "0x391d108a0ba169bb746b3d5816fa985288c230bdde7e3b8433f8d595b63f08a90448923f30926960cf736be42e377b087e68848af89d80d95122b942b0162153d9d665c0e3508d8a25c8862c0bb7ad4f00e4b1213326f5ce32433df12cb9", + "0x3004000a0a01280130601018127a8050080030098074038003300415003508090408800910800140cb6008a4002250081e688082701800d00020a000a004000380d4408021508482214802240332a406002080002220150a200034310081", + "0x6eeff5db3eb1fa56bfb756bbdda57ff99d6ebef33bddfff3fdc77ffd7d5f7bfbbffaeffba7f3ddf6b67fff7fbe52ff77fb97f6d86deff9fe9d9ffe7bdd2f2b66bdbfdf7ffd6ff70bd8ef7efce6dfbf7afef05e6fbe7f7a6fdde3feb7dfd7fb9", + "0x6eecf59b3e115a443fa450badc245851986e3ef03b45f8b3c5c74cfd3c0f78ab3f6aaf73a762d5f6a273497f3412fd52fb16105065c8f87e909ffc71dd252b26bd87d23bf56de20390cd6a7cc49f8c50be905c67be7d586e8d41feb49cc7f38" + }, + { + "0xa210334e6ffbec2fcfa42021075f84222c7", + "0x181b940df674ffa93b3346264fed88e40b8d8f252487bc1f2cb4c3284fa17145d2cd0c77102fc177898e53fb12c40525aeb017a57661a80a268f27b4c78cbb4bae0e96ed0065e32bc7dcb01be9cc4e6bd5db5e453e94855cb2d1d3f86e8218fe55035102fc10901add0eb539089af", + "0x821032440351002c0080000106150000087", + "0x181b940df674ffa93b3346264fed88e40b8d8f252487bc1f2cb4c3284fa17145d2cd0c77102fc177898e53fb12c40525aeb017a57661a80a268f27b4c78cbb4bae0e96ed0065e32bc7dcb01be9cc4e6bd5db5e453e94855cb2d1d3f86ea218ff5f6ffbeeffdfb43afd0fffbd2abef", + "0x181b940df674ffa93b3346264fed88e40b8d8f252487bc1f2cb4c3284fa17145d2cd0c77102fc177898e53fb12c40525aeb017a57661a80a268f27b4c78cbb4bae0e96ed0065e32bc7dcb01be9cc4e6bd5db5e453e94855cb2d1d3f86e2008cd1b6caaeed3df343afc09eabd2ab68" + }, + { + "0x2db0666cd0edeeab9e46e5b729521be3ece0714ffeefe18cd1b8b0f17e04c51b0d79fc6d428c22b9af63756", + "0x1c1d5f18453c10d365065465c676fb8b58cb436b88660a0e19c350feb1f6954caf029a43a3e59bb35ce0bdbf80a7b8ff4b4f5d7d133bd244df8813e9695b1a6af9cea293e5da9ce4f8e1035fc8ce4ca62ecbec89e89fe25053e4153899415f61c41fcb412f13b58ac70fb84077831497f", + "0x8906468c0014e888e44a426094009e08ce05043e4052088411820c01e00410b01318845028800318300156", + "0x1c1d5f18453c10d365065465c676fb8b58cb436b88660a0e19c350feb1f6954caf029a43a3e59bb35ce0bdbf80a7b8ff4b4f5d7d133bd244df8813e9695b1a6af9cea293e5ffbce6fcf1efffebde4ee7bfebfe9bebffe2715ffefff99dd1fff1f57fcfc53f1ffdfeef4fbc62ffaf77f7f", + "0x1c1d5f18453c10d365065465c676fb8b58cb436b88660a0e19c350feb1f6954caf029a43a3e59bb35ce0bdbf80a7b8ff4b4f5d7d133bd244df8813e9695b1a6af9cea293e5f72c829431eeb163500a4399e2be920b7302211c1afad91590e7d13561cf84341ecc76aa4d3462ce2c77e29" + }, + { + "0x33de1dc3fc5d6eeb5cbca27cc816a3727d1f9188400ea6b2c2799a40f7e611770b45cac7ed49fc0b66a46fcaf2393c0e03741bd08d26308fce62b0c56fbe44cb0949990bc3d4e5919ee1706dce518d6a06e865bdc26e761ef6723241b33583262bc4365103ba49dd17c0", + "0x148a80223564208532d09dd94cf189921325cad8f2a6a32568e36b2007f00866ce0c8e59034cac999f915817492737af76413832e2c4e840627b91b54766a1555e91b87b2692df16c41161184ac9a124d59aad5c06b1a61892cf5c0cd6cc628f764a161f1bdd6546cb51a1510eef5ddfbd", + "0x1121081d84c608910102048c812a222250881080006a00042480800510200240905804005492403262441083220040800601b9085062081444290806b2600cb004011010040c18104c1102d4c0081220080451c00464402867202001311812402c01001010a495d1780", + "0x148a8022356420b7fedddffd5dffebdebfa7fed8f6a7f37d7ff3eb600ff6bae6ff9eceffe75dff9bdfdbdfff49ff3feff66ffaf2fbfcee43767bd1bd6776afdf7eb1fd7fbed6df1fcd996bdbdeedb1bef5faedde57bdee1efaeffdcefefe7eff767a57bf3fdf676fcf77f153beefdddffd", + "0x148a8022356420b6eccd5e25119f62ceaf87b610e405d1587772e3600956baa4b796ceaee55ddb92da5b9ffa00db3cc9d22ef2c0dbf8e6431660413861562e9b3c217d1498d6141f8d886adb9e2c30ba34eac092573ccc1e7aaae1ceb8ba7c79047857ac2e5e436d0f67f052b4a680c87d" + }, + { + "0x683d881de1820ee9fbb71ccd74fd10e3a9ce71bd132955b9e9840d9259275498d2fae81b112416f37e9af907c319657d5d81623462b98d93818a23751a2196de6dd7c18e05960", + "0xa9a2ae43423e6c78cc59ceba6601f6d85397527c462767dceeb1ebc6ad425fb2810a2b7525", + "0xa880a002402e24688c104c300601d4d81203422800012018a2314182094046900008205120", + "0x683d881de1820ee9fbb71ccd74fd10e3a9ce71bd132955b9e9840d9259275498d2fafa3bf53437f7ff9efd9febbf657f7d857b7567fdeff7fdceeb7fbe6bd6ffffffd1aeb7d65", + "0x683d881de1820ee9fbb71ccd74fd10e3a9ce71bd132955b9e9840d9259275498d2f07231f5103515b9163c9b28bf056230045b41457defe5fc44c86ba64b42fb96ffd12cb2c45" + }, + { + "0xa827c5e2bd4293ed726065b32cac5c18d9df68b18300848f23f98c22fecd6b9fe7ed38a5adedd78f8dfe975d85c171f62b766947d7cd3d2ed3be52b50b792c0d6bb2701e28f22674a092e5ee0ec89bcd52680c6ae673a", + "0x1deac63a0a7ae71db949662f05aafcefed47a6c6dd5819dc82d250d978001903a1f19e1b8b44e76bd5899884bb97121fa13a63c33822314a486d29b59b66f141fd64af3414a3ea6bdca9b4362e704c744e8a12c1ab736636ca3aa9da4b75795f1a", + "0x202040a28c429068606045810c880c00099700018000040921b88402768d48998049382121e813860c328201048000d20b502047140d140ad30042340239080943226004004020202012a52602488388102004428471a", + "0x1deac63a0a7ae71db9496eaf7dfeffffed7ff7e6df5b3bdec7d3ddddfe8b1933a9f9fe3f9bc6efefd7b9fefefb9f5adffd7afbdff977f95e5f7f6bb7fff6fd7dfff6ef3ff5abfaffdee9f6bf2f71eeff6eef5ac9af7fe6fecbbefdfecbf7ff7f3a", + "0x1deac63a0a7ae71db9496cad79f4d73bc47971e0db032b164713dd448e8b0133a9b96c241386c887033066fa681d48c17c429b1cd157e9165f724b02fdf28c3d2eb6420ff188badc4e69628d0971aefb6ced58c8852d86da43867cfccbb3d73820" + }, + { + "0x1cc981657c8a20f5c777fc1df0e3cde0b23d434e043732dcaaa0758e009a8d1bf8591ff8db693d676eff2c39645b79c06b510ac22b1b47551eb728aa9404c24f2a6dee6bbdf2276759786f4116d21f4009dd6fb8e277976668bd021effecc797ca23682b97dbdffb93333834b8bb8fb68e922f42e3c00111", + "0x1e52f1e05fbedda88873e9984a7a19bfbfbe9ea43e30588f46317b5cadc8eb02d255875f1dde872476d05dec1164e46c7fcf3fd718fff34a80d4c6e951d10f6ae0225d00e3953e99e", + "0x61010a002b094200063608808400824b2a69ea43a10000644110254014821000015865b0c060124668050200164c4687c823682187db14a801002814181086a60200000221400110", + "0x1cc981657c8a20f5c777fc1df0e3cde0b23d434e043732dcaaa0758e009a8d1bf8591ff8db693d676eff2c39645b79c1ef7f1ec7fbffdfdd9fbfb9aeb7a5dbfffbedee6bfff7aff77b7fffcbdedebf6d2ddd7ff9fffff7676dbddedfffeec7d7fef3fd7b9ffffffb9f7f7eb5bdbbffbe8eb7ff4efbd3e99f", + "0x1cc981657c8a20f5c777fc1df0e3cde0b23d434e043732dcaaa0758e009a8d1bf8591ff8db693d676eff2c39645b79c18e7e14c7d0f69ddd9989b12e33a559b4d18404285ef7af933a6fda8bca5caf6d2c851a493f9fe52105b8dcdfe9a2815036d0955a1824eb539e7f56a1a5ab79188cb7ff4cda93e88f" + }, + { + "0xb77c8e0971a4f32bc9539c14b542ed2fa08e87560981cbdca4ccf4f7cc04fe7546a4a7eebe2592d131329fd591f66728a4179e", + "0x2fb77bc1694a8265e74ee9f41672fc681d72ea8eb65ef5807bcba4bc52ef9e381a4e4315a771497e506b734def1ca93dd519fe9e6944dd782380dff70b72798c", + "0x327c080970a08222485180108100ac02a08e0012080101842048745048004c6504a025c4182492410010180180d6670820118c", + "0x2fb77bc1694a8265e74ee9f416f7fcee1d73eeffbfdff79c7fffe6fd7fef9ebf5e4fc3dffff5cdfef7ef77ffff5eadbfffbfff9ef975fffff791fff72bf67f9e", + "0x2fb77bc1694a8265e74ee9f416c580e614034e7d9d97a61c6f7ee6517d4f10bf4c47c2de7bd5858aa7a777b39a5a0d9a3ba7db0cb875efe7f611299023d66e12" + }, + { + "0x89a0fbe80f4c622f45f4f7a15d8dc23bff17d939349f39cffa643af024db78243fc46c7948ab14ea12595e8a6cf2196ed4f353d9b1b8834b96fb61073301b99af019f042b2215e8cd5f31cf65123dab47d6b697a", + "0xc2b6f7a999af54a94c156f771b995b528", + "0x22215a8890f108944102d23039012128", + "0x89a0fbe80f4c622f45f4f7a15d8dc23bff17d939349f39cffa643af024db78243fc46c7948ab14ea12595e8a6cf2196ed4f353d9b1b8834b96fb61073301b99af019f04ebb6f7e9ddff75ef6d177fff5fdfffd7a", + "0x89a0fbe80f4c622f45f4f7a15d8dc23bff17d939349f39cffa643af024db78243fc46c7948ab14ea12595e8a6cf2196ed4f353d9b1b8834b96fb61073301b99af019f04e994e24154f06566290752dc5c4fedc52" + }, + { + "0x61cc2de53fe06a0381ce0dc4999795469453324c9036484632c257f02dddee71188198ed649bbe9ddae347178970bfbd3f1f28a787ee407a433f8473ba4fb77940227b769c9d555a8a70917ecfd038f80da4c6d5dc7211cc468c69a2275cfc119f145d2887543bbeb24", + "0x117135d192a9645062d1be59a1f8b151692159285e5877a0ae304521ad800f51fbba812d038e053cb79578c70cd34248a2b4026533bb961add83d9362893b74ce01695861c82b6f94f181feb4a957875c74cf1e7fe48dcc5196bf1214cc564f599168bf2fee1a07e617cfac992443fcdb28247", + "0x1c408050b000202018205c4811200420452124800340802200250302051ca71108010cd24008a09402243138960ad983d13208103644000411800402a4f947100223020148554508a1011648dc010900d0004c454421180408c29a20204e4118f04192003541b28204", + "0x117135d192a9645062d7bedbfffbff57e9395de8de59fff9fe794533adc90f75fffbad2d7f8eddfef795f8df8ed74bfbebfdae7573fb971bffd3f9f6aafbffece7b6b7fe5fbbb6fb7f9c1feffffdf9f5d7ecf7efffecfdc79febfb6d6ddde7f59dd6ebf6fee3f5ffe17dfbcdd2cc7fcfbbeb67", + "0x117135d192a9645062d7a29b7fab4f57c91945c88211eed9fa59001289490c357fd9ad087c8cd8e25084f0de82050bf34b69ac5142c30111265028c4a2ebc9a8e7b2a67e5bb91202388c1dccfdfcb1a092e456eee9a421c696eb2b6d2198a3d485d2e33464c3d5b1a0650b8c40cc4a8e096963" + }, + { + "0x1af3ce2ba6101f661c52430ae7280e3491d8d044a6621c3ef348c4e6e45fc6dfc91ec46b27214a9ebff52a0922fdebf1e895cd7cc4f428c64b7b3c4711b53f1f04f25b2f63ba70f281f52cb8149509f1ad38156397556eedf9e5c72388364cdba9112913", + "0x5c5811bd255dad9049ec956e6eeaa95895e56e1c5c03cbfe24ae065ac3f528fda51a966771d288dfe3aab7611232e6f6bde10cf0d97620ebde6370ab24dbdecd4d7783c05cc8579517951049f16b26cf1612f6344a669d93ac990a997dfb5180a07a75f6a20dc110fd5547e744cfe0b348cc1786d8c7f587dc83fd9e8fdb9", + "0xa00e02861011200452010885280a201010000426621c10c3088462041dc61708124429240042183c050801205169510095043044f02006434024411130091000925b25000a00a201602098100501502c30046203140cc1786584230834481b89002911", + "0x5c5811bd255dad9049ec956e6eeaa95895e56e1c5c03cbfe24ae07fffff7bafda5fef7e775f2aeffe3ebff7d9f36eef6bde3eff4dd7e6eeffe6ffcbbecdffeff5dffebff5ee8d7bfdfbf1ec9fdffeecf569ef6b7fbe6fd9bfff9fadf7dfbf7bba77f7dfff2cfc159fddf5ff7c5dff9f75eeedf9edcf7fd87fccfff9f9fdbb", + "0x5c5811bd255dad9049ec956e6eeaa95895e56e1c5c03cbfe24ae07f5ff17929ca4ecf7a255e226ad6349fe7c9f36ac909c22e3c455384eae220e8c3ac89d6cbf59de683f0e68c5bac92a0ec0adbcea80549e9283f9a2ec88ff68fad65849a7bb07755de9f0c64059adca5d34c599d9c61e22c81884b5cd04b84e470f9d4aa" + }, + { + "0xcd10bb69c381582eff7391a446db73312e738c6978564b350ca88e09cad650ef89dfb4cb00831c41d4739e957fdac00124348c91183da60b8f12dd3e349cad8b8d752fd9ea5613b1a41818032e0a2f2030790009a4fe9cdca54f96402b143e", + "0x7c4f944973a8882522976043833419c2c15b1531af1207b40092dd1e3c123a4cf06370c3111b", + "0x104d140010a888052007404202101180001801200a020030000009043c10180440024003101a", + "0xcd10bb69c381582eff7391a446db73312e738c6978564b350ca88e09cad650ef89dfb4cb00831c41d4739e957fdac00124348c91183da60b8f7edfbe7dffad8bad77bff9ebd737b9e6d95b173faf3f27b47992ddbefe9efeedfff770eb153f", + "0xcd10bb69c381582eff7391a446db73312e738c6978564b350ca88e09cad650ef89dfb4cb00831c41d4739e957fdac00124348c91183da60b8f6e92aa7def0503a857b8b9a9d527a866d943161fa53d27847992d4bac28ee6e9bff530e80525" + }, + { + "0x1cdc2579b3f1727c03a0f733c6a1a50025c8b51640ed21fb0e700f873d35c83797a14", + "0xe3e7298d39a9c7cd225125b1a01505e3d9ca63f8b494e4d7218b10e8bddc06984bbbe43e263f30f6a92a9d7", + "0x10042120110162580220f03084a085000100a0144004004b0a600e063d30c02102814", + "0xe3e7298d39a9c7cd225dfdb5f9b7f5f3fdcbe3ffb7d6e5f721afd8fdbfdcefb9fbbff43fa73f35febfbfbd7", + "0xe3e7298d39a9c7cd224df994d9a6f491a5c9c30f8752457221aed85dab9cebb9b0b59431a102053e9ebd3c3" + }, + { + "0x3ac7a7062a50d421ec7b732acfeafd988b5fe95661d371a7f2fdb5b9c1d37e304dd3a0dfcb995e9f99e1b86696b54df83fcd4e87764ffe27fbbd785875c31993f20f4628df79cbaeb50c3dfd132e20935f33ee0276c23f445dff5a075a8198907c1e248787fb28c44495d2e2ed677832432eeda5026afb91467cef4b8", + "0x12659e0b26181845981459681797ab57a50c5b4a34882e973f884d99c1e89c0457b99c9445be077039c60cffa057c608594d38423730d3eae76e8a8db6f946877e90bfecde4aaa320128ef3811cd31c3834e66fa7a61d1454778bf82781c091ae5fd348fd903d85116f83f331d84edaa925d1d65b0b30c1b7c6c69da380", + "0x20860306081044000459600287aa5580085b481400021127804d9181c0900410099080458a0150198000b820168408580d0842073043ea276a88081071420112900f44084a280200200c3811012000834e22ea0260c0054458bf0200180118807c14048103d800044015120084652812410c65a002081b104468ca080", + "0x127fdfaf263a58d5b9fc7b7b3fdfebffbd8f5feb76e9fff7bffafdbdf9e9df7e77fddfb4dfff9f7ebfdfedffe6d7f74df97ffd4eb776dffee7ffbffdfefdc79ffff2bfeefedffbfbafbdef3dfddf3fe3935f77fe7a77d37f477dffda7f5e899af5fd3eafdf87fb79d6fcbff3ffedeffab25f3fedb5b36efbfd6e7dff7b8", + "0x125f59ac20324891b9f8221b3d5841aa3d8704a362e9fde6987ab02c78294f7a67f44f349a759e2ea65fed47c6c17345a172f50cb0469c14c09537f5ee8c859eed62b0aaf695d3f9af9de305ecde1fe3101155147817137a032540d87f46888275812aab5e842379d2bcaae1ff698ad2a01e338815b166e0ed2a1535738" + }, + { + "0x39d2210d760b098917fd1293f0708ed6ffcd7686a4041e774a0f52e808524d686429da6774dd45dcf69abb4a7a48116d71f8e38074196cddf128b041a28cdc1e12cf755c7", + "0x59d65c9b948dab08f5c3604fb8b4d15085e4ae6ea8e762bbcceb904b3d9b5837977c4c9f2b9e9f3f8c6babd3b5e846ed8bdad898648bc4f8ccbea95d7a9cf5fd694e6b1a176058fbb30257aafa296741ab7181398c43a264a94972c08b4a5c56807a5f06b5b88eb420df822b43c43b400d0", + "0x284221095208080003c41080b0200c529cc5740004001a17400852a000520868202140237081018c42822008484000094058428070190495b008b00082800802000b400c0", + "0x59d65c9b948dab08f5c3604fb8b4d15085e4ae6ea8e762bbcceb904b3d9b5837977c4c9f2b9e9f3f8c6babd3b5f9d6ed8ffedb99ed9ffdfadffef9dffefffdffefee6f1e776a5ffbfb0a57effa6d6fdbef75dd7ddcf7baffeb7b7ad1ef7bfcf7807e5f6efdf9aeb461ff8eff5fd6ff755d7", + "0x59d65c9b948dab08f5c3604fb8b4d15085e4ae6ea8e762bbcceb904b3d9b5837977c4c9f2b9e9f3f8c6babd3b5d194cc86acd391ed9c39ea5f4ed9d3ac63388befea6f04602a57a95b0a05e7924d4e9bcc055c7c50b538dfe3333ad1e63ba4b5000e466a6849a604617d0ef75dd6f435517" + }, + { + "0xcf08fe64414998cc59938913e660f0f9b221f459cd8e04126cf902d0b6cea0edc26164b9d84e9ce7dfe058c1fe0fb452848616368c3", + "0x234286d14c1098ea9fd7f83508641ef3288da679fce09dd1359514ebf0dbcdc73b8f7f6171762d3d5df6492591c9386", + "0x4000910810806090d1b02100400c820000247900c094c0208500616099c84618875f6050402c0d145200041000082", + "0xcf08fe644149bbcedfd3cd13feeafffffa35fc7ddfff2c9feef9fef0bfdfb5fdd6ebf4fbddcfbfefffe179f7ff3ffdf6cda797ffbc7", + "0xcf08fe644149bb8edf42c5037e8a6f2e4a14fc3dd37d2c9fca80fe302b1f9578d68a94621589a768a08129b7d332e9a4cda387ffb45" + }, + { + "0x343e32e61b86c0c7cc895cf233ea3d5b5ad65435c1f87e034b59788a9af14ffae9249f1f3cfe0789abbe8edc8ce", + "0x63f7afb1dcebc9d65f9d468754ea558119988cb7d85e427003f2c1d9b360d2c75b97c1308ee3a7b5901044c6353e14f3e6b54a2ead64acdf914c6f7b6d4ed3205abdc78aa7bb47d548607b4ffe1db7331aac39c8bc7fcfd62238467352656a3ad04a423", + "0x241e10440b024046c00058b0038a251b42d4402041487e010311188818c00c7ac9040218047202012a3a8048002", + "0x63f7afb1dcebc9d65f9d468754ea558119988cb7d85e427003f2c1d9b360d2c75b97c1308ee3a7b5901044c6353e14f3e6b54a2ead64bcffb3ee7fffedcfdfa95efff7eabffb5fd75c75fbfffe1fff7b7aaebbf9ffffeff6bf3f7eff57edebbededecef", + "0x63f7afb1dcebc9d65f9d468754ea558119988cb7d85e427003f2c1d9b360d2c75b97c1308ee3a7b5901044c6353e14f3e6b54a2ead6498e1a3aa74fdad891fa9064ff4609ae01d031c55bab7801efc6a6226a339f38526f2bd277a8d55ecc1845e96ced" + }, + { + "0x981ba5db1da1fe952887e32cd21d51ba024022c8d837ec00f9772a111f87644012cee4a01f66d09ef168ebdfb91232e9e8f65d63ee7e6e050ae9707e7b15df4f8037b0d8d427f32429a45312a24081ed5a9c8ec22358f3621c961349638f30e049d00d513901fe065d5364f4cfca93f14a2b1b", + "0x1ba08accd8474ea8d9dc2f10d3c2c2edcbf9c3a909ab45", + "0x38000c048400c0019002e00514240e4cbc883a1082b01", + "0x981ba5db1da1fe952887e32cd21d51ba024022c8d837ec00f9772a111f87644012cee4a01f66d09ef168ebdfb91232e9e8f65d63ee7e6e050ae9707e7b15df4f8037b0d8d427f32429a45312a24081ed5a9c8ec22358f3621c9613497bafbaecd9d74ff9f9ddff16dfd3e6fdcffbd3f94bab5f", + "0x981ba5db1da1fe952887e32cd21d51ba024022c8d837ec00f9772a111f87644012cee4a01f66d09ef168ebdfb91232e9e8f65d63ee7e6e050ae9707e7b15df4f8037b0d8d427f32429a45312a24081ed5a9c8ec22358f3621c961349782fba2c919743f9e0ddd1168e91a6190433505843805e" + }, + { + "0x1d9992a4fce731fe937e70ec9efba437b1efa9e5459e3145f8c9142c6988eca9a61273750bcc1f00a64b32bab5a3a4c89858231f4fedce7a73bcc7285bbd18b328ccc298919f5511e973cd124f7e1c3912d52f4593c676f1c3f87a521", + "0x6e195204da93bdade43f0622217647326502417d70305d050d988", + "0x421810045011a921c412062200300210250001447030410008100", + "0x1d9992a4fce731fe937e70ec9efba437b1efa9e5459e3145f8c9142c6988eca9a61273750bcc1f00a64b32bab5a3a4c89858231f4fedce7a73bcc7285bbd18b328ccee99d39fdf93fdffed3f4f7e3d7f57f76f47d3ff76f1dffd7fda9", + "0x1d9992a4fce731fe937e70ec9efba437b1efa9e5459e3145f8c9142c6988eca9a61273750bcc1f00a64b32bab5a3a4c89858231f4fedce7a73bcc7285bbd18b328ccac81c39b8f8254de292d495c3d4f55e74a47d2bb06c19efd77ca9" + }, + { + "0x123b8aaf5660144d596f10574b4c232f267222596831", + "0x10ab460448ce805f18a3c1d64fc8cc0c02b2cd5f860d462e33602f09fd131e5468c86997e5a033729b2a03d3c284ee0111488ea", + "0x1021028c0600144801270012000c2028066000100820", + "0x10ab460448ce805f18a3c1d64fc8cc0c02b2cd5f860d462e33602f09fd133ffceafd6f97e5f5b7f39f7eb7d3f2f6ef2335de8fb", + "0x10ab460448ce805f18a3c1d64fc8cc0c02b2cd5f860d462e33602f09fd123decc23d0f96a175a5839e5eb711f076892334de0db" + }, + { + "0x17529608c59c36277d9e89f9b275032e62ab42b4dc006f1943e12b088c36657b02937109db797e2fbb83c984f507841be083c5e36dd04a8b7d3", + "0x1d556659e3b765044e08b1f7879bf057ef", + "0x1814004940304104080810368500a017c3", + "0x17529608c59c36277d9e89f9b275032e62ab42b4dc006f1943e12b088c36657b02937109db797e2fbbd7dfe5ff3ff65be4e3cfff7df9ff8f7ff", + "0x17529608c59c36277d9e89f9b275032e62ab42b4dc006f1943e12b088c36657b02937109db797e2fba569fe16b3cf24ba4634efc15a9f58e03c" + }, + { + "0x23ed0547893da2de2673832f9e6d988ce38c44a47495c1e0a714eb2f18ec455157cc20ea9da75cdcb0c4e9afa546efb3650b7e5cb7e659359d17fe79d2d5116bcd6c5cca45e0719d063e7df33f6788e5c6bd77c114340748cf553c5aa4992076953c4904181e24bb7c26a6e895d8b808c70133b52c9ca4a2266c2e2302bf777", + "0x3eaf5dd3cbba83558163fd16469a3d64905ff28ee65c15ff01f4d720b1ad669a893671bb614382f2331985333b0af52cbc0af22e50e4cb39d4ab3ad58127b3c481e692bb22dc0b497690e57e6fc84a87c2e1eb85e6c8bfc253fd497fc88", + "0x20aa1d83489880448123a50646922500105cb286401415170070d20011294408080241a061010232311105230800c42c340010240040cb11140a2091002691040104101a20980800268085582808420102a12884a48026400221003f400", + "0x23ed0547893da2de2673832f9e6d988ce38c44a47495c1e0a714eb2f18ec455157cc3eefddf7dffeb3d5e9effd56efbb7d6ffe5ff7eeff7d9dfffffdd7f5b1efeffeddfe75fb71df86fe7ffbbf77bbeff7bdffcbf63e57eccf7dfcfbbedda177b7fcc9e69abf26ff7f6ff6f8f5feffc8cf87f3f5ef9de6eabfee7fff4bfffff", + "0x23ed0547893da2de2673832f9e6d988ce38c44a47495c1e0a714eb2f18ec455157cc1e45c0749766339168cc5850a929586fee034568bf6988e8ff8d05f5a0c6abf6d5fc345b10de84cc4eeaba54b3ef3391cbcbe61a57ac046ce8f19e4ca15126f8c8e28aa50667776fd07870a6d7c08d86f154c719426a99ae7dde4bc0bff" + }, + { + "0x4881b1172db56487aa0b4362479871a57", + "0xd40bc374f241c2bb638ed6dea08d7885135052619d2f58523b3218b57371993a62bea6cfc8abf4abb8e4a96b0a38bbffffdd0bc5e5a6514f0db", + "0x4081210228b16487880b4160061041053", + "0xd40bc374f241c2bb638ed6dea08d7885135052619d2f58523b3218b57371993a62bea6cfc8abf4abb8eca9fb1f3dbfffffff0bc7e7e7d97fadf", + "0xd40bc374f241c2bb638ed6dea08d7885135052619d2f58523b3218b57371993a62bea6cfc8abf4abb8ac28da1d150e9b7877008687e1c93ea8c" + }, + { + "0x1e0e22b43b6de9f7ee3000e87eef492f84ee1bcd3f490cdbf35171b174335fe53afa9b752d9b1e1b0bd58d71d35687cb7b74", + "0xac57c7cfa532414e1182c7c499ffa996f7a28187f7f5d7586f0fd6b64e566bff1ff68daa60d7b650cfece99b8e2551941008aaa5ab966c526d584251600baf9f48d6b573e2779363363cea427961c0ac63d9c9abcc30976c3755b739dcbcccfbb7ae06b5deed54c59a5271caaa26134877898f75b065f3c72a8429ab5", + "0x40602140a4429948a30000876c3410b008c0bcc0f0908c0635160914411052518aa82612483181803510451105280421a34", + "0xac57c7cfa532414e1182c7c499ffa996f7a28187f7f5d7586f0fd6b64e566bff1ff68daa60d7b650cfece99b8e2551941008aaa5ab966c526d584251600baf9f48d6b573e2779363363cebe2fb6bc3beffdfffebcc3e97eef7d7ff7ffdbcdfffb7efbfb5dfff57c7bffe73efabb753d9f7e9bffdf8f7fff76afcbfbf5", + "0xac57c7cfa532414e1182c7c499ffa996f7a28187f7f5d7586f0fd6b64e566bff1ff68daa60d7b650cfece99b8e2551941008aaa5ab966c526d584251600baf9f48d6b573e2779363363ceba29b4a831abd46b748cc3e1082c3c74f773d001f0f2763b980c9f64386afac226503914191c6683fc8e8b2eef242f89e1c1" + }, + { + "0x46529c1d4b03b4a0efd29ce200ce9564cdc4fa4b53b9b6725e3fffe3454d6e53848fa573858f0bdbcf846d790a5bfc7470d0b8ac1d494804fa7048b869d5e016e389bf93cb959469dca3f4c5e93f8bcb7dbb64bcec19c8d9dbc5f2cecb285d81f5fefe99ff4564662c7cc275a40f0ea519adb2", + "0x1b10fed79bfd5e52ba14eea13cf223bfbeb5f42bd781083545c4306ed5f69250efc19707288aadf9df45b4056a293da0cfae076ee9b08e7a7058ef0a58e67149980cdc60a75825607ec4e531e9d036e71e3df52048853e3", + "0x1010d6c518485a523810e0a13cf0029790a5b4034701080041c4100045a6000086811601280889f91c01100408083d004e82002ca190864a40408c0818a4510888008440075825601ec4440060c004271a00f02040801a2", + "0x46529c1d4b03b4a0efd29ce200ce9564cdc4fa4b53b9b6725e3fffe3f54fef7bbfdfe57ba5cfebdbcfa67ffbeb5ffefd78d0bbfc5d4b4eedff796dbefdddf076ebabff9fffdfd47ffeb3fecdfbffffefffbbe7bfed9ff8fddfe7f6dfcbeddf8bf5fefe9fff4f777ebd7fee75e7df5ea599fff3", + "0x46529c1d4b03b4a0efd29ce200ce9564cdc4fa4b53b9b6725e3fffe2f442832a3b5a405824c1e1c800a65682e104bec908c03bf8410a4ee9a5196db695cc90646b23600e3fced43f7e302ec913dffd25e6b3831be997387c55a2e6574be59b8b807ca89e130b3778b17fac0447d05ca191fe51" + }, + { + "0x1c61ea1ba6135d29a669cc258f24a09ce0c6af1fa717", + "0x277557a8f45578e7730c64350cd3fd389bf96320fb3079402e9949062868fda63a6c371adf34952bd8fbf8a361671041556548ecabc7561f3febfcf26290dc819caa54b8eb26a7fb3a593202b2eb9a87fa214342ea4d639c3487882c7b6a03401d0715171c8ec44d45eff0c2571ca3f556d0d986fbeb5ff", + "0x10416008a4005408a60804218a24000c00802f1ea517", + "0x277557a8f45578e7730c64350cd3fd389bf96320fb3079402e9949062868fda63a6c371adf34952bd8fbf8a361671041556548ecabc7561f3febfcf26290dc819caa54b8eb26a7fb3a593202b2eb9a87fa214342ea4d639c3487882c7b6a03401d07d71fbdbee57dd7fff6ded75cf3ff5fdeddeefbfb7ff", + "0x277557a8f45578e7730c64350cd3fd389bf96320fb3079402e9949062868fda63a6c371adf34952bd8fbf8a361671041556548ecabc7561f3febfcf26290dc819caa54b8eb26a7fb3a593202b2eb9a87fa214342ea4d639c3487882c7b6a03401d06d309bd34a5789775965e954451bf5f1ed5ec0a112e8" + }, + { + "0x259856f9c56582b4f8056fdbd37332ff6684ad104683782087ef2b965fa2d22153ca880d735c116878afac5b2477b7f", + "0x1518494828299164e2ee455afe73cd24484df0def1e24c01926bdb2566d44e483a04bbdd5aeab159678305b6ade08cb5bc83e0e63a7bd9e2bb016c355f0fd9e94044e8e9dd380c64ea2f83d239d0987a6864dd1a07c9d742", + "0x20105268c4008210c8040e438331122b2004811040811800044e0a945380c20002c8080111080120000d80002415342", + "0x1518494828299164e2ee455afe73cd24484df0def1e24c01926bdb2566d44e483a04bbdd5aeab15967db85ffbdf6dcbfff83f6ffbf7ffbefff696ef55f6fffeb487efaf9fdfa2d66ff3fabd2fff5d97eefeeffdfb7cfff7f", + "0x1518494828299164e2ee455afe73cd24484df0def1e24c01926bdb2566d44e483a04bbdd5aeab15965da80d931b6d49ef303b61b874ceacd4d6926e45b67ee6b483a1a50b8c22146ff132b52eee5596cefee27dfb58eac3d" + }, + { + "0xd8526c4a399bb415b422ab254fb7c9a053c1507e3260aac195366c5fed9ff583053547f1b8f54561838e8d5fff273e25", + "0xdc8169197ca1b7f60394685c3438a5b9ff07c0deafe3d68064567be3d9ad3c577600e0d98c4bda37a6ed8175d437cded052bdf221c4c3d76221331061", + "0x4002480a30180400b42028044527882012c14076200008808434205a6c981501013446d010b540218082854221231021", + "0xdc8169197ca1b7f60394685c3dbda7fdff9ffbdfffe3feb274ff7ffbddbd3d57f726eafd9d5bfef7fefdff7df477ddff1fafdf761c7cfdf7fff373e65", + "0xdc8169197ca1b7f60394685c39bd837d5c9e7b9ff4a1fc3230ad0779dc9129509526ea759518bcf258347e2de46499921ea48b740474d5a3dde142e44" + }, + { + "0x47ac96c78ee0c7a9906ce5af63d0ad1b0420e1ca783cc6904ee84", + "0x630297e0f122e36f0c5f2f34efbb078c2f4c00e7c16f96cb054", + "0x20028780e002a1000c452f20c0a90304204000600046904a004", + "0x47ef96d7eef1e7ebff6cffaf77ffbf1f8c2fedcafffdef96cfed4", + "0x47cf94506e11e54aff60ba80573f161c880fadca9ffda90685ed0" + }, + { + "0x432a40ea48fcb8b8161bc19a26b544f54833bf5e005c7d1c19e8405c5464c8c139fdd9b627865e596c513fc68454827f070310dd7efe80306693ce441c89a74d91db5e27d6ba966aa1e109cc8385bd86a23d127cf609eea4118e0e1d9be83b561dcffb0ec3844d22", + "0x70d78d38ebcadb77733fc709a6d3b76576ca71acd7e3196640d6adc00225142070b943d5624a3a3d4e77a787d8221848ab06c5135", + "0x50c7880002481864410882008011b560744a212482021004401009c002211020402002c0400820214836838540001800a80044120", + "0x432a40ea48fcb8b8161bc19a26b544f54833bf5e005c7d1c19e8405c5464c8c139fdd9b627865e596c513fc68454827f070310df7ffed3befebfff773ffdf7dffdfb7e77febf9eeffff19fec8feffd86a27d527fff9dfff635afafddfffa7b7f9fefff8ef3ec5d37", + "0x432a40ea48fcb8b8161bc19a26b544f54833bf5e005c7d1c19e8405c5464c8c139fdd9b627865e596c513fc68454827f070310da738653beda3e79332f75d7d7fce02870ba1d8ca7dfd09fa88eef6186806c507bfd9dd3f2352dadc97c92432b9fee7f8473e81c17" + }, + { + "0x7c4c2d104ca2a5c080fbf1e717e47f848ff9be3555bcff60c07907ade9e334a556157dcd28ebbfd73367defdc4d8f5de60815360394e4de6e7535d356ccb8a2d896157ba65a7e8541a06e604454aef3e8cebfc7aedb48466eb65039cf17c13fcdb1b", + "0x2a73b2854f05d043d4e28e0b2634fd7023aaf3e57e58f213dd0693769", + "0x2a0100804e00404084e2880a2604ac50000262a45018c213c10681309", + "0x7c4c2d104ca2a5c080fbf1e717e47f848ff9be3555bcff60c07907ade9e334a556157dcd28ebbfd73367defdc4d8f5de60815360394e4de6e7535d356ccb8a2d896157ba65a7ef7f3a56f65d457fef3eecfbff7fffb6beefff77e79ff17dd3fdff7b", + "0x7c4c2d104ca2a5c080fbf1e717e47f848ff9be3555bcff60c07907ade9e334a556157dcd28ebbfd73367defdc4d8f5de60815360394e4de6e7535d356ccb8a2d896157ba65a54f6f325216594177a1166c599f353ab6bec9d532e613d041c395ec72" + }, + { + "0x3ee957090c3ab10e1c8af669f2093bba430a4322a741522d2ce1d20b07558298627de3dbbbef8828abc64195bad0f9f6acbb734a420d0d8dd330e90d23ab633826a612060eb95070758199006b547b24792d59f97c3191b2dee7a96e", + "0x7e30cfb7abf89648583c2f705f30abb997ded579a0de3172e2b546c920f92fbdf3bf5ffbd5d73620da518e7b4964a44505817d16c7028f4da494135d2589deffbfdb19f6a454f0431cda1884e51f48c67605f9f044e955a4f23da9dfa92af8dfba09ea6adf0390c", + "0x4e102090838a1061808e20122091028020a02228701502d2c415202050500802014424010480000284000949a4041348018114a420d018d42004904218921080600100406205010040091004b005a0478000989782090a28ce0290c", + "0x7e30cfb7abf89648583c2f73ffb5fbb9d7ffd5f9e8ff77ffe2b7ffed30fd3fbff7bf7ffbdfdf36b0ff59afff6ffebdffbff9ff9eff669f5fad9f9f7fefbffeffbfdbd9ffb75ef0d33efe3b86ef7f68e6ff95fff75cf9d5a6f77fbbdfbbffffdffb19fb6fff7b96e", + "0x7e30cfb7abf89648583c2f73b1a5db295475c598687157edc226fd6d105d1d9787aa7d291bca1690af09a7fd6eba99febb79ff9c7b669616099b8c37ee3eea5b9f0bc12b975a6091266c2b068f7e68a69d90fef71cf0c5a2477a1b983bff67487910f1473179062" + }, + { + "0x20265b43c9319cd56eac6a02cbf7913ba44b", + "0x995b92e854a8e0d548bfc02e18529b37790f0e4d9aaf36e7abc4a0f1e6d69489215aaa61b5863b1c86b3536b443dc639d1eb3db7789c2cb2f8cad1a74e5168ef33948c81a06fbad3b9ab0b7c84045cd1f77620ef43c7f2088d2901917bec5346a44f679be9491d273dbe5bf6e39095bb411cac63e38626013d671445c", + "0x20261901493010c0462c2802401390310448", + "0x995b92e854a8e0d548bfc02e18529b37790f0e4d9aaf36e7abc4a0f1e6d69489215aaa61b5863b1c86b3536b443dc639d1eb3db7789c2cb2f8cad1a74e5168ef33948c81a06fbad3b9ab0b7c84045cd1f77620ef43c7f2088d2901917bec5346a44f679be9491d273dbe5bf6e7b4bdbb59ddfeebe7a62ebf7d77be45f", + "0x995b92e854a8e0d548bfc02e18529b37790f0e4d9aaf36e7abc4a0f1e6d69489215aaa61b5863b1c86b3536b443dc639d1eb3db7789c2cb2f8cad1a74e5168ef33948c81a06fbad3b9ab0b7c84045cd1f77620ef43c7f2088d2901917bec5346a44f679be9491d273dbe59f48624a92858d1fa8925260abe4474ae017" + }, + { + "0x20a92c71c161a786989694109718416d7a291b8f9c71a5a71ee827e003a5a19cf2aa8faeecbfa231c330e2d4c747b75ccc4d43d8c37472b60", + "0xc2ba3ef844b62f020cd6e4b010499c2c28ab3c15ed2ef3114e5b806244e57be1a7d999a21399c1e950977f021c82a906bed39caeec6aa077628421f9d5dfed01b24fe857000e259537fbe07d6a83080080ae927512d4518f9a56f0a40376234855377d8ef40dcb6055bd8d351", + "0x20282071400021809096840092084045000801851471a0250a80000000a480141280018e8816a020033022404507350cc40d4340413400340", + "0xc2ba3ef844b62f020cd6e4b010499c2c28ab3c15ed2ef3114e5b806244e57be1a7d999a21399c1e950977f021c82a906bed39caeecebac77e3e5a7ffdddffd11b75fe97f7a2f3f9fbffbe5ff7eeb2fe083afb3fdf2fedfaffefff2b5c376e3dcd777ffdefc4dcbf8d7fdffb71", + "0xc2ba3ef844b62f020cd6e4b010499c2c28ab3c15ed2ef3114e5b806244e57be1a7d999a21399c1e950977f021c82a906bed39caeccc38c06a3e5867f4d4979112557a93a7a273e1aab8a45da746b2fe0830b33e9e07ede2176e95295c046c19c9270cad2384088b896c9ff831" + }, + { + "0xf6b7f399370d10b097b17e514f044d77a8f170148f4837033bb5d425f73a4079e1c7a9c3e69246f902d8c9fd27caad1e93d83578d4af8d3b7b1c02041c44917a22ed56f2562ac1426a356f8d31965e8e367b8929f3907b1dc6e73a8f3a566ca5c4e113e9d2c53770b110df51cf504701ff3fcea5b819b9bfc49f", + "0x61989df2b7097a6a84dc016aec2716d9cac359d2d799d90ec006a66efe3f1fd0851978c4cfe2f64b307b852e23f5dfdc2f63196e1076782a228a46f5f7d4e54afc1ad7abf1f8fef46edaad1706956f95eb95953bd4", + "0x990290097822808c0002c82510d08a8119521400000c40002222ec1612500001404005628401105a8426238109d0006319460032082a020804c4e110e142c41250a110d850c440420117068425900991950094", + "0xf6b7f399370d10b097b17e514f044d77a8f170148f4837033bb5d425f73a4079e1c7a9c3e6f3defdf2ffc9ff6fcefd1ffbfc377eddefcf7bfbdf9bdd1ec497fe6eff7fffd6afd97aeeffefff7bb67f8f3e7bfdffffbf7b1deef77eff3a76eee7f5f7d7eddafd3ff7bbf1ffffff7edfadff3fdfefbdfbbdbfffdf", + "0xf6b7f399370d10b097b17e514f044d77a8f170148f4837033bb5d425f73a4079e1c7a9c3e6f3de64f06fc0874d4e711ff934126e0d654e62a9cb9bdd128497dc4c1369ed86afd83aaefa8d7b7aa6250b18587cf62fbf1804a8f74cf71074e6e33116c70c98392da71ae127af3b3e9dace8395bca2df22c2aff4b" + }, + { + "0x31d126e874580b754389fad8b64aaa61cabb4f8eb6904fe7e504341ed903f7daa3e74d4da3afca80b2415672a", + "0x16fb17a0468c0afa6bad456efa4f9baf26860eda9d7c00c2520c8c9b6026fb50df59b8cb74f6d9be861052c5e831158e7ffd98746328ce11f91d9ea22f0803a8b059aea22d1715ca1abeae53a8bc6b8bfb9b6c9d24ae714767", + "0x11100e0745803440288e0189048aa20c0800a8a04904a22c10014008902e51a83c6080da1a6c880024114722", + "0x16fb17a0468c0afa6bad456efa4f9baf26860eda9d7c00c2520c8c9b6026fb50df59b8cb74f6d9be861052c5eb3d17eefffd98f77738dfbdfb7dbea63fabb7f8fb79aefe7f5757cbffbebf7faabe7fdffbbbfcbd2fae75676f", + "0x16fb17a0468c0afa6bad456efa4f9baf26860eda9d7c00c2520c8c9b6026fb50df59b8cb74f6d9be861052c5eb2c07e0f8b818c3371051bc7279340433a3b7505b30aa5c5347568bf72e912e02821f5f21a190352f8a64204d" + }, + { + "0xbf1a14e469c234b72d56324d100e016bc38cdf7158e35f230c047585e7b107acc8e222e7f19552541e59316affd90e96ca657b6112f5e8c786dfcff342fc46252fcdab10c632578540dbf6235f164bc5711924c7c6ba9da85ab", + "0x5dd3fb9a3de26cd89eb9517af6bb25678f149f906e8751a0c20d7646d21c17191237022a990e0156541e376986fd6a680c60228e5955df08bae5789c81751cdcafe5a2e72d45b09", + "0x5d5158821d220c001481413006a800620204919042041000000876400214020112210220880600564412026806252a480800020251054008b22158140145101824c582a20d00109", + "0xbf1a14e469c234b72d56324d100e016bc38cdff3fbfb7fe36cdcffbdf7fbf7bfede7aff7ff957ed75ff9f36fffdfde9edf7d7b7712fff9cf87dfdfff77fdc6fd6fedaf70e6be5fd5dfdbfee77f9ecbf57dddafe7e6ffbdedfab", + "0xbf1a14e469c234b72d56324d100e016bc38c82a2a37962c160dceb3cb6cbf117ed85adf36e053cd34ff9f367899fdc8add7c695610df71c987899bed7595c0d845a5a770e4bc0ed09fd34cc6278acab06dc58b22645db0edea2" + }, + }; + + bool opa=true, opo=true, opx=true; + + //////////////////// AND //////////////////// + + for (size_t i=0; i and + // Exponentiate(). It can easily consume all machine memory because it is an exponentiation + // without a modular reduction. + + // ****************************** DivideByZero ****************************** + + { + try { + Integer x = Integer(prng, 128) / Integer::Zero(); + result=false; + } catch (const Exception&) { + result=true; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer DivideByZero\n"; + } + + // The 0*0 % 0 test. + { + try { + Integer x = 0; + Integer y = 0; + Integer z = ModularMultiplication(y, y, x); + result = false; + } + catch(const Integer::DivideByZero&) { + result = true; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer DivideByZero\n"; + } + + // Another 0*0 % 0 test. + { + try { + Integer x = 0; + Integer y = 0; + Integer z = (y * y) % x; + result = false; + } + catch(const Integer::DivideByZero&) { + result = true; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer DivideByZero\n"; + } + + // The 0^0 % 0 test. + { + try { + Integer x = 0; + Integer y = 0; + Integer z = ModularExponentiation(y, y, x); + result = false; + } + catch(const Integer::DivideByZero&) { + result = true; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer DivideByZero\n"; + } + + // Another 0^0 % 0 test. + { + try { + Integer x = 0; + Integer y = 0; + Integer z = EuclideanDomainOf().Exponentiate(y, y) % x; + result = false; + } + catch(const Integer::DivideByZero&) { + result = true; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer DivideByZero\n"; + } + + // Integer divide by 0 + { + try { + Integer r=1, q=1, a=1, d=0; + Integer::Divide(r, q, a, d); + result = false; + } + catch(const Integer::DivideByZero&) { + result = true; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer DivideByZero\n"; + } + + // Another Integer divide by 0 + { + try { + Integer q=1, a=1; word r=1, d=0; + Integer::Divide(r, q, a, d); + result = false; + } + catch(const Integer::DivideByZero&) { + result = true; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer DivideByZero\n"; + } + + if (pass) + std::cout << "passed:"; + else + std::cout << "FAILED:"; + std::cout << " Integer DivideByZero\n"; + + // ************************ RandomNumberNotFound ************************ + + try { + // A run of 71 composites; see http://en.wikipedia.org/wiki/Prime_gap + Integer x = Integer(GlobalRNG(), 31398, 31468, Integer::PRIME); + result=false; + } catch (const Exception&) { + result=true; + } + + pass = result && pass; + if (result) + std::cout << "passed:"; + else + std::cout << "FAILED:"; + std::cout << " Integer RandomNumberNotFound\n"; + + // ************************ Carmichael pseudo-primes ************************ + + result=true; + if (IsPrime(Integer("561"))) + result = false; + if (IsPrime(Integer("41041"))) + result = false; + if (IsPrime(Integer("321197185"))) + result = false; + if (IsPrime(Integer("5394826801"))) + result = false; + if (IsPrime(Integer("232250619601"))) + result = false; + if (IsPrime(Integer("974637772161"))) + result = false; + + pass = result && pass; + if (result) + std::cout << "passed:"; + else + std::cout << "FAILED:"; + std::cout << " Carmichael pseudo-primes\n"; + + // ****************************** Integer Double ****************************** + + try { + Integer x = Integer::One().Doubled(); + result = (x == Integer::Two()); + } catch (const Exception&) { + result=false; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer Doubled\n"; + + // ****************************** Integer Square ****************************** + + try { + Integer x = Integer::Two().Squared(); + result = (x == 4); + } catch (const Exception&) { + result=false; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer Squared\n"; + + try { + Integer x = Integer::Two().Squared(); + result = (x == 4) && x.IsSquare(); + } catch (const Exception&) { + result=false; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Integer IsSquare\n"; + + if (pass) + std::cout << "passed:"; + else + std::cout << "FAILED:"; + std::cout << " Squaring operations\n"; + + // ****************************** Integer GCD ****************************** + + { + for (unsigned int i=0; i<128; ++i) + { + Integer x, y; + switch(i%2) + { + case 0: + { + AlgorithmParameters params = + MakeParameters("BitLength", 256)("RandomNumberType", Integer::PRIME); + x.GenerateRandom(prng, params); + y.GenerateRandom(prng, params); + break; + } + case 1: + { + x = MaurerProvablePrime(prng, 256); + y = MihailescuProvablePrime(prng, 256); + } + } + + if (x != y) + { + result = (RelativelyPrime(x, y) == true); + pass = result && pass; + + if (!result) + std::cout << "FAILED: Integer GCD\n"; + } + } + + if (pass) + std::cout << "passed:"; + else + std::cout << "FAILED:"; + std::cout << " GCD operations\n"; + } + + // ******************** Integer Modulo and InverseMod ******************** + + // http://github.com/weidai11/cryptopp/issues/602 + // The bug report that uncovered the InverseMod problems + { + Integer a("0x2F0500010000018000000000001C1C000000000000000A000B0000000000000000000000000000FDFFFFFF00000000"); + Integer b("0x3D2F050001"); + + result = (Integer("0x3529E4FEBC") == a.InverseMod(b)); + pass = result && pass; + if (!result) + std::cout << "FAILED: InverseMod operation\n"; + } + + // Integer Integer::InverseMod(const Integer &m) + // Large 'a' and 'm' + for (unsigned int i=0; i<128; ++i) + { + Integer a(prng, 1024), m(prng, 1024); + a++, m++; // make non-0 + + Integer x = a.InverseMod(m); + Integer y = (a % m).InverseMod(m); + Integer z = (a * y).Modulo(m); + + if (RelativelyPrime(a, m) == true) + result = (x == y) && (z == 1) && (ModularMultiplication(a, x, m) == 1); + else + result = (x == y); + + pass = result && pass; + if (!result) + std::cout << "FAILED: InverseMod operation\n"; + } + + // Integer Integer::InverseMod(const Integer &m) + // Corner cases like 0, 2m-1 and 2m+1 + for (unsigned int i=0; i<128; ++i) + { + Integer a(prng, 1024), m(prng, 1024); + a++, m++; // make non-0 + + // Corner cases + int j = i % 12; + switch (j) + { + case 0: + a = -1; break; + case 1: + a = 0; break; + case 2: + a = 1; break; + case 3: + a = m-1; break; + case 4: + a = m; break; + case 5: + a = m+1; break; + case 6: + a = 2*m-1; break; + case 7: + a = 2*m; break; + case 8: + a = 2*m+1; break; + case 9: + a = (m<<256)-1; break; + case 10: + a = (m<<256); break; + case 11: + a = (m<<256)+1; break; + default: + ; + } + + Integer x = a.InverseMod(m); + Integer y = (a % m).InverseMod(m); + Integer z = (a * y).Modulo(m); + + if (RelativelyPrime(a, m) == true) + result = (x == y) && (z == 1) && (ModularMultiplication(a, x, m) == 1); + else + result = (x == y); + + pass = result && pass; + if (!result) + std::cout << "FAILED: InverseMod operation\n"; + } + + // Integer Integer::InverseMod(const Integer &m) + // Large 'a', small 'm' + for (unsigned int i=0; i<128; ++i) + { + Integer a(prng, 4096), m(prng, 32); + a++, m++; // make non-0 + + Integer x = a.InverseMod(m); + Integer y = (a % m).InverseMod(m); + Integer z = (a * y).Modulo(m); + + if (RelativelyPrime(a, m) == true) + result = (x == y) && (z == 1) && (ModularMultiplication(a, x, m) == 1); + else + result = (x == y); + + pass = result && pass; + if (!result) + std::cout << "FAILED: InverseMod operation\n"; + } + + // Integer Integer::InverseMod(word m) + // Small 'm' using word + for (unsigned int i=0; i<128; ++i) + { + Integer a(prng, 4096); word m; + prng.GenerateBlock((byte*)&m, sizeof(m)); + + a++; // make non-0 + if (m == 0) m++; + + // Avoid the conversion from word to long + Integer mi = Integer(Integer::POSITIVE, 0, m); + Integer ri = a % Integer(Integer::POSITIVE, 0, m); + + Integer x = Integer(Integer::POSITIVE, 0, a.InverseMod(m)); + Integer y = Integer(Integer::POSITIVE, 0, ri.InverseMod(m)); + Integer z = Integer(Integer::POSITIVE, 0, (a * y).Modulo(m)); + + if (GCD(a,mi) == 1) + result = (x == y) && (z == 1); + else + result = (x == y); + + pass = result && pass; + if (!result) + std::cout << "FAILED: InverseMod operation\n"; + } + + if (pass) + std::cout << "passed:"; + else + std::cout << "FAILED:"; + std::cout << " InverseMod operations\n"; + + // ****************************** Integer Divide ****************************** + + // Divide (Integer &r, Integer &q, const Integer &a, const Integer &d) + for (unsigned int i=0; i<128; ++i) + { + Integer r, q, a(prng, 1024), d(prng, 1024); + Integer::Divide(r, q, a, d); + + Integer xr = a % d; + Integer xq = a / d; + result = (r == xr) && (q == xq); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Divide operation\n"; + } + + // Divide (word &r, Integer &q, const Integer &a, word d) + for (unsigned int i=0; i<128; ++i) + { + word r, d = prng.GenerateWord32(); + Integer q, a(prng, 1024); + Integer::Divide(r, q, a, d); + + Integer xr = a % Integer(Integer::POSITIVE, 0, d); + Integer xq = a / Integer(Integer::POSITIVE, 0, d); + result = (Integer(Integer::POSITIVE, 0, r) == xr) && (q == xq); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Divide operation\n"; + } + + if (pass) + std::cout << "passed:"; + else + std::cout << "FAILED:"; + std::cout << " Divide operations\n"; + + // ****************************** Integer Power2 ****************************** + + { + Integer x, y; + + x = Integer::Power2(0); + result = (x == 1); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Power2 operation\n"; + + x = Integer::Power2(1); + result = (x == 2); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Power2 operation\n"; + } + + for (unsigned int i=0; i<128; i+=2) + { + Integer b = 2, m(prng, 2048); + + Integer x = EuclideanDomainOf().Exponentiate(b, i) % m; + Integer y = Integer::Power2(i) % m; + result = (x == y); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Power2 operation\n"; + } + + if (pass) + std::cout << "passed:"; + else + std::cout << "FAILED:"; + std::cout << " Power2 operations\n"; + + // ****************************** Integer Exponentiation ****************************** + + { + word32 m = prng.GenerateWord32(); + if (m == 0) m++; + + Integer z = Integer::Zero(); + Integer x = ModularExponentiation(z, z, m); + Integer y = EuclideanDomainOf().Exponentiate(z, z) % m; + result = (x == y) && (x == 1); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Exponentiation operation\n"; + } + + // The 0^0 % 0 test. + { + try + { + Integer x = 0; + Integer y = ModularExponentiation(x, x, x); + result = false; + } + catch(const Integer::DivideByZero&) + { + result = true; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Exponentiation operation\n"; + } + + // Another 0^0 % 0 test. + { + try + { + Integer x = 0; + Integer z = EuclideanDomainOf().Exponentiate(0, 0) % x; + result = false; + } + catch(const Integer::DivideByZero&) + { + result = true; + } + + pass = result && pass; + if (!result) + std::cout << "FAILED: Exponentiation operation\n"; + } + + // Run the exponent 0 to 128 on base 0 + for (unsigned int i=0; i<128; i+=2) + { + Integer b = 0, m(prng, 2048); + + Integer x = ModularExponentiation(b, i, m); + Integer y = EuclideanDomainOf().Exponentiate(b, i) % m; + result = (x == y); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Exponentiation operation\n"; + } + + // Run the exponent 1 to 128 on base 2 + for (unsigned int i=0; i<128; i+=2) + { + Integer b = 1, m(prng, 2048); + + Integer x = ModularExponentiation(b, i, m); + Integer y = EuclideanDomainOf().Exponentiate(b, i) % m; + result = (x == y); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Exponentiation operation\n"; + } + + // Run the exponent 0 to 128 on base 2 + for (unsigned int i=0; i<128; i+=2) + { + Integer b = 2, m(prng, 2048); + + Integer x = ModularExponentiation(b, i, m); + Integer y = EuclideanDomainOf().Exponentiate(b, i) % m; + result = (x == y); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Exponentiation operation\n"; + } + + // Run the exponent 0 to 24 on random base + for (unsigned int i=0; i<24; ++i) + { + Integer b(prng, 32), m(prng, 2048); + + Integer x = ModularExponentiation(b, i, m); + Integer y = EuclideanDomainOf().Exponentiate(b, i) % m; + result = (x == y); + + pass = result && pass; + if (!result) + std::cout << "FAILED: Exponentiation operation\n"; + } + + if (pass) + std::cout << "passed:"; + else + std::cout << "FAILED:"; + std::cout << " Exponentiation operations\n"; + + return pass; +} +#endif + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/validat3.cpp b/external/ours/library/crypto/src/shared/original/validat3.cpp new file mode 100755 index 000000000..f941ce5c4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/validat3.cpp @@ -0,0 +1,1341 @@ +// validat3.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017. +// Source files split in July 2018 to expedite compiles. + +#include "pch.h" + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "cpu.h" +#include "validate.h" + +#include "rng.h" +#include "drbg.h" +#include "darn.h" +#include "osrng.h" +#include "rdrand.h" +#include "mersenne.h" +#include "padlkrng.h" +#include "randpool.h" + +#include "gzip.h" +#include "channels.h" + +#include +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_VER >= 1500) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +bool ValidateAll(bool thorough) +{ + bool pass=TestSettings(); + pass=TestOS_RNG() && pass; + pass=TestRandomPool() && pass; +#if !defined(NO_OS_DEPENDENCE) && defined(OS_RNG_AVAILABLE) + pass=TestAutoSeededX917() && pass; +#endif + // pass=TestSecRandom() && pass; +#if defined(CRYPTOPP_EXTENDED_VALIDATION) + pass=TestMersenne() && pass; +#endif +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + pass=TestPadlockRNG() && pass; + pass=TestRDRAND() && pass; + pass=TestRDSEED() && pass; +#endif +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) + pass=TestDARN() && pass; +#endif +#if defined(CRYPTOPP_EXTENDED_VALIDATION) + // http://github.com/weidai11/cryptopp/issues/92 + pass=TestSecBlock() && pass; + // http://github.com/weidai11/cryptopp/issues/602 + pass=TestIntegerOps() && pass; + // http://github.com/weidai11/cryptopp/issues/336 + pass=TestIntegerBitops() && pass; + // http://github.com/weidai11/cryptopp/issues/64 + pass=TestPolynomialMod2() && pass; + // http://github.com/weidai11/cryptopp/issues/360 + pass=TestRounding() && pass; + // http://github.com/weidai11/cryptopp/issues/242 + pass=TestHuffmanCodes() && pass; + // http://github.com/weidai11/cryptopp/issues/346 + pass=TestASN1Parse() && pass; + pass=TestASN1Functions() && pass; + // https://github.com/weidai11/cryptopp/pull/334 + pass=TestStringSink() && pass; + // Always part of the self tests; call in Debug +# if defined(CRYPTOPP_ALTIVEC_AVAILABLE) + pass=TestAltivecOps() && pass; +# endif + // Always part of the self tests; call in Debug + pass=ValidateBaseCode() && pass; + // https://github.com/weidai11/cryptopp/issues/562 + pass=ValidateEncoder() && pass; + // Additional tests due to no coverage + pass=TestCompressors() && pass; + pass=TestSharing() && pass; + pass=TestEncryptors() && pass; + pass=TestX25519() && pass; + pass=TestEd25519() && pass; +#endif + + pass=ValidateCRC32() && pass; + pass=ValidateCRC32C() && pass; + pass=ValidateAdler32() && pass; + pass=ValidateMD2() && pass; +#if defined(CRYPTOPP_EXTENDED_VALIDATION) + pass=ValidateMD4() && pass; +#endif + pass=ValidateMD5() && pass; + pass=ValidateSHA() && pass; + + pass=ValidateKeccak() && pass; + pass=ValidateSHA3() && pass; + pass=ValidateSHAKE() && pass; + pass=ValidateSHAKE_XOF() && pass; + + pass=ValidateLSH() && pass; + + pass=ValidateHashDRBG() && pass; + pass=ValidateHmacDRBG() && pass; + + pass=ValidateTiger() && pass; + pass=ValidateRIPEMD() && pass; + pass=ValidatePanama() && pass; + pass=ValidateWhirlpool() && pass; + + pass=ValidateSM3() && pass; + pass=ValidateBLAKE2s() && pass; + pass=ValidateBLAKE2b() && pass; + pass=ValidatePoly1305() && pass; + pass=ValidateSipHash() && pass; + + pass=ValidateHMAC() && pass; + pass=ValidateTTMAC() && pass; + + pass=ValidatePBKDF() && pass; + pass=ValidateHKDF() && pass; + pass=ValidateScrypt() && pass; + + pass=ValidateDES() && pass; + pass=ValidateCipherModes() && pass; + pass=ValidateIDEA() && pass; + pass=ValidateSAFER() && pass; + pass=ValidateRC2() && pass; + pass=ValidateARC4() && pass; + pass=ValidateRC5() && pass; + pass=ValidateBlowfish() && pass; + pass=ValidateThreeWay() && pass; + pass=ValidateGOST() && pass; + pass=ValidateSHARK() && pass; + pass=ValidateCAST() && pass; + pass=ValidateSquare() && pass; + pass=ValidateSKIPJACK() && pass; + pass=ValidateSEAL() && pass; + pass=ValidateRC6() && pass; + pass=ValidateMARS() && pass; + pass=ValidateRijndael() && pass; + pass=ValidateTwofish() && pass; + pass=ValidateSerpent() && pass; + pass=ValidateSHACAL2() && pass; + pass=ValidateARIA() && pass; + pass=ValidateCHAM() && pass; + pass=ValidateHIGHT() && pass; + pass=ValidateLEA() && pass; + pass=ValidateSIMECK() && pass; + pass=ValidateSIMON() && pass; + pass=ValidateSPECK() && pass; + pass=ValidateCamellia() && pass; + pass=ValidateSalsa() && pass; + pass=ValidateChaCha() && pass; + pass=ValidateChaChaTLS() && pass; + pass=ValidateSosemanuk() && pass; + pass=ValidateRabbit() && pass; + pass=ValidateHC128() && pass; + pass=ValidateHC256() && pass; + pass=RunTestDataFile("TestVectors/seed.txt") && pass; + pass=RunTestDataFile("TestVectors/threefish.txt") && pass; + pass=RunTestDataFile("TestVectors/kalyna.txt") && pass; + pass=RunTestDataFile("TestVectors/sm4.txt") && pass; + pass=ValidateVMAC() && pass; + pass=ValidateCCM() && pass; + pass=ValidateGCM() && pass; + pass=ValidateXTS() && pass; + pass=ValidateCMAC() && pass; + pass=RunTestDataFile("TestVectors/eax.txt") && pass; + + pass=ValidateBBS() && pass; + pass=ValidateDH() && pass; + pass=ValidateX25519() && pass; + pass=ValidateMQV() && pass; + pass=ValidateHMQV() && pass; + pass=ValidateFHMQV() && pass; + pass=ValidateRSA() && pass; + pass=ValidateElGamal() && pass; + pass=ValidateDLIES() && pass; + pass=ValidateNR() && pass; + pass=ValidateDSA(thorough) && pass; + pass=ValidateLUC() && pass; + pass=ValidateLUC_DH() && pass; + pass=ValidateLUC_DL() && pass; + pass=ValidateXTR_DH() && pass; + pass=ValidateRabin() && pass; + pass=ValidateRW() && pass; + pass=ValidateECP() && pass; + pass=ValidateEC2N() && pass; + pass=ValidateECP_Legacy_Encrypt() && pass; + pass=ValidateEC2N_Legacy_Encrypt() && pass; + pass=ValidateECDSA() && pass; + pass=ValidateECDSA_RFC6979() && pass; + pass=ValidateECGDSA(thorough) && pass; + pass=ValidateESIGN() && pass; + + pass=ValidateX25519() && pass; + pass=ValidateEd25519() && pass; + pass=ValidateNaCl() && pass; + + if (pass) + std::cout << "\nAll tests passed!\n"; + else + std::cout << "\nOops! Not all tests passed.\n"; + + return pass; +} + +bool TestSettings() +{ + bool pass = true; + + std::cout << "\nTesting Settings...\n\n"; + + word32 w; + const byte s[] = "\x01\x02\x03\x04"; + +#if (_MSC_VER >= 1400) + memcpy_s(&w, 4, s, 4); +#else + std::copy(s, s+4, reinterpret_cast(&w)); +#endif + + if (w == 0x04030201L) + { +#if (CRYPTOPP_LITTLE_ENDIAN) + std::cout << "passed: "; +#else + std::cout << "FAILED: "; + pass = false; +#endif + std::cout << "Your machine is little endian.\n"; + } + else if (w == 0x01020304L) + { +#if (CRYPTOPP_BIG_ENDIAN) + std::cout << "passed: "; +#else + std::cout << "FAILED: "; + pass = false; +#endif + std::cout << "Your machine is big endian.\n"; + } + else + { + std::cout << "FAILED: Your machine is neither big endian nor little endian.\n"; + pass = false; + } + + if (sizeof(void*) == 8) + { + std::cout << "passed: Your machine is 64-bit.\n"; + } + else if (sizeof(void*) == 4) + { + std::cout << "passed: Your machine is 32-bit.\n"; + } + else + { + std::cout << "FAILED: Your machine is neither 32-bit nor 64-bit.\n"; + pass = false; + } + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) + // App and library versions, http://github.com/weidai11/cryptopp/issues/371 + const int v1 = LibraryVersion(); + const int v2 = HeaderVersion(); + if(v1/10 == v2/10) + std::cout << "passed: "; + else + { + std::cout << "FAILED: "; + pass = false; + } + std::cout << "Library version (library): " << v1 << ", header version (app): " << v2 << "\n"; +#endif + + if (sizeof(byte) == 1) + std::cout << "passed: "; + else + { + std::cout << "FAILED: "; + pass = false; + } + std::cout << "sizeof(byte) == " << sizeof(byte) << "\n"; + + if (sizeof(word16) == 2) + std::cout << "passed: "; + else + { + std::cout << "FAILED: "; + pass = false; + } + std::cout << "sizeof(word16) == " << sizeof(word16) << "\n"; + + if (sizeof(word32) == 4) + std::cout << "passed: "; + else + { + std::cout << "FAILED: "; + pass = false; + } + std::cout << "sizeof(word32) == " << sizeof(word32) << "\n"; + + if (sizeof(word64) == 8) + std::cout << "passed: "; + else + { + std::cout << "FAILED: "; + pass = false; + } + std::cout << "sizeof(word64) == " << sizeof(word64) << "\n"; + +#ifdef CRYPTOPP_WORD128_AVAILABLE + if (sizeof(word128) == 16) + std::cout << "passed: "; + else + { + std::cout << "FAILED: "; + pass = false; + } + std::cout << "sizeof(word128) == " << sizeof(word128) << "\n"; +#endif + + if (sizeof(word) == 2*sizeof(hword) +#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + && sizeof(dword) == 2*sizeof(word) +#endif + ) + std::cout << "passed: "; + else + { + std::cout << "FAILED: "; + pass = false; + } + std::cout << "sizeof(hword) == " << sizeof(hword) << ", sizeof(word) == " << sizeof(word); +#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + std::cout << ", sizeof(dword) == " << sizeof(dword); +#endif + std::cout << "\n"; + + const int cacheLineSize = GetCacheLineSize(); + if (cacheLineSize < 16 || cacheLineSize > 256 || !IsPowerOf2(cacheLineSize)) + { + std::cout << "FAILED: "; + pass = false; + } + else + std::cout << "passed: "; + std::cout << "cacheLineSize == " << cacheLineSize << "\n"; + +#ifdef CRYPTOPP_CPUID_AVAILABLE + bool hasSSE2 = HasSSE2(); + bool hasSSSE3 = HasSSSE3(); + bool hasSSE41 = HasSSE41(); + bool hasSSE42 = HasSSE42(); + bool hasAVX = HasAVX(); + bool hasAVX2 = HasAVX2(); + bool hasAESNI = HasAESNI(); + bool hasCLMUL = HasCLMUL(); + bool hasRDRAND = HasRDRAND(); + bool hasRDSEED = HasRDSEED(); + bool hasSHA = HasSHA(); + bool isP4 = IsP4(); + + std::cout << "hasSSE2 == " << hasSSE2 << ", hasSSSE3 == " << hasSSSE3; + std::cout << ", hasSSE4.1 == " << hasSSE41 << ", hasSSE4.2 == " << hasSSE42; + std::cout << ", hasAVX == " << hasAVX << ", hasAVX2 == " << hasAVX2; + std::cout << ", hasAESNI == " << hasAESNI << ", hasCLMUL == " << hasCLMUL; + std::cout << ", hasRDRAND == " << hasRDRAND << ", hasRDSEED == " << hasRDSEED; + std::cout << ", hasSHA == " << hasSHA << ", isP4 == " << isP4; + std::cout << "\n"; + +#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8) + +# if defined(__arm__) + bool hasARMv7 = HasARMv7(); + bool hasNEON = HasNEON(); + + std::cout << "passed: "; + std::cout << "hasARMv7 == " << hasARMv7 << ", hasNEON == " << hasNEON << "\n"; +# else // __arch32__ and __aarch64__ + bool hasCRC32 = HasCRC32(); + bool hasPMULL = HasPMULL(); + bool hasAES = HasAES(); + bool hasSHA1 = HasSHA1(); + bool hasSHA2 = HasSHA2(); + bool hasSHA3 = HasSHA3(); + bool hasSHA512 = HasSHA512(); + bool hasSM3 = HasSM3(); + bool hasSM4 = HasSM4(); + + std::cout << "passed: hasASIMD == 1"; + std::cout << ", hasCRC32 == " << hasCRC32 << ", hasAES == " << hasAES; + std::cout << ", hasPMULL == " << hasPMULL << ", hasSHA1 == " << hasSHA1; + std::cout << ", hasSHA2 == " << hasSHA2 << ", hasSHA3 == " << hasSHA3; + std::cout << ", hasSHA512 == " << hasSHA512 << ", hasSM3 == " << hasSM3; + std::cout << ", hasSM4 == " << hasSM4 << "\n"; +# endif + +#elif (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) + const bool hasAltivec = HasAltivec(); + const bool hasPower7 = HasPower7(); + const bool hasPower8 = HasPower8(); + const bool hasPower9 = HasPower9(); + const bool hasAES = HasAES(); + const bool hasPMULL = HasPMULL(); + const bool hasSHA256 = HasSHA256(); + const bool hasSHA512 = HasSHA512(); + const bool hasDARN = HasDARN(); + + std::cout << "passed: "; + std::cout << "hasAltivec == " << hasAltivec << ", hasPower7 == " << hasPower7; + std::cout << ", hasPower8 == " << hasPower8 << ", hasPower9 == " << hasPower9; + std::cout << ", hasAES == " << hasAES << ", hasPMULL == " << hasPMULL; + std::cout << ", hasSHA256 == " << hasSHA256 << ", hasSHA512 == " << hasSHA512; + std::cout << ", hasDARN == " << hasDARN << "\n"; + +#endif + + if (!pass) + { + std::cerr << "Some critical setting in config.h is in error. Please fix it and recompile.\n"; + std::abort(); + } + return pass; +} + +bool Test_RandomNumberGenerator(RandomNumberGenerator& prng, bool drain=false) +{ + bool pass = true, result = true; + const size_t GENERATE_SIZE = 1024*10, DISCARD_SIZE = 256, ENTROPY_SIZE = 32; + + if(drain) + { + RandomNumberSource(prng, UINT_MAX, true, new Redirector(TheBitBucket())); + } + + MeterFilter meter(new Redirector(TheBitBucket())); + RandomNumberSource(prng, GENERATE_SIZE, true, new Deflator(new Redirector(meter))); + + if (meter.GetTotalBytes() < GENERATE_SIZE) + { + pass = false; + result = false; + } + + if (!pass) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " " << GENERATE_SIZE << " generated bytes compressed to "; + std::cout << meter.GetTotalBytes() << " bytes by DEFLATE\n"; + + try + { + pass = true; + if(prng.CanIncorporateEntropy()) + { + SecByteBlock entropy(ENTROPY_SIZE); + GlobalRNG().GenerateBlock(entropy, entropy.SizeInBytes()); + + prng.IncorporateEntropy(entropy, entropy.SizeInBytes()); + prng.IncorporateEntropy(entropy, entropy.SizeInBytes()-1); + prng.IncorporateEntropy(entropy, entropy.SizeInBytes()-2); + prng.IncorporateEntropy(entropy, entropy.SizeInBytes()-3); + } + } + catch (const Exception& /*ex*/) + { + pass = false; + result = false; + } + + if (!pass) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " IncorporateEntropy with " << 4*ENTROPY_SIZE << " bytes\n"; + + try + { + word32 val = prng.GenerateWord32(); + val = prng.GenerateWord32((val & 0xff), 0xffffffff - (val & 0xff)); + + prng.GenerateBlock(reinterpret_cast(&val), 4); + prng.GenerateBlock(reinterpret_cast(&val), 3); + prng.GenerateBlock(reinterpret_cast(&val), 2); + prng.GenerateBlock(reinterpret_cast(&val), 1); + } + catch (const Exception&) + { + pass = false; + result = false; + } + + if (!pass) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " GenerateWord32 and Crop\n"; + + try + { + pass = true; + prng.DiscardBytes(DISCARD_SIZE); + prng.DiscardBytes(DISCARD_SIZE-1); + prng.DiscardBytes(DISCARD_SIZE-2); + prng.DiscardBytes(DISCARD_SIZE-3); + } + catch (const Exception&) + { + pass = false; + result = false; + } + + if (!pass) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " DiscardBytes with " << 4*DISCARD_SIZE << " bytes\n"; + + // Miscellaneous for code coverage + (void)prng.AlgorithmName(); // "unknown" + + CRYPTOPP_ASSERT(result); + return result; +} + +bool TestOS_RNG() +{ + bool pass = true; + + member_ptr rng; + +#ifdef BLOCKING_RNG_AVAILABLE + try {rng.reset(new BlockingRng);} + catch (const OS_RNG_Err &) {} + + if (rng.get()) + { + std::cout << "\nTesting operating system provided blocking random number generator...\n\n"; + + MeterFilter meter(new Redirector(TheBitBucket())); + RandomNumberSource test(*rng, UINT_MAX, false, new Deflator(new Redirector(meter))); + unsigned long total=0; + time_t t = time(NULLPTR), t1 = 0; + + // check that it doesn't take too long to generate a reasonable amount of randomness + while (total < 16 && (t1 < 10 || total*8 > (unsigned long)t1)) + { + test.Pump(1); + total += 1; + t1 = time(NULLPTR) - t; + } + + if (total < 16) + { + std::cout << "FAILED:"; + pass = false; + } + else + std::cout << "passed:"; + std::cout << " it took " << long(t1) << " seconds to generate " << total << " bytes" << std::endl; + + test.AttachedTransformation()->MessageEnd(); + + if (meter.GetTotalBytes() < total) + { + std::cout << "FAILED:"; + pass = false; + } + else + std::cout << "passed:"; + std::cout << " " << total << " generated bytes compressed to " << meter.GetTotalBytes() << " bytes by DEFLATE\n"; + + try + { + // Miscellaneous for code coverage + RandomNumberGenerator& prng = *rng.get(); + (void)prng.AlgorithmName(); + word32 result = prng.GenerateWord32(); + result = prng.GenerateWord32((result & 0xff), 0xffffffff - (result & 0xff)); + prng.GenerateBlock(reinterpret_cast(&result), 4); + prng.GenerateBlock(reinterpret_cast(&result), 3); + prng.GenerateBlock(reinterpret_cast(&result), 2); + prng.GenerateBlock(reinterpret_cast(&result), 1); + prng.GenerateBlock(reinterpret_cast(&result), 0); + pass = true; + } + catch (const Exception&) + { + pass = false; + } + + if (!pass) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " GenerateWord32 and Crop\n"; + } + else + std::cout << "\nNo operating system provided blocking random number generator, skipping test." << std::endl; +#endif + +#ifdef NONBLOCKING_RNG_AVAILABLE + try {rng.reset(new NonblockingRng);} + catch (OS_RNG_Err &) {} + + if (rng.get()) + { + std::cout << "\nTesting operating system provided nonblocking random number generator...\n\n"; + + pass = Test_RandomNumberGenerator(*rng.get()) && pass; + } + else + std::cout << "\nNo operating system provided non-blocking random number generator, skipping test." << std::endl; +#endif + + CRYPTOPP_ASSERT(pass); + return pass; +} + +bool TestRandomPool() +{ + member_ptr prng; + bool pass=true; + + try {prng.reset(new RandomPool);} + catch (Exception &) {} + + if(prng.get()) + { + std::cout << "\nTesting RandomPool generator...\n\n"; + pass = Test_RandomNumberGenerator(*prng.get()) && pass; + } + +#if !defined(NO_OS_DEPENDENCE) && defined(OS_RNG_AVAILABLE) + try {prng.reset(new AutoSeededRandomPool);} + catch (Exception &) {} + + if(prng.get()) + { + std::cout << "\nTesting AutoSeeded RandomPool generator...\n\n"; + pass = Test_RandomNumberGenerator(*prng.get()) && pass; + } +#endif + + // Old, PGP 2.6 style RandomPool. Added because users were still having problems + // with it in 2017. The missing functionality was a barrier to upgrades. + try {prng.reset(new OldRandomPool);} + catch (Exception &) {} + + if(prng.get()) + { + std::cout << "\nTesting OldRandomPool generator...\n\n"; + pass = Test_RandomNumberGenerator(*prng.get()) && pass; + + // https://github.com/weidai11/cryptopp/issues/452 + byte actual[32], expected[32] = { + 0x41,0xD1,0xEF,0x8F,0x10,0x3C,0xE2,0x94, + 0x47,0xC0,0xC3,0x86,0x66,0xBC,0x86,0x09, + 0x57,0x77,0x73,0x91,0x57,0x4D,0x93,0x66, + 0xD1,0x13,0xE1,0xBA,0x07,0x49,0x8F,0x75 + }; + + prng.reset(new OldRandomPool); + RandomNumberGenerator& old = *prng.get(); + + SecByteBlock seed(384); + for (size_t i=0; i<384; ++i) + seed[i] = static_cast(i); + old.IncorporateEntropy(seed, seed.size()); + + old.GenerateBlock(actual, sizeof(actual)); + pass = (0 == std::memcmp(actual, expected, sizeof(expected))) && pass; + + if (!pass) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Expected sequence from PGP-style RandomPool (circa 2007)\n"; + } + + return pass; +} + +#if !defined(NO_OS_DEPENDENCE) && defined(OS_RNG_AVAILABLE) +bool TestAutoSeededX917() +{ + // This tests Auto-Seeding and GenerateIntoBufferedTransformation. + std::cout << "\nTesting AutoSeeded X917 generator...\n\n"; + + AutoSeededX917RNG prng; + return Test_RandomNumberGenerator(prng); +} +#endif + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +bool TestMersenne() +{ + std::cout << "\nTesting Mersenne Twister...\n\n"; + + member_ptr rng; + bool pass = true; + + try {rng.reset(new MT19937ar);} + catch (const Exception &) {} + + if(rng.get()) + { + pass = Test_RandomNumberGenerator(*rng.get()); + } + + // Reset state + try {rng.reset(new MT19937ar);} + catch (const Exception &) {} + + if(rng.get()) + { + // First 10; http://create.stephan-brumme.com/mersenne-twister/ + word32 result[10], expected[10] = { + 0xD091BB5C, 0x22AE9EF6, 0xE7E1FAEE, 0xD5C31F79, + 0x2082352C, 0xF807B7DF, 0xE9D30005, 0x3895AFE1, + 0xA1E24BBA, 0x4EE4092B + }; + + rng->GenerateBlock(reinterpret_cast(result), sizeof(result)); + pass = (0 == std::memcmp(result, expected, sizeof(expected))) && pass; + + if (!pass) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Expected sequence from MT19937\n"; + } + + return pass; +} +#endif + +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +bool TestPadlockRNG() +{ + std::cout << "\nTesting Padlock RNG generator...\n\n"; + + member_ptr rng; + bool pass = true, fail; + + try {rng.reset(new PadlockRNG);} + catch (const PadlockRNG_Err &) {} + + if (rng.get()) + { + PadlockRNG& padlock = dynamic_cast(*rng.get()); + pass = Test_RandomNumberGenerator(padlock); + + // PadlockRNG does not accept entropy. However, the contract is no throw + const byte entropy[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + (void)padlock.IncorporateEntropy(entropy, sizeof(entropy)); + + SecByteBlock zero(16), one(16), t(16); + std::memset(zero, 0x00, zero.size()); + std::memset( one, 0xff, one.size()); + + // Cryptography Research, Inc tests + word32 oldDivisor = padlock.SetDivisor(0); + padlock.GenerateBlock(t, t.size()); + word32 msr = padlock.GetMSR(); + padlock.SetDivisor(oldDivisor); + + // Bit 6 should be set + fail = !(msr & (1 << 6U)); + pass &= !fail; + if (fail) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " VIA RNG is activated\n"; + + // Bit 13 should be unset + fail = !!(msr & (1 << 13U)); + pass &= !fail; + if (fail) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " von Neumann corrector is activated\n"; + + // Bit 14 should be unset + fail = !!(msr & (1 << 14U)); + pass &= !fail; + if (fail) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " String filter is deactivated\n"; + + // Bit 12:10 should be unset + fail = !!(msr & (0x7 << 10U)); + pass &= !fail; + if (fail) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Bias voltage is unmodified\n"; + + fail = false; + if (t == zero || t == one) + fail = true; + + pass &= !fail; + if (fail) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " All 0's or all 1's test\n"; + } + else + std::cout << "Padlock RNG generator not available, skipping test.\n"; + + return pass; +} + +bool TestRDRAND() +{ + std::cout << "\nTesting RDRAND generator...\n\n"; + + bool pass = true; + member_ptr rng; + + try {rng.reset(new RDRAND);} + catch (const RDRAND_Err &) {} + + if (rng.get()) + { + RDRAND& rdrand = dynamic_cast(*rng.get()); + pass = Test_RandomNumberGenerator(rdrand) && pass; + + // RDRAND does not accept entropy. However, the contract is no throw + const byte entropy[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + (void)rdrand.IncorporateEntropy(entropy, sizeof(entropy)); + + MaurerRandomnessTest maurer; + const unsigned int SIZE = 1024*10; + RandomNumberSource(rdrand, SIZE, true, new Redirector(maurer)); + + CRYPTOPP_ASSERT(0 == maurer.BytesNeeded()); + const double mv = maurer.GetTestValue(); + if (mv < 0.98f) + pass = false; + + std::ostringstream oss; + oss.flags(std::ios::fixed); + oss.precision(6); + + if (!pass) + oss << "FAILED:"; + else + oss << "passed:"; + oss << " Maurer Randomness Test returned value " << mv << "\n"; + std::cout << oss.str(); + } + else + std::cout << "RDRAND generator not available, skipping test.\n"; + + return pass; +} + +bool TestRDSEED() +{ + std::cout << "\nTesting RDSEED generator...\n\n"; + + bool pass = true; + member_ptr rng; + + try {rng.reset(new RDSEED);} + catch (const RDSEED_Err &) {} + + if (rng.get()) + { + RDSEED& rdseed = dynamic_cast(*rng.get()); + pass = Test_RandomNumberGenerator(rdseed) && pass; + + // RDSEED does not accept entropy. However, the contract is no throw + const byte entropy[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + (void)rdseed.IncorporateEntropy(entropy, sizeof(entropy)); + + MaurerRandomnessTest maurer; + const unsigned int SIZE = 1024*10; + RandomNumberSource(rdseed, SIZE, true, new Redirector(maurer)); + + CRYPTOPP_ASSERT(0 == maurer.BytesNeeded()); + const double mv = maurer.GetTestValue(); + if (mv < 0.98f) + pass = false; + + std::ostringstream oss; + oss.flags(std::ios::fixed); + oss.precision(6); + + if (!pass) + oss << "FAILED:"; + else + oss << "passed:"; + oss << " Maurer Randomness Test returned value " << mv << "\n"; + std::cout << oss.str(); + } + else + std::cout << "RDSEED generator not available, skipping test.\n"; + + return pass; +} +#endif // x86, x32, or x64 + +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) +bool TestDARN() +{ + std::cout << "\nTesting DARN generator...\n\n"; + + bool pass = true; + member_ptr rng; + + try {rng.reset(new DARN);} + catch (const DARN_Err &) {} + + if (rng.get()) + { + DARN& darn = dynamic_cast(*rng.get()); + pass = Test_RandomNumberGenerator(darn) && pass; + + // DARN does not accept entropy. However, the contract is no throw + const byte entropy[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + (void)darn.IncorporateEntropy(entropy, sizeof(entropy)); + + MaurerRandomnessTest maurer; + const unsigned int SIZE = 1024*10; + RandomNumberSource(darn, SIZE, true, new Redirector(maurer)); + + CRYPTOPP_ASSERT(0 == maurer.BytesNeeded()); + const double mv = maurer.GetTestValue(); + if (mv < 0.98f) + pass = false; + + std::ostringstream oss; + oss.flags(std::ios::fixed); + oss.precision(6); + + if (!pass) + oss << "FAILED:"; + else + oss << "passed:"; + oss << " Maurer Randomness Test returned value " << mv << "\n"; + std::cout << oss.str(); + } + else + std::cout << "DARN generator not available, skipping test.\n"; + + return pass; +} +#endif // PPC32 or PPC64 + +bool ValidateHashDRBG() +{ + std::cout << "\nTesting NIST Hash DRBGs...\n\n"; + bool pass=true, fail; + + // # CAVS 14.3 + // # DRBG800-90A information for "drbg_pr" + // # Generated on Tue Apr 02 15:32:09 2013 + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 0], [AdditionalInputLen = 0], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x16\x10\xb8\x28\xcc\xd2\x7d\xe0\x8c\xee\xa0\x32\xa2\x0e\x92\x08"; + const byte entropy2[] = "\x72\xd2\x8c\x90\x8e\xda\xf9\xa4\xd1\xe5\x26\xd8\xf2\xde\xd5\x44"; + const byte nonce[] = "\x49\x2c\xf1\x70\x92\x42\xf6\xb5"; + + Hash_DRBG drbg(entropy1, 16, nonce, 8); + drbg.IncorporateEntropy(entropy2, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(result, result.size()); + drbg.GenerateBlock(result, result.size()); + + const byte expected[] = "\x56\xF3\x3D\x4F\xDB\xB9\xA5\xB6\x4D\x26\x23\x44\x97\xE9\xDC\xB8\x77\x98\xC6\x8D" + "\x08\xF7\xC4\x11\x99\xD4\xBD\xDF\x97\xEB\xBF\x6C\xB5\x55\x0E\x5D\x14\x9F\xF4\xD5" + "\xBD\x0F\x05\xF2\x5A\x69\x88\xC1\x74\x36\x39\x62\x27\x18\x4A\xF8\x4A\x56\x43\x35" + "\x65\x8E\x2F\x85\x72\xBE\xA3\x33\xEE\xE2\xAB\xFF\x22\xFF\xA6\xDE\x3E\x22\xAC\xA2"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (COUNT=0, E=16, N=8)\n"; + } + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 0], [AdditionalInputLen = 0], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x55\x08\x75\xb7\x4e\xc1\x1f\x90\x67\x78\xa3\x1a\x37\xa3\x29\xfd"; + const byte entropy2[] = "\x96\xc6\x39\xec\x14\x9f\x6b\x28\xe2\x79\x3b\xb9\x37\x9e\x60\x67"; + const byte nonce[] = "\x08\xdd\x8c\xd3\x5b\xfa\x00\x94"; + + Hash_DRBG drbg(entropy1, 16, nonce, 8); + drbg.IncorporateEntropy(entropy2, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(result, result.size()); + drbg.GenerateBlock(result, result.size()); + + const byte expected[] = "\xEE\x44\xC6\xCF\x2C\x0C\x73\xA8\xAC\x4C\xA5\x6C\x0E\x71\x2C\xA5\x50\x9A\x19\x5D" + "\xE4\x5B\x8D\x2B\xC9\x40\xA7\xDB\x66\xC3\xEB\x2A\xA1\xBD\xB4\xDD\x76\x85\x12\x45" + "\x80\x2E\x68\x05\x4A\xAB\xA8\x7C\xD6\x3A\xD3\xE5\xC9\x7C\x06\xE7\xA3\x9F\xF6\xF9" + "\x8E\xB3\xD9\x72\xD4\x11\x35\xE5\xE7\x46\x1B\x49\x9C\x56\x45\x6A\xBE\x7F\x77\xD4"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (COUNT=1, E=16, N=8)\n"; + } + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 0], [AdditionalInputLen = 128], [ReturnedBitsLen = 640] + const byte entropy1[] = "\xd9\xba\xb5\xce\xdc\xa9\x6f\x61\x78\xd6\x45\x09\xa0\xdf\xdc\x5e"; + const byte entropy2[] = "\xc6\xba\xd0\x74\xc5\x90\x67\x86\xf5\xe1\xf3\x20\x99\xf5\xb4\x91"; + const byte nonce[] = "\xda\xd8\x98\x94\x14\x45\x0e\x01"; + const byte additional1[] = "\x3e\x6b\xf4\x6f\x4d\xaa\x38\x25\xd7\x19\x4e\x69\x4e\x77\x52\xf7"; + const byte additional2[] = "\x04\xfa\x28\x95\xaa\x5a\x6f\x8c\x57\x43\x34\x3b\x80\x5e\x5e\xa4"; + const byte additional3[] = "\xdf\x5d\xc4\x59\xdf\xf0\x2a\xa2\xf0\x52\xd7\x21\xec\x60\x72\x30"; + + Hash_DRBG drbg(entropy1, 16, nonce, 8); + drbg.IncorporateEntropy(entropy2, 16, additional1, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(additional2, 16, result, result.size()); + drbg.GenerateBlock(additional3, 16, result, result.size()); + + const byte expected[] = "\xC4\x8B\x89\xF9\xDA\x3F\x74\x82\x45\x55\x5D\x5D\x03\x3B\x69\x3D\xD7\x1A\x4D\xF5" + "\x69\x02\x05\xCE\xFC\xD7\x20\x11\x3C\xC2\x4E\x09\x89\x36\xFF\x5E\x77\xB5\x41\x53" + "\x58\x70\xB3\x39\x46\x8C\xDD\x8D\x6F\xAF\x8C\x56\x16\x3A\x70\x0A\x75\xB2\x3E\x59" + "\x9B\x5A\xEC\xF1\x6F\x3B\xAF\x6D\x5F\x24\x19\x97\x1F\x24\xF4\x46\x72\x0F\xEA\xBE"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=16)\n"; + } + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 0], [AdditionalInputLen = 128], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x28\x00\x0f\xbf\xf0\x57\x22\xc8\x89\x93\x06\xc2\x9b\x50\x78\x0a"; + const byte entropy2[] = "\xd9\x95\x8e\x8c\x08\xaf\x5a\x41\x0e\x91\x9b\xdf\x40\x8e\x5a\x0a"; + const byte nonce[] = "\x11\x2f\x6e\x20\xc0\x29\xed\x3f"; + const byte additional1[] = "\x91\x1d\x96\x5b\x6e\x77\xa9\x6c\xfe\x3f\xf2\xd2\xe3\x0e\x2a\x86"; + const byte additional2[] = "\xcd\x44\xd9\x96\xab\x05\xef\xe8\x27\xd3\x65\x83\xf1\x43\x18\x2c"; + const byte additional3[] = "\x9f\x6a\x31\x82\x12\x18\x4e\x70\xaf\x5d\x00\x14\x1f\x42\x82\xf6"; + + Hash_DRBG drbg(entropy1, 16, nonce, 8); + drbg.IncorporateEntropy(entropy2, 16, additional1, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(additional2, 16, result, result.size()); + drbg.GenerateBlock(additional3, 16, result, result.size()); + + const byte expected[] = "\x54\x61\x65\x92\x1E\x71\x4A\xD1\x39\x02\x2F\x97\xD2\x65\x3F\x0D\x47\x69\xB1\x4A" + "\x3E\x6E\xEF\xA1\xA0\x16\xD6\x9E\xA9\x7F\x51\xD5\x81\xDC\xAA\xCF\x66\xF9\xB1\xE8" + "\x06\x94\x41\xD6\xB5\xC5\x44\x60\x54\x07\xE8\xE7\xDC\x1C\xD8\xE4\x70\xAD\x84\x77" + "\x5A\x65\x31\xBE\xE0\xFC\x81\x36\xE2\x8F\x0B\xFE\xEB\xE1\x98\x62\x7E\x98\xE0\xC1"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=16)\n"; + } + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 128], [AdditionalInputLen = 0], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x0e\xd5\x4c\xef\x44\x5c\x61\x7d\x58\x86\xe0\x34\xc0\x97\x36\xd4"; + const byte entropy2[] = "\x0b\x90\x27\xb8\x01\xe7\xf7\x2e\xe6\xec\x50\x2b\x8b\x6b\xd7\x11"; + const byte nonce[] = "\x2c\x8b\x07\x13\x55\x6c\x91\x6f"; + const byte personalization[] = "\xf3\x37\x8e\xa1\x45\x34\x30\x41\x12\xe0\xee\x57\xe9\xb3\x4a\x4b"; + + Hash_DRBG drbg(entropy1, 16, nonce, 8, personalization, 16); + drbg.IncorporateEntropy(entropy2, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(result, result.size()); + drbg.GenerateBlock(result, result.size()); + + const byte expected[] = "\x55\x37\x0E\xD4\xB7\xCA\xA4\xBB\x67\x3A\x0F\x58\x40\xB3\x9F\x76\x4E\xDA\xD2\x85" + "\xD5\x6F\x01\x8F\x2D\xA7\x54\x4B\x0E\x66\x39\x62\x35\x96\x1D\xB7\xF6\xDA\xFB\x30" + "\xB6\xC5\x68\xD8\x40\x6E\x2B\xD4\x3D\x23\xEB\x0F\x10\xBA\x5F\x24\x9C\xC9\xE9\x4A" + "\xD3\xA5\xF1\xDF\xA4\xF2\xB4\x80\x40\x91\xED\x8C\xD6\x6D\xE7\xB7\x53\xB2\x09\xD5"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=0, P=16)\n"; + } + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 128], [AdditionalInputLen = 0], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x8f\x2a\x33\x9f\x5f\x45\x21\x30\xa4\x57\xa9\x6f\xcb\xe2\xe6\x36"; + const byte entropy2[] = "\x1f\xff\x9e\x4f\x4d\x66\x3a\x1f\x9e\x85\x4a\x15\x7d\xad\x97\xe0"; + const byte nonce[] = "\x0e\xd0\xe9\xa5\xa4\x54\x8a\xd0"; + const byte personalization[] = "\x45\xe4\xb3\xe2\x63\x87\x62\x57\x2c\x99\xe4\x03\x45\xd6\x32\x6f"; + + Hash_DRBG drbg(entropy1, 16, nonce, 8, personalization, 16); + drbg.IncorporateEntropy(entropy2, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(result, result.size()); + drbg.GenerateBlock(result, result.size()); + + const byte expected[] = "\x4F\xE8\x96\x41\xF8\xD3\x95\xC4\x43\x6E\xFB\xF8\x05\x75\xA7\x69\x74\x6E\x0C\x5F" + "\x54\x14\x35\xB4\xE6\xA6\xB3\x40\x7C\xA2\xC4\x42\xA2\x2F\x66\x28\x28\xCF\x4A\xA8" + "\xDC\x16\xBC\x5F\x69\xE5\xBB\x05\xD1\x43\x8F\x80\xAB\xC5\x8F\x9C\x3F\x75\x57\xEB" + "\x44\x0D\xF5\x0C\xF4\x95\x23\x94\x67\x11\x55\x98\x14\x43\xFF\x13\x14\x85\x5A\xBC"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=0, P=16)\n"; + } + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 128], [AdditionalInputLen = 16], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x48\xa1\xa9\x7c\xcc\x49\xd7\xcc\xf6\xe3\x78\xa2\xf1\x6b\x0f\xcd"; + const byte entropy2[] = "\xba\x5d\xa6\x79\x12\x37\x24\x3f\xea\x60\x50\xf5\xb9\x9e\xcd\xf5"; + const byte nonce[] = "\xb0\x91\xd2\xec\x12\xa8\x39\xfe"; + const byte personalization[] = "\x3d\xc1\x6c\x1a\xdd\x9c\xac\x4e\xbb\xb0\xb8\x89\xe4\x3b\x9e\x12"; + const byte additional1[] = "\xd1\x23\xe3\x8e\x4c\x97\xe8\x29\x94\xa9\x71\x7a\xc6\xf1\x7c\x08"; + const byte additional2[] = "\x80\x0b\xed\x97\x29\xcf\xad\xe6\x68\x0d\xfe\x53\xba\x0c\x1e\x28"; + const byte additional3[] = "\x25\x1e\x66\xb9\xe3\x85\xac\x1c\x17\xfb\x77\x1b\x5d\xc7\x6c\xf2"; + + Hash_DRBG drbg(entropy1, 16, nonce, 8, personalization, 16); + drbg.IncorporateEntropy(entropy2, 16, additional1, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(additional2, 16, result, result.size()); + drbg.GenerateBlock(additional3, 16, result, result.size()); + + const byte expected[] = "\xA1\xB2\xEE\x86\xA0\xF1\xDA\xB7\x93\x83\x13\x3A\x62\x27\x99\x08\x95\x3A\x1C\x9A" + "\x98\x77\x60\x12\x11\x19\xCC\x78\xB8\x51\x2B\xD5\x37\xA1\x9D\xB9\x73\xCA\x39\x7A" + "\xDD\x92\x33\x78\x6D\x5D\x41\xFF\xFA\xE9\x80\x59\x04\x85\x21\xE2\x52\x84\xBC\x6F" + "\xDB\x97\xF3\x4E\x6A\x12\x7A\xCD\x41\x0F\x50\x68\x28\x46\xBE\x56\x9E\x9A\x6B\xC8"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=16, P=16)\n"; + } + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 128], [AdditionalInputLen = 16], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x3b\xcb\xa8\x3b\x6d\xfb\x06\x79\x80\xef\xc3\x1e\xd2\x9e\x68\x57"; + const byte entropy2[] = "\x2f\xc9\x87\x49\x19\xcb\x52\x4a\x5b\xac\xf0\xcd\x96\x4e\xf8\x6e"; + const byte nonce[] = "\x23\xfe\x20\x9f\xac\x70\x45\xde"; + const byte personalization[] = "\xf2\x25\xf4\xd9\x6b\x9c\xab\x49\x1e\xab\x18\x14\xb2\x5e\x78\xef"; + const byte additional1[] = "\x57\x5b\x9a\x11\x32\x7a\xab\x89\x08\xfe\x46\x11\x9a\xed\x14\x5d"; + const byte additional2[] = "\x5d\x19\xcd\xed\xb7\xe3\x44\x66\x8e\x11\x42\x96\xa0\x38\xb1\x7f"; + const byte additional3[] = "\x2b\xaf\xa0\x15\xed\xdd\x5c\x76\x32\x75\x34\x35\xd1\x37\x72\xfb"; + + Hash_DRBG drbg(entropy1, 16, nonce, 8, personalization, 16); + drbg.IncorporateEntropy(entropy2, 16, additional1, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(additional2, 16, result, result.size()); + drbg.GenerateBlock(additional3, 16, result, result.size()); + + const byte expected[] = "\x1D\x12\xEB\x6D\x42\x60\xBD\xFB\xA7\x99\xB8\x53\xCC\x6F\x19\xB1\x64\xFE\x2F\x55" + "\xBA\xA2\x1C\x89\xD4\xD0\xE9\xB4\xBA\xD4\xE5\xF8\xC5\x30\x06\x41\xBA\xC4\x3D\x2B" + "\x73\x91\x27\xE9\x31\xC0\x55\x55\x11\xE8\xB6\x57\x02\x0D\xCE\x90\xAC\x31\xB9\x00" + "\x31\xC1\xD4\x4F\xE7\x12\x3B\xCC\x85\x16\x2F\x12\x8F\xB2\xDF\x84\x4E\xF7\x06\xBE"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=16, P=16)\n"; + } + + { + // [SHA-256], [PredictionResistance = False], [EntropyInputLen = 256], [NonceLen = 128] + // [PersonalizationStringLen = 256], [AdditionalInputLen = 256], [ReturnedBitsLen = 1024] + const byte entropy1[] = "\xf0\x5b\xab\x56\xc7\xac\x6e\xeb\x31\xa0\xcf\x8a\x8a\x06\x2a\x49\x17\x9a\xcf\x3c\x5b\x20\x4d\x60\xdd\x7a\x3e\xb7\x8f\x5d\x8e\x3b"; + const byte entropy2[] = "\x72\xd4\x02\xa2\x59\x7b\x98\xa3\xb8\xf5\x0b\x71\x6c\x63\xc6\xdb\xa7\x3a\x07\xe6\x54\x89\x06\x3f\x02\xc5\x32\xf5\xda\xc4\xd4\x18"; + const byte nonce[] = "\xa1\x45\x08\x53\x41\x68\xb6\x88\xf0\x5f\x1e\x41\x9c\x88\xcc\x30"; + const byte personalization[] = "\xa0\x34\x72\xf4\x04\x59\xe2\x87\xea\xcb\x21\x32\xc0\xb6\x54\x02\x7d\xa3\xe6\x69\x25\xb4\x21\x25\x54\xc4\x48\x18\x8c\x0e\x86\x01"; + const byte additional1[] = "\xb3\x0d\x28\xaf\xa4\x11\x6b\xbc\x13\x6e\x65\x09\xb5\x82\xa6\x93\xbc\x91\x71\x40\x46\xaa\x3c\x66\xb6\x77\xb3\xef\xf9\xad\xfd\x49"; + const byte additional2[] = "\x77\xfd\x1d\x68\xd6\xa4\xdd\xd5\xf3\x27\x25\x2d\x3f\x6b\xdf\xee\x8c\x35\xce\xd3\x83\xbe\xaf\xc9\x32\x77\xef\xf2\x1b\x6f\xf4\x1b"; + const byte additional3[] = "\x59\xa0\x1f\xf8\x6a\x58\x72\x1e\x85\xd2\xf8\x3f\x73\x99\xf1\x96\x4e\x27\xf8\x7f\xcd\x1b\xf5\xc1\xeb\xf3\x37\x10\x9b\x13\xbd\x24"; + + Hash_DRBG drbg(entropy1, 32, nonce, 16, personalization, 32); + drbg.IncorporateEntropy(entropy2, 32, additional1, 32); + + SecByteBlock result(128); + drbg.GenerateBlock(additional2, 32, result, result.size()); + drbg.GenerateBlock(additional3, 32, result, result.size()); + + const byte expected[] = "\xFF\x27\x96\x38\x5C\x32\xBF\x84\x3D\xFA\xBB\xF0\x3E\x70\x5A\x39\xCB\xA3\x4C\xF1" + "\x4F\xAE\xC3\x05\x63\xDF\x5A\xDD\xBD\x2D\x35\x83\xF5\x7E\x05\xF9\x40\x30\x56\x18" + "\xF2\x00\x88\x14\x03\xC2\xD9\x81\x36\x39\xE6\x67\x55\xDC\xFC\x4E\x88\xEA\x71\xDD" + "\xB2\x25\x2E\x09\x91\x49\x40\xEB\xE2\x3D\x63\x44\xA0\xF4\xDB\x5E\xE8\x39\xE6\x70" + "\xEC\x47\x24\x3F\xA0\xFC\xF5\x13\x61\xCE\x53\x98\xAA\xBF\xB4\x19\x1B\xFE\xD5\x00" + "\xE1\x03\x3A\x76\x54\xFF\xD7\x24\x70\x5E\x8C\xB2\x41\x7D\x92\x0A\x2F\x4F\x27\xB8" + "\x45\x13\x7F\xFB\x87\x90\xA9\x49"; + + fail = !!memcmp(result, expected, 1024/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA256/128/440 (C0UNT=0, E=32, N=16, A=32, P=32)\n"; + } + + { + // [SHA-256], [PredictionResistance = False], [EntropyInputLen = 256], [NonceLen = 128] + // [PersonalizationStringLen = 256], [AdditionalInputLen = 256], [ReturnedBitsLen = 1024] + const byte entropy1[] = "\xfe\x61\x50\x79\xf1\xad\x2a\x71\xea\x7f\x0f\x5a\x14\x34\xee\xc8\x46\x35\x54\x4a\x95\x6a\x4f\xbd\x64\xff\xba\xf6\x1d\x34\x61\x83"; + const byte entropy2[] = "\x18\x89\x7b\xd8\x3e\xff\x38\xab\xb5\x6e\x82\xa8\x1b\x8c\x5e\x59\x3c\x3d\x85\x62\x2a\xe2\x88\xe5\xb2\xc6\xc5\xd2\xad\x7d\xc9\x45"; + const byte nonce[] = "\x9d\xa7\x87\x56\xb7\x49\x17\x02\x4c\xd2\x00\x65\x11\x9b\xe8\x7e"; + const byte personalization[] = "\x77\x5d\xbf\x32\xf3\x5c\xf3\x51\xf4\xb8\x1c\xd3\xfa\x7f\x65\x0b\xcf\x31\x88\xa1\x25\x57\x0c\xdd\xac\xaa\xfe\xa1\x7b\x3b\x29\xbc"; + const byte additional1[] = "\xef\x96\xc7\x9c\xb1\x73\x1d\x82\x85\x0a\x6b\xca\x9b\x5c\x34\x39\xba\xd3\x4e\x4d\x82\x6f\x35\x9f\x61\x5c\xf6\xf2\xa3\x3e\x91\x05"; + const byte additional2[] = "\xaf\x25\xc4\x6e\x21\xfc\xc3\xaf\x1f\xbb\xf8\x76\xb4\x57\xab\x1a\x94\x0a\x85\x16\x47\x81\xa4\xab\xda\xc8\xab\xca\xd0\x84\xda\xae"; + const byte additional3[] = "\x59\x5b\x44\x94\x38\x86\x36\xff\x8e\x45\x1a\x0c\x42\xc8\xcc\x21\x06\x38\x3a\xc5\xa6\x30\x96\xb9\x14\x81\xb3\xa1\x2b\xc8\xcd\xf6"; + + Hash_DRBG drbg(entropy1, 32, nonce, 16, personalization, 32); + drbg.IncorporateEntropy(entropy2, 32, additional1, 32); + + SecByteBlock result(128); + drbg.GenerateBlock(additional2, 32, result, result.size()); + drbg.GenerateBlock(additional3, 32, result, result.size()); + + const byte expected[] = "\x8B\x1C\x9C\x76\xC4\x9B\x3B\xAE\xFD\x6E\xEB\x6C\xFF\xA3\xA1\x03\x3A\x8C\xAF\x09" + "\xFE\xBD\x44\x00\xFC\x0F\xD3\xA8\x26\x9C\xEE\x01\xAC\xE3\x73\x0E\xBE\xDA\x9A\xC6" + "\x23\x44\x6D\xA1\x56\x94\x29\xEC\x4B\xCD\x01\x84\x32\x25\xEF\x00\x91\x0B\xCC\xF3" + "\x06\x3B\x80\xF5\x46\xAC\xD2\xED\x5F\x70\x2B\x56\x2F\x21\x0A\xE9\x80\x87\x38\xAD" + "\xB0\x2A\xEB\x27\xF2\xD9\x20\x2A\x66\x0E\xF5\xC9\x20\x4A\xB4\x3C\xCE\xD6\x24\x97" + "\xDB\xB1\xED\x94\x12\x6A\x2F\x03\x98\x4A\xD4\xD1\x72\xF3\x7A\x66\x74\x7E\x2A\x5B" + "\xDE\xEF\x43\xBC\xB9\x8C\x49\x01"; + + fail = !!memcmp(result, expected, 1024/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA256/128/440 (C0UNT=1, E=32, N=16, A=32, P=32)\n"; + } + + { + // [SHA-512], [PredictionResistance = False], [EntropyInputLen = 256], [NonceLen = 128] + // [PersonalizationStringLen = 256], [AdditionalInputLen = 256], [ReturnedBitsLen = 2048] + const byte entropy1[] = "\x55\x4e\x8f\xfd\xc4\x9a\xd8\xf9\x9a\xe5\xd5\xf8\x1a\xf5\xda\xfb\x7f\x75\x53\xd7\xcb\x56\x8e\xa7\x3c\xc0\x82\xdd\x80\x76\x25\xc0"; + const byte entropy2[] = "\x78\x07\x3e\x86\x79\x4b\x10\x95\x88\xf4\x22\xf9\xbd\x04\x7e\xc0\xce\xab\xd6\x78\x6b\xdf\xe2\x89\xb3\x16\x43\x9c\x32\x2d\xb2\x59"; + const byte nonce[] = "\xf0\x89\x78\xde\x2d\xc2\xcd\xd9\xc0\xfd\x3d\x84\xd9\x8b\x8e\x8e"; + const byte personalization[] = "\x3e\x52\x7a\xb5\x81\x2b\x0c\x0e\x98\x2a\x95\x78\x93\x98\xd9\xeb\xf1\xb9\xeb\xd6\x1d\x02\x05\xed\x42\x21\x2d\x24\xb8\x37\xf8\x41"; + const byte additional1[] = "\xf2\x6b\xb1\xef\x30\xca\x8f\x97\xc0\x19\xd0\x79\xe5\xc6\x5e\xae\xd1\xa3\x9a\x52\xaf\x12\xe8\x28\xde\x03\x70\x79\x9a\x70\x11\x8b"; + const byte additional2[] = "\xb0\x9d\xb5\xa8\x45\xec\x79\x7a\x4b\x60\x7e\xe4\xd5\x58\x56\x70\x35\x20\x9b\xd8\xe5\x01\x6c\x78\xff\x1f\x6b\x93\xbf\x7c\x34\xca"; + const byte additional3[] = "\x45\x92\x2f\xb3\x5a\xd0\x6a\x84\x5f\xc9\xca\x16\x4a\x42\xbb\x59\x84\xb4\x38\x57\xa9\x16\x23\x48\xf0\x2f\x51\x61\x24\x35\xb8\x62"; + + Hash_DRBG drbg(entropy1, 32, nonce, 16, personalization, 32); + drbg.IncorporateEntropy(entropy2, 32, additional1, 32); + + SecByteBlock result(256); + drbg.GenerateBlock(additional2, 32, result, result.size()); + drbg.GenerateBlock(additional3, 32, result, result.size()); + + const byte expected[] = "\x1F\x20\x83\x9E\x22\x55\x3B\x1E\x6C\xD4\xF6\x3A\x47\xC3\x99\x54\x0F\x69\xA3\xBB" + "\x37\x47\xA0\x2A\x12\xAC\xC7\x00\x85\xC5\xCC\xF4\x7B\x12\x5A\x4A\xEA\xED\x2F\xE5" + "\x31\x51\x0D\xC1\x8E\x50\x29\xE2\xA6\xCB\x8F\x34\xBA\xDA\x8B\x47\x32\x33\x81\xF1" + "\x2D\xF6\x8B\x73\x8C\xFF\x15\xC8\x8E\x8C\x31\x48\xFA\xC3\xC4\x9F\x52\x81\x23\xC2" + "\x2A\x83\xBD\xF1\x44\xEF\x15\x49\x93\x44\x83\x6B\x37\x5D\xBB\xFF\x72\xD2\x86\x96" + "\x62\xF8\x4D\x12\x3B\x16\xCB\xAC\xA1\x00\x12\x1F\x94\xA8\xD5\xAE\x9A\x9E\xDA\xC8" + "\xD7\x6D\x59\x33\xFD\x55\xC9\xCC\x5B\xAD\x39\x73\xB5\x13\x8B\x96\xDF\xDB\xF5\x90" + "\x81\xDF\x68\x6A\x30\x72\x42\xF2\x74\xAE\x7F\x1F\x7F\xFE\x8B\x3D\x49\x38\x98\x34" + "\x7C\x63\x46\x6E\xAF\xFA\xCB\x06\x06\x08\xE6\xC8\x35\x3C\x68\xB8\xCC\x9D\x5C\xDF" + "\xDB\xC0\x41\x44\x48\xE6\x11\xD4\x78\x50\x81\x91\xED\x1D\x75\xF3\xBD\x79\xFF\x1E" + "\x37\xAF\xC6\x5D\x49\xD6\x5C\xAC\x5B\xCB\xD6\x91\x37\x51\xFA\x98\x70\xFC\x32\xB3" + "\xF2\x86\xE4\xED\x74\xF2\x5D\x8B\x6C\x4D\xB8\xDE\xD8\x4A\xD6\x5E\xD6\x6D\xAE\xB1" + "\x1B\xA2\x94\x52\x54\xAD\x3C\x3D\x25\xBD\x12\x46\x3C\xA0\x45\x9D"; + + fail = !!memcmp(result, expected, 2048/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA512/256/888 (C0UNT=0, E=32, N=16, A=32, P=32)\n"; + } + + { + // [SHA-512], [PredictionResistance = False], [EntropyInputLen = 256], [NonceLen = 128] + // [PersonalizationStringLen = 256], [AdditionalInputLen = 256], [ReturnedBitsLen = 2048] + const byte entropy1[] = "\x0c\x9f\xcd\x06\x21\x3c\xb2\xf6\x3c\xdf\x79\x76\x4b\x46\x74\xfc\xdf\x68\xb0\xff\xae\xc7\x21\x8a\xa2\xaf\x4e\x4c\xb9\xe6\x60\x78"; + const byte entropy2[] = "\x75\xb8\x49\x54\xdf\x30\x10\x16\x2c\x06\x8c\x12\xeb\x6c\x1d\x03\x64\x5c\xad\x10\x5c\xc3\x17\x69\xb2\x5a\xc1\x7c\xb8\x33\x5b\x45"; + const byte nonce[] = "\x43\x1c\x4d\x65\x93\x96\xad\xdc\xc1\x6d\x17\x9f\x7f\x57\x24\x4d"; + const byte personalization[] = "\x7e\x54\xbd\x87\xd2\x0a\x95\xd7\xc4\x0c\x3b\x1b\x32\x15\x26\xd2\x06\x67\xa4\xac\xc1\xaa\xfb\x55\x91\x68\x2c\xb5\xc9\xcd\x66\x05"; + const byte additional1[] = "\xd5\x74\x9e\x56\xfb\x5f\xf3\xf8\x2c\x73\x2b\x7a\x83\xe0\xde\x06\x85\x0b\xf0\x57\x50\xc8\x55\x60\x4a\x41\x4f\x86\xb1\x68\x14\x03"; + const byte additional2[] = "\x9a\x83\xbb\x06\xdf\x4d\x53\x89\xf5\x3f\x24\xff\xf7\xcd\x0c\xcf\x4f\xbe\x46\x79\x8e\xce\x82\xa8\xc4\x6b\x5f\x8e\x58\x32\x62\x23"; + const byte additional3[] = "\x48\x13\xc4\x95\x10\x99\xdd\x7f\xd4\x77\x3c\x9b\x8a\xa4\x1c\x3d\xb0\x93\x92\x50\xba\x23\x98\xef\x4b\x1b\xd2\x53\xc1\x61\xda\xc6"; + + Hash_DRBG drbg(entropy1, 32, nonce, 16, personalization, 32); + drbg.IncorporateEntropy(entropy2, 32, additional1, 32); + + SecByteBlock result(256); + drbg.GenerateBlock(additional2, 32, result, result.size()); + drbg.GenerateBlock(additional3, 32, result, result.size()); + + const byte expected[] = "\xE1\x7E\x4B\xEE\xD1\x65\x4F\xB2\xFC\xC8\xE8\xD7\xC6\x72\x7D\xD2\xE3\x15\x73\xC0" + "\x23\xC8\x55\x5D\x2B\xD8\x28\xD8\x31\xE4\xC9\x87\x42\x51\x87\x66\x43\x1F\x2C\xA4" + "\x73\xED\x4E\x50\x12\xC4\x50\x0E\x4C\xDD\x14\x73\xA2\xFB\xB3\x07\x0C\x66\x97\x4D" + "\x89\xDE\x35\x1C\x93\xE7\xE6\x8F\x20\x3D\x84\xE6\x73\x46\x0F\x7C\xF4\x3B\x6C\x02" + "\x23\x7C\x79\x6C\x86\xD9\x48\x80\x9C\x34\xCB\xA1\x23\xE7\xF7\x8A\x2E\x4B\x9D\x39" + "\xA5\x86\x1A\x73\x58\x28\x5A\x1D\x8D\x4A\xBD\x42\xD5\x49\x2B\xDF\x53\x1D\xE7\x4A" + "\x5F\x74\x09\x7F\xDC\x29\x7D\x58\x9C\x4B\xC5\x2F\x3B\x8F\xBF\x56\xCA\x48\x0A\x74" + "\xAE\xFF\xDD\x12\xE4\xF6\xAB\x83\x26\x4F\x52\x8A\x19\xBB\x91\x32\xA4\x42\xEC\x4F" + "\x3C\x76\xED\x9F\x03\xAA\x5E\x53\x79\x4C\xD0\x06\xD2\x1A\x42\x9D\xB1\xA7\xEC\xF7" + "\x5B\xD4\x03\x70\x1E\xF2\x47\x26\x48\xAC\x35\xEE\xD0\x58\x40\x94\x8C\x11\xD0\xEB" + "\x77\x39\x5A\xA3\xD5\xD0\xD3\xC3\x68\xE1\x75\xAA\xC0\x44\xEA\xD8\xDD\x13\x3F\xF9" + "\x7D\x21\x14\x34\xA5\x87\x43\xA4\x0A\x96\x77\x00\xCC\xCA\xB1\xDA\xC4\x39\xE0\x66" + "\x37\x05\x6E\xAC\xF2\xE6\xC6\xC5\x4F\x79\xD3\xE5\x6A\x3D\x36\x3F"; + + fail = !!memcmp(result, expected, 2048/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA512/256/888 (C0UNT=1, E=32, N=16, A=32, P=32)\n"; + } + + return pass; +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/validat4.cpp b/external/ours/library/crypto/src/shared/original/validat4.cpp new file mode 100755 index 000000000..e41c1c8b1 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/validat4.cpp @@ -0,0 +1,1813 @@ +// validat4.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017. +// Source files split in July 2018 to expedite compiles. + +#include "pch.h" + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "cpu.h" +#include "validate.h" + +#include "hex.h" +#include "base32.h" +#include "base64.h" + +#include "rc2.h" +#include "aes.h" +#include "des.h" +#include "rc5.h" +#include "rc6.h" +#include "3way.h" +#include "aria.h" +#include "cast.h" +#include "mars.h" +#include "idea.h" +#include "gost.h" +#include "seal.h" +#include "seed.h" +#include "safer.h" +#include "shark.h" +#include "square.h" +#include "serpent.h" +#include "shacal2.h" +#include "twofish.h" +#include "blowfish.h" +#include "camellia.h" +#include "skipjack.h" + +#include "arc4.h" +#include "salsa.h" +#include "chacha.h" +#include "rabbit.h" +#include "sosemanuk.h" + +#include "modes.h" +#include "cmac.h" +#include "dmac.h" +#include "hmac.h" +#include "vmac.h" +#include "ttmac.h" + +#include "drbg.h" + +#include +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + + +bool ValidateHmacDRBG() +{ + std::cout << "\nTesting NIST HMAC DRBGs...\n\n"; + bool pass=true, fail; + + // # CAVS 14.3 + // # DRBG800-90A information for "drbg_pr" + // # Generated on Tue Apr 02 15:32:12 2013 + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 0], [AdditionalInputLen = 0], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x79\x34\x9b\xbf\x7c\xdd\xa5\x79\x95\x57\x86\x66\x21\xc9\x13\x83"; + const byte entropy2[] = "\xc7\x21\x5b\x5b\x96\xc4\x8e\x9b\x33\x8c\x74\xe3\xe9\x9d\xfe\xdf"; + const byte nonce[] = "\x11\x46\x73\x3a\xbf\x8c\x35\xc8"; + + HMAC_DRBG drbg(entropy1, 16, nonce, 8); + drbg.IncorporateEntropy(entropy2, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(result, result.size()); + drbg.GenerateBlock(result, result.size()); + + const byte expected[] = "\xc6\xa1\x6a\xb8\xd4\x20\x70\x6f\x0f\x34\xab\x7f\xec\x5a\xdc\xa9\xd8\xca\x3a\x13" + "\x3e\x15\x9c\xa6\xac\x43\xc6\xf8\xa2\xbe\x22\x83\x4a\x4c\x0a\x0a\xff\xb1\x0d\x71" + "\x94\xf1\xc1\xa5\xcf\x73\x22\xec\x1a\xe0\x96\x4e\xd4\xbf\x12\x27\x46\xe0\x87\xfd" + "\xb5\xb3\xe9\x1b\x34\x93\xd5\xbb\x98\xfa\xed\x49\xe8\x5f\x13\x0f\xc8\xa4\x59\xb7"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "HMAC_DRBG SHA1/128/440 (COUNT=0, E=16, N=8)\n"; + } + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 0], [AdditionalInputLen = 0], [ReturnedBitsLen = 640] + const byte entropy1[] = "\xee\x57\xfc\x23\x60\x0f\xb9\x02\x9a\x9e\xc6\xc8\x2e\x7b\x51\xe4"; + const byte entropy2[] = "\x84\x1d\x27\x6c\xa9\x51\x90\x61\xd9\x2d\x7d\xdf\xa6\x62\x8c\xa3"; + const byte nonce[] = "\x3e\x97\x21\xe4\x39\x3e\xf9\xad"; + + HMAC_DRBG drbg(entropy1, 16, nonce, 8); + drbg.IncorporateEntropy(entropy2, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(result, result.size()); + drbg.GenerateBlock(result, result.size()); + + const byte expected[] = "\xee\x26\xa5\xc8\xef\x08\xa1\xca\x8f\x14\x15\x4d\x67\xc8\x8f\x5e\x7e\xd8\x21\x9d" + "\x93\x1b\x98\x42\xac\x00\x39\xf2\x14\x55\x39\xf2\x14\x2b\x44\x11\x7a\x99\x8c\x22" + "\xf5\x90\xf6\xc9\xb3\x8b\x46\x5b\x78\x3e\xcf\xf1\x3a\x77\x50\x20\x1f\x7e\xcf\x1b" + "\x8a\xb3\x93\x60\x4c\x73\xb2\x38\x93\x36\x60\x9a\xf3\x44\x0c\xde\x43\x29\x8b\x84"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "HMAC_DRBG SHA1/128/440 (COUNT=1, E=16, N=8)\n"; + } + + // ***************************************************** + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 0], [AdditionalInputLen = 16], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x7d\x70\x52\xa7\x76\xfd\x2f\xb3\xd7\x19\x1f\x73\x33\x04\xee\x8b"; + const byte entropy2[] = "\x49\x04\x7e\x87\x9d\x61\x09\x55\xee\xd9\x16\xe4\x06\x0e\x00\xc9"; + const byte nonce[] = "\xbe\x4a\x0c\xee\xdc\xa8\x02\x07"; + const byte additional1[] = "\xfd\x8b\xb3\x3a\xab\x2f\x6c\xdf\xbc\x54\x18\x11\x86\x1d\x51\x8d"; + const byte additional2[] = "\x99\xaf\xe3\x47\x54\x04\x61\xdd\xf6\xab\xeb\x49\x1e\x07\x15\xb4"; + const byte additional3[] = "\x02\xf7\x73\x48\x2d\xd7\xae\x66\xf7\x6e\x38\x15\x98\xa6\x4e\xf0"; + + HMAC_DRBG drbg(entropy1, 16, nonce, 8); + drbg.IncorporateEntropy(entropy2, 16, additional1, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(additional2, 16, result, result.size()); + drbg.GenerateBlock(additional3, 16, result, result.size()); + + const byte expected[] = "\xa7\x36\x34\x38\x44\xfc\x92\x51\x13\x91\xdb\x0a\xdd\xd9\x06\x4d\xbe\xe2\x4c\x89" + "\x76\xaa\x25\x9a\x9e\x3b\x63\x68\xaa\x6d\xe4\xc9\xbf\x3a\x0e\xff\xcd\xa9\xcb\x0e" + "\x9d\xc3\x36\x52\xab\x58\xec\xb7\x65\x0e\xd8\x04\x67\xf7\x6a\x84\x9f\xb1\xcf\xc1" + "\xed\x0a\x09\xf7\x15\x50\x86\x06\x4d\xb3\x24\xb1\xe1\x24\xf3\xfc\x9e\x61\x4f\xcb"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "HMAC_DRBG SHA1/128/440 (COUNT=0, E=16, N=8, A=16)\n"; + } + + { + // [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64] + // [PersonalizationStringLen = 0], [AdditionalInputLen = 16], [ReturnedBitsLen = 640] + const byte entropy1[] = "\x29\xc6\x2a\xfa\x3c\x52\x20\x8a\x3f\xde\xcb\x43\xfa\x61\x3f\x15"; + const byte entropy2[] = "\xbd\x87\xbe\x99\xd1\x84\x16\x54\x12\x31\x41\x40\xd4\x02\x71\x41"; + const byte nonce[] = "\x6c\x9e\xb5\x9a\xc3\xc2\xd4\x8b"; + const byte additional1[] = "\x43\x3d\xda\xf2\x59\xd1\x4b\xcf\x89\x76\x30\xcc\xaa\x27\x33\x8c"; + const byte additional2[] = "\x14\x11\x46\xd4\x04\xf2\x84\xc2\xd0\x2b\x6a\x10\x15\x6e\x33\x82"; + const byte additional3[] = "\xed\xc3\x43\xdb\xff\xe7\x1a\xb4\x11\x4a\xc3\x63\x9d\x44\x5b\x65"; + + HMAC_DRBG drbg(entropy1, 16, nonce, 8); + drbg.IncorporateEntropy(entropy2, 16, additional1, 16); + + SecByteBlock result(80); + drbg.GenerateBlock(additional2, 16, result, result.size()); + drbg.GenerateBlock(additional3, 16, result, result.size()); + + const byte expected[] = "\x8c\x73\x0f\x05\x26\x69\x4d\x5a\x9a\x45\xdb\xab\x05\x7a\x19\x75\x35\x7d\x65\xaf" + "\xd3\xef\xf3\x03\x32\x0b\xd1\x40\x61\xf9\xad\x38\x75\x91\x02\xb6\xc6\x01\x16\xf6" + "\xdb\x7a\x6e\x8e\x7a\xb9\x4c\x05\x50\x0b\x4d\x1e\x35\x7d\xf8\xe9\x57\xac\x89\x37" + "\xb0\x5f\xb3\xd0\x80\xa0\xf9\x06\x74\xd4\x4d\xe1\xbd\x6f\x94\xd2\x95\xc4\x51\x9d"; + + fail = !!memcmp(result, expected, 640/8); + pass = !fail && pass; + + std::cout << (fail ? "FAILED " : "passed ") << "HMAC_DRBG SHA1/128/440 (COUNT=1, E=16, N=8, A=16)\n"; + } + + return pass; +} + +class CipherFactory +{ +public: + virtual unsigned int BlockSize() const =0; + virtual unsigned int KeyLength() const =0; + + virtual BlockTransformation* NewEncryption(const byte *keyStr) const =0; + virtual BlockTransformation* NewDecryption(const byte *keyStr) const =0; +}; + +template class FixedRoundsCipherFactory : public CipherFactory +{ +public: + FixedRoundsCipherFactory(unsigned int keylen=0) : + m_keylen(keylen ? keylen : static_cast(E::DEFAULT_KEYLENGTH)) {} + + unsigned int BlockSize() const {return E::BLOCKSIZE;} + unsigned int KeyLength() const {return m_keylen;} + + BlockTransformation* NewEncryption(const byte *keyStr) const + {return new E(keyStr, m_keylen);} + BlockTransformation* NewDecryption(const byte *keyStr) const + {return new D(keyStr, m_keylen);} + + unsigned int m_keylen; +}; + +template class VariableRoundsCipherFactory : public CipherFactory +{ +public: + VariableRoundsCipherFactory(unsigned int keylen=0, unsigned int rounds=0) : + m_keylen(keylen ? keylen : static_cast(E::DEFAULT_KEYLENGTH)), + m_rounds(rounds ? rounds : static_cast(E::DEFAULT_ROUNDS)) {} + + unsigned int BlockSize() const {return static_cast(E::BLOCKSIZE);} + unsigned int KeyLength() const {return m_keylen;} + + BlockTransformation* NewEncryption(const byte *keyStr) const + {return new E(keyStr, m_keylen, m_rounds);} + BlockTransformation* NewDecryption(const byte *keyStr) const + {return new D(keyStr, m_keylen, m_rounds);} + + unsigned int m_keylen, m_rounds; +}; + +bool BlockTransformationTest(const CipherFactory &cg, BufferedTransformation &valdata, unsigned int tuples = 0xffff) +{ + HexEncoder output(new FileSink(std::cout)); + SecByteBlock plain(cg.BlockSize()), cipher(cg.BlockSize()), out(cg.BlockSize()), outplain(cg.BlockSize()); + SecByteBlock key(cg.KeyLength()); + bool pass=true, fail; + + while (valdata.MaxRetrievable() && tuples--) + { + (void)valdata.Get(key, cg.KeyLength()); + (void)valdata.Get(plain, cg.BlockSize()); + (void)valdata.Get(cipher, cg.BlockSize()); + + member_ptr transE(cg.NewEncryption(key)); + transE->ProcessBlock(plain, out); + fail = memcmp(out, cipher, cg.BlockSize()) != 0; + + member_ptr transD(cg.NewDecryption(key)); + transD->ProcessBlock(out, outplain); + fail=fail || memcmp(outplain, plain, cg.BlockSize()); + + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + output.Put(key, cg.KeyLength()); + std::cout << " "; + output.Put(outplain, cg.BlockSize()); + std::cout << " "; + output.Put(out, cg.BlockSize()); + std::cout << std::endl; + } + return pass; +} + +class FilterTester : public Unflushable +{ +public: + FilterTester(const byte *validOutput, size_t outputLen) + : validOutput(validOutput), outputLen(outputLen), counter(0), fail(false) {} + void PutByte(byte inByte) + { + if (counter >= outputLen || validOutput[counter] != inByte) + { + std::cerr << "incorrect output " << counter << ", " << (word16)validOutput[counter] << ", " << (word16)inByte << "\n"; + fail = true; + CRYPTOPP_ASSERT(false); + } + counter++; + } + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + CRYPTOPP_UNUSED(messageEnd), CRYPTOPP_UNUSED(blocking); + + while (length--) + FilterTester::PutByte(*inString++); + + if (messageEnd) + if (counter != outputLen) + { + fail = true; + CRYPTOPP_ASSERT(false); + } + + return 0; + } + bool GetResult() + { + return !fail; + } + + const byte *validOutput; + size_t outputLen, counter; + bool fail; +}; + +bool TestFilter(BufferedTransformation &bt, const byte *in, size_t inLen, const byte *out, size_t outLen) +{ + FilterTester *ft; + bt.Attach(ft = new FilterTester(out, outLen)); + + while (inLen) + { + size_t randomLen = GlobalRNG().GenerateWord32(0, (word32)inLen); + bt.Put(in, randomLen); + in += randomLen; + inLen -= randomLen; + } + bt.MessageEnd(); + return ft->GetResult(); +} + +bool ValidateDES() +{ + std::cout << "\nDES validation suite running...\n\n"; + + FileSource valdata(DataDir("TestData/descert.dat").c_str(), true, new HexDecoder); + bool pass = BlockTransformationTest(FixedRoundsCipherFactory(), valdata); + + std::cout << "\nTesting EDE2, EDE3, and XEX3 variants...\n\n"; + + FileSource valdata1(DataDir("TestData/3desval.dat").c_str(), true, new HexDecoder); + pass = BlockTransformationTest(FixedRoundsCipherFactory(), valdata1, 1) && pass; + pass = BlockTransformationTest(FixedRoundsCipherFactory(), valdata1, 1) && pass; + pass = BlockTransformationTest(FixedRoundsCipherFactory(), valdata1, 1) && pass; + + return pass; +} + +bool TestModeIV(SymmetricCipher &e, SymmetricCipher &d) +{ + SecByteBlock lastIV, iv(e.IVSize()); + StreamTransformationFilter filter(e, new StreamTransformationFilter(d)); + + // Enterprise Analysis finding on the stack based array + const int BUF_SIZE=20480U; + AlignedSecByteBlock plaintext(BUF_SIZE); + + for (unsigned int i=1; i cbcmac(key); + HashFilter cbcmacFilter(cbcmac); + fail = !TestFilter(cbcmacFilter, plain_3, sizeof(plain_3), mac1, sizeof(mac1)); + pass = pass && !fail; + std::cout << (fail ? "FAILED " : "passed ") << "CBC MAC" << std::endl; + + DMAC dmac(key); + HashFilter dmacFilter(dmac); + fail = !TestFilter(dmacFilter, plain_3, sizeof(plain_3), mac2, sizeof(mac2)); + pass = pass && !fail; + std::cout << (fail ? "FAILED " : "passed ") << "DMAC" << std::endl; + } + + return pass; +} + +bool ValidateIDEA() +{ + std::cout << "\nIDEA validation suite running...\n\n"; + + FileSource valdata(DataDir("TestData/ideaval.dat").c_str(), true, new HexDecoder); + return BlockTransformationTest(FixedRoundsCipherFactory(), valdata); +} + +bool ValidateSAFER() +{ + std::cout << "\nSAFER validation suite running...\n\n"; + + FileSource valdata(DataDir("TestData/saferval.dat").c_str(), true, new HexDecoder); + bool pass = true; + pass = BlockTransformationTest(VariableRoundsCipherFactory(8,6), valdata, 4) && pass; + pass = BlockTransformationTest(VariableRoundsCipherFactory(16,12), valdata, 4) && pass; + pass = BlockTransformationTest(VariableRoundsCipherFactory(8,6), valdata, 4) && pass; + pass = BlockTransformationTest(VariableRoundsCipherFactory(16,10), valdata, 4) && pass; + return pass; +} + +bool ValidateRC2() +{ + std::cout << "\nRC2 validation suite running...\n\n"; + + FileSource valdata(DataDir("TestData/rc2val.dat").c_str(), true, new HexDecoder); + HexEncoder output(new FileSink(std::cout)); + SecByteBlock plain(RC2Encryption::BLOCKSIZE), cipher(RC2Encryption::BLOCKSIZE), out(RC2Encryption::BLOCKSIZE), outplain(RC2Encryption::BLOCKSIZE); + SecByteBlock key(128); + bool pass=true, fail; + + while (valdata.MaxRetrievable()) + { + byte keyLen, effectiveLen; + + (void)valdata.Get(keyLen); + (void)valdata.Get(effectiveLen); + (void)valdata.Get(key, keyLen); + (void)valdata.Get(plain, RC2Encryption::BLOCKSIZE); + (void)valdata.Get(cipher, RC2Encryption::BLOCKSIZE); + + member_ptr transE(new RC2Encryption(key, keyLen, effectiveLen)); + transE->ProcessBlock(plain, out); + fail = memcmp(out, cipher, RC2Encryption::BLOCKSIZE) != 0; + + member_ptr transD(new RC2Decryption(key, keyLen, effectiveLen)); + transD->ProcessBlock(out, outplain); + fail=fail || memcmp(outplain, plain, RC2Encryption::BLOCKSIZE); + + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + output.Put(key, keyLen); + std::cout << " "; + output.Put(outplain, RC2Encryption::BLOCKSIZE); + std::cout << " "; + output.Put(out, RC2Encryption::BLOCKSIZE); + std::cout << std::endl; + } + return pass; +} + +bool ValidateARC4() +{ + unsigned char Key0[] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef }; + unsigned char Input0[]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; + unsigned char Output0[] = {0x75,0xb7,0x87,0x80,0x99,0xe0,0xc5,0x96}; + + unsigned char Key1[]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; + unsigned char Input1[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + unsigned char Output1[]={0x74,0x94,0xc2,0xe7,0x10,0x4b,0x08,0x79}; + + unsigned char Key2[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + unsigned char Input2[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + unsigned char Output2[]={0xde,0x18,0x89,0x41,0xa3,0x37,0x5d,0x3a}; + + unsigned char Key3[]={0xef,0x01,0x23,0x45}; + unsigned char Input3[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + unsigned char Output3[]={0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf,0xbd,0x61}; + + unsigned char Key4[]={ 0x01,0x23,0x45,0x67,0x89,0xab, 0xcd,0xef }; + unsigned char Input4[] = + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01}; + unsigned char Output4[]= { + 0x75,0x95,0xc3,0xe6,0x11,0x4a,0x09,0x78,0x0c,0x4a,0xd4, + 0x52,0x33,0x8e,0x1f,0xfd,0x9a,0x1b,0xe9,0x49,0x8f, + 0x81,0x3d,0x76,0x53,0x34,0x49,0xb6,0x77,0x8d,0xca, + 0xd8,0xc7,0x8a,0x8d,0x2b,0xa9,0xac,0x66,0x08,0x5d, + 0x0e,0x53,0xd5,0x9c,0x26,0xc2,0xd1,0xc4,0x90,0xc1, + 0xeb,0xbe,0x0c,0xe6,0x6d,0x1b,0x6b,0x1b,0x13,0xb6, + 0xb9,0x19,0xb8,0x47,0xc2,0x5a,0x91,0x44,0x7a,0x95, + 0xe7,0x5e,0x4e,0xf1,0x67,0x79,0xcd,0xe8,0xbf,0x0a, + 0x95,0x85,0x0e,0x32,0xaf,0x96,0x89,0x44,0x4f,0xd3, + 0x77,0x10,0x8f,0x98,0xfd,0xcb,0xd4,0xe7,0x26,0x56, + 0x75,0x00,0x99,0x0b,0xcc,0x7e,0x0c,0xa3,0xc4,0xaa, + 0xa3,0x04,0xa3,0x87,0xd2,0x0f,0x3b,0x8f,0xbb,0xcd, + 0x42,0xa1,0xbd,0x31,0x1d,0x7a,0x43,0x03,0xdd,0xa5, + 0xab,0x07,0x88,0x96,0xae,0x80,0xc1,0x8b,0x0a,0xf6, + 0x6d,0xff,0x31,0x96,0x16,0xeb,0x78,0x4e,0x49,0x5a, + 0xd2,0xce,0x90,0xd7,0xf7,0x72,0xa8,0x17,0x47,0xb6, + 0x5f,0x62,0x09,0x3b,0x1e,0x0d,0xb9,0xe5,0xba,0x53, + 0x2f,0xaf,0xec,0x47,0x50,0x83,0x23,0xe6,0x71,0x32, + 0x7d,0xf9,0x44,0x44,0x32,0xcb,0x73,0x67,0xce,0xc8, + 0x2f,0x5d,0x44,0xc0,0xd0,0x0b,0x67,0xd6,0x50,0xa0, + 0x75,0xcd,0x4b,0x70,0xde,0xdd,0x77,0xeb,0x9b,0x10, + 0x23,0x1b,0x6b,0x5b,0x74,0x13,0x47,0x39,0x6d,0x62, + 0x89,0x74,0x21,0xd4,0x3d,0xf9,0xb4,0x2e,0x44,0x6e, + 0x35,0x8e,0x9c,0x11,0xa9,0xb2,0x18,0x4e,0xcb,0xef, + 0x0c,0xd8,0xe7,0xa8,0x77,0xef,0x96,0x8f,0x13,0x90, + 0xec,0x9b,0x3d,0x35,0xa5,0x58,0x5c,0xb0,0x09,0x29, + 0x0e,0x2f,0xcd,0xe7,0xb5,0xec,0x66,0xd9,0x08,0x4b, + 0xe4,0x40,0x55,0xa6,0x19,0xd9,0xdd,0x7f,0xc3,0x16, + 0x6f,0x94,0x87,0xf7,0xcb,0x27,0x29,0x12,0x42,0x64, + 0x45,0x99,0x85,0x14,0xc1,0x5d,0x53,0xa1,0x8c,0x86, + 0x4c,0xe3,0xa2,0xb7,0x55,0x57,0x93,0x98,0x81,0x26, + 0x52,0x0e,0xac,0xf2,0xe3,0x06,0x6e,0x23,0x0c,0x91, + 0xbe,0xe4,0xdd,0x53,0x04,0xf5,0xfd,0x04,0x05,0xb3, + 0x5b,0xd9,0x9c,0x73,0x13,0x5d,0x3d,0x9b,0xc3,0x35, + 0xee,0x04,0x9e,0xf6,0x9b,0x38,0x67,0xbf,0x2d,0x7b, + 0xd1,0xea,0xa5,0x95,0xd8,0xbf,0xc0,0x06,0x6f,0xf8, + 0xd3,0x15,0x09,0xeb,0x0c,0x6c,0xaa,0x00,0x6c,0x80, + 0x7a,0x62,0x3e,0xf8,0x4c,0x3d,0x33,0xc1,0x95,0xd2, + 0x3e,0xe3,0x20,0xc4,0x0d,0xe0,0x55,0x81,0x57,0xc8, + 0x22,0xd4,0xb8,0xc5,0x69,0xd8,0x49,0xae,0xd5,0x9d, + 0x4e,0x0f,0xd7,0xf3,0x79,0x58,0x6b,0x4b,0x7f,0xf6, + 0x84,0xed,0x6a,0x18,0x9f,0x74,0x86,0xd4,0x9b,0x9c, + 0x4b,0xad,0x9b,0xa2,0x4b,0x96,0xab,0xf9,0x24,0x37, + 0x2c,0x8a,0x8f,0xff,0xb1,0x0d,0x55,0x35,0x49,0x00, + 0xa7,0x7a,0x3d,0xb5,0xf2,0x05,0xe1,0xb9,0x9f,0xcd, + 0x86,0x60,0x86,0x3a,0x15,0x9a,0xd4,0xab,0xe4,0x0f, + 0xa4,0x89,0x34,0x16,0x3d,0xdd,0xe5,0x42,0xa6,0x58, + 0x55,0x40,0xfd,0x68,0x3c,0xbf,0xd8,0xc0,0x0f,0x12, + 0x12,0x9a,0x28,0x4d,0xea,0xcc,0x4c,0xde,0xfe,0x58, + 0xbe,0x71,0x37,0x54,0x1c,0x04,0x71,0x26,0xc8,0xd4, + 0x9e,0x27,0x55,0xab,0x18,0x1a,0xb7,0xe9,0x40,0xb0, + 0xc0}; + + member_ptr arc4; + bool pass=true, fail; + unsigned int i; + + std::cout << "\nARC4 validation suite running...\n\n"; + + arc4.reset(new Weak::ARC4(Key0, sizeof(Key0))); + arc4->ProcessString(Input0, sizeof(Input0)); + fail = memcmp(Input0, Output0, sizeof(Input0)) != 0; + std::cout << (fail ? "FAILED" : "passed") << " Test 0" << std::endl; + pass = pass && !fail; + + arc4.reset(new Weak::ARC4(Key1, sizeof(Key1))); + arc4->ProcessString(Key1, Input1, sizeof(Key1)); + fail = memcmp(Output1, Key1, sizeof(Key1)) != 0; + std::cout << (fail ? "FAILED" : "passed") << " Test 1" << std::endl; + pass = pass && !fail; + + arc4.reset(new Weak::ARC4(Key2, sizeof(Key2))); + for (i=0, fail=false; iProcessByte(Input2[i]) != Output2[i]) + fail = true; + std::cout << (fail ? "FAILED" : "passed") << " Test 2" << std::endl; + pass = pass && !fail; + + arc4.reset(new Weak::ARC4(Key3, sizeof(Key3))); + for (i=0, fail=false; iProcessByte(Input3[i]) != Output3[i]) + fail = true; + std::cout << (fail ? "FAILED" : "passed") << " Test 3" << std::endl; + pass = pass && !fail; + + arc4.reset(new Weak::ARC4(Key4, sizeof(Key4))); + for (i=0, fail=false; iProcessByte(Input4[i]) != Output4[i]) + fail = true; + std::cout << (fail ? "FAILED" : "passed") << " Test 4" << std::endl; + pass = pass && !fail; + + return pass; +} + +bool ValidateRC5() +{ + std::cout << "\nRC5 validation suite running...\n\n"; + bool pass1 = true, pass2 = true; + + RC5Encryption enc; // 0 to 2040-bits (255-bytes) + pass1 = RC5Encryption::DEFAULT_KEYLENGTH == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(0) == 0 && pass1; + pass1 = enc.StaticGetValidKeyLength(254) == 254 && pass1; + pass1 = enc.StaticGetValidKeyLength(255) == 255 && pass1; + pass1 = enc.StaticGetValidKeyLength(256) == 255 && pass1; + pass1 = enc.StaticGetValidKeyLength(0) == enc.MinKeyLength() && pass1; + pass1 = enc.StaticGetValidKeyLength(SIZE_MAX) == enc.MaxKeyLength() && pass1; + + RC5Decryption dec; + pass2 = RC5Decryption::DEFAULT_KEYLENGTH == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(0) == 0 && pass2; + pass2 = dec.StaticGetValidKeyLength(254) == 254 && pass2; + pass2 = dec.StaticGetValidKeyLength(255) == 255 && pass2; + pass2 = dec.StaticGetValidKeyLength(256) == 255 && pass2; + pass2 = dec.StaticGetValidKeyLength(0) == dec.MinKeyLength() && pass2; + pass2 = dec.StaticGetValidKeyLength(SIZE_MAX) == dec.MaxKeyLength() && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/rc5val.dat").c_str(), true, new HexDecoder); + return BlockTransformationTest(VariableRoundsCipherFactory(16, 12), valdata) && pass1 && pass2; +} + +bool ValidateRC6() +{ + std::cout << "\nRC6 validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + RC6Encryption enc; + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(24) == 24 && pass1; + pass1 = enc.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(64) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(128) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(0) == enc.MinKeyLength() && pass1; + pass1 = enc.StaticGetValidKeyLength(SIZE_MAX) == enc.MaxKeyLength() && pass1; + + RC6Decryption dec; + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(24) == 24 && pass2; + pass2 = dec.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(64) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(128) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(0) == dec.MinKeyLength() && pass2; + pass2 = dec.StaticGetValidKeyLength(SIZE_MAX) == dec.MaxKeyLength() && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/rc6val.dat").c_str(), true, new HexDecoder); + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(16), valdata, 2) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(24), valdata, 2) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(32), valdata, 2) && pass3; + return pass1 && pass2 && pass3; +} + +bool ValidateMARS() +{ + std::cout << "\nMARS validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + MARSEncryption enc; + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(24) == 24 && pass1; + pass1 = enc.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(64) == 56 && pass1; + pass1 = enc.StaticGetValidKeyLength(128) == 56 && pass1; + pass1 = enc.StaticGetValidKeyLength(0) == enc.MinKeyLength() && pass1; + pass1 = enc.StaticGetValidKeyLength(SIZE_MAX) == enc.MaxKeyLength() && pass1; + + MARSDecryption dec; + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(24) == 24 && pass2; + pass2 = dec.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(64) == 56 && pass2; + pass2 = dec.StaticGetValidKeyLength(128) == 56 && pass2; + pass2 = dec.StaticGetValidKeyLength(0) == dec.MinKeyLength() && pass2; + pass2 = dec.StaticGetValidKeyLength(SIZE_MAX) == dec.MaxKeyLength() && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/marsval.dat").c_str(), true, new HexDecoder); + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(16), valdata, 4) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(24), valdata, 3) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(32), valdata, 2) && pass3; + return pass1 && pass2 && pass3; +} + +bool ValidateRijndael() +{ + std::cout << "\nRijndael (AES) validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + RijndaelEncryption enc; + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(24) == 24 && pass1; + pass1 = enc.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(64) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(128) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(0) == enc.MinKeyLength() && pass1; + pass1 = enc.StaticGetValidKeyLength(SIZE_MAX) == enc.MaxKeyLength() && pass1; + + RijndaelDecryption dec; + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(24) == 24 && pass2; + pass2 = dec.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(64) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(128) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(0) == dec.MinKeyLength() && pass2; + pass2 = dec.StaticGetValidKeyLength(SIZE_MAX) == dec.MaxKeyLength() && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/rijndael.dat").c_str(), true, new HexDecoder); + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(16), valdata, 4) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(24), valdata, 3) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(32), valdata, 2) && pass3; + pass3 = RunTestDataFile("TestVectors/aes.txt") && pass3; + return pass1 && pass2 && pass3; +} + +bool ValidateTwofish() +{ + std::cout << "\nTwofish validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + TwofishEncryption enc; + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(24) == 24 && pass1; + pass1 = enc.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(64) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(128) == 32 && pass1; + + TwofishDecryption dec; + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(24) == 24 && pass2; + pass2 = dec.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(64) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(128) == 32 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/twofishv.dat").c_str(), true, new HexDecoder); + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(16), valdata, 4) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(24), valdata, 3) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(32), valdata, 2) && pass3; + return pass1 && pass2 && pass3; +} + +bool ValidateSerpent() +{ + std::cout << "\nSerpent validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + SerpentEncryption enc; + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(24) == 24 && pass1; + pass1 = enc.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(64) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(128) == 32 && pass1; + + SerpentDecryption dec; + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(24) == 24 && pass2; + pass2 = dec.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(64) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(128) == 32 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/serpentv.dat").c_str(), true, new HexDecoder); + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(16), valdata, 5) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(24), valdata, 4) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(32), valdata, 3) && pass3; + return pass1 && pass2 && pass3; +} + +bool ValidateBlowfish() +{ + std::cout << "\nBlowfish validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true, fail; + + BlowfishEncryption enc1; // 32 to 448-bits (4 to 56-bytes) + pass1 = enc1.StaticGetValidKeyLength(3) == 4 && pass1; + pass1 = enc1.StaticGetValidKeyLength(4) == 4 && pass1; + pass1 = enc1.StaticGetValidKeyLength(5) == 5 && pass1; + pass1 = enc1.StaticGetValidKeyLength(8) == 8 && pass1; + pass1 = enc1.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc1.StaticGetValidKeyLength(24) == 24 && pass1; + pass1 = enc1.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc1.StaticGetValidKeyLength(56) == 56 && pass1; + pass1 = enc1.StaticGetValidKeyLength(57) == 56 && pass1; + pass1 = enc1.StaticGetValidKeyLength(60) == 56 && pass1; + pass1 = enc1.StaticGetValidKeyLength(64) == 56 && pass1; + pass1 = enc1.StaticGetValidKeyLength(128) == 56 && pass1; + + BlowfishDecryption dec1; // 32 to 448-bits (4 to 56-bytes) + pass2 = dec1.StaticGetValidKeyLength(3) == 4 && pass2; + pass2 = dec1.StaticGetValidKeyLength(4) == 4 && pass2; + pass2 = dec1.StaticGetValidKeyLength(5) == 5 && pass2; + pass2 = dec1.StaticGetValidKeyLength(8) == 8 && pass2; + pass2 = dec1.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec1.StaticGetValidKeyLength(24) == 24 && pass2; + pass2 = dec1.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec1.StaticGetValidKeyLength(56) == 56 && pass2; + pass2 = dec1.StaticGetValidKeyLength(57) == 56 && pass2; + pass2 = dec1.StaticGetValidKeyLength(60) == 56 && pass2; + pass2 = dec1.StaticGetValidKeyLength(64) == 56 && pass2; + pass2 = dec1.StaticGetValidKeyLength(128) == 56 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + HexEncoder output(new FileSink(std::cout)); + const char *key[]={"abcdefghijklmnopqrstuvwxyz", "Who is John Galt?"}; + byte *plain[]={(byte *)"BLOWFISH", (byte *)"\xfe\xdc\xba\x98\x76\x54\x32\x10"}; + byte *cipher[]={(byte *)"\x32\x4e\xd0\xfe\xf4\x13\xa2\x03", (byte *)"\xcc\x91\x73\x2b\x80\x22\xf6\x84"}; + byte out[8], outplain[8]; + + for (int i=0; i<2; i++) + { + ECB_Mode::Encryption enc2((byte *)key[i], strlen(key[i])); + enc2.ProcessData(out, plain[i], 8); + fail = memcmp(out, cipher[i], 8) != 0; + + ECB_Mode::Decryption dec2((byte *)key[i], strlen(key[i])); + dec2.ProcessData(outplain, cipher[i], 8); + fail = fail || memcmp(outplain, plain[i], 8); + pass3 = pass3 && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << '\"' << key[i] << '\"'; + for (int j=0; j<(signed int)(30-strlen(key[i])); j++) + std::cout << ' '; + output.Put(outplain, 8); + std::cout << " "; + output.Put(out, 8); + std::cout << std::endl; + } + return pass1 && pass2 && pass3; +} + +bool ValidateThreeWay() +{ + std::cout << "\n3-WAY validation suite running...\n\n"; + bool pass1 = true, pass2 = true; + + ThreeWayEncryption enc; // 96-bit only + pass1 = ThreeWayEncryption::KEYLENGTH == 12 && pass1; + pass1 = enc.StaticGetValidKeyLength(8) == 12 && pass1; + pass1 = enc.StaticGetValidKeyLength(12) == 12 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 12 && pass1; + + ThreeWayDecryption dec; // 96-bit only + pass2 = ThreeWayDecryption::KEYLENGTH == 12 && pass2; + pass2 = dec.StaticGetValidKeyLength(8) == 12 && pass2; + pass2 = dec.StaticGetValidKeyLength(12) == 12 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 12 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/3wayval.dat").c_str(), true, new HexDecoder); + return BlockTransformationTest(FixedRoundsCipherFactory(), valdata) && pass1 && pass2; +} + +bool ValidateGOST() +{ + std::cout << "\nGOST validation suite running...\n\n"; + bool pass1 = true, pass2 = true; + + GOSTEncryption enc; // 256-bit only + pass1 = GOSTEncryption::KEYLENGTH == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(24) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(40) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(64) == 32 && pass1; + + GOSTDecryption dec; // 256-bit only + pass2 = GOSTDecryption::KEYLENGTH == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(24) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(40) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(64) == 32 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/gostval.dat").c_str(), true, new HexDecoder); + return BlockTransformationTest(FixedRoundsCipherFactory(), valdata) && pass1 && pass2; +} + +bool ValidateSHARK() +{ + std::cout << "\nSHARK validation suite running...\n\n"; + bool pass1 = true, pass2 = true; + + SHARKEncryption enc; // 128-bit only + pass1 = SHARKEncryption::KEYLENGTH == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(15) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(17) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(32) == 16 && pass1; + + SHARKDecryption dec; // 128-bit only + pass2 = SHARKDecryption::KEYLENGTH == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(15) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(17) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(32) == 16 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/sharkval.dat").c_str(), true, new HexDecoder); + return BlockTransformationTest(FixedRoundsCipherFactory(), valdata) && pass1 && pass2; +} + +bool ValidateCAST() +{ + std::cout << "\nCAST-128 validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + CAST128Encryption enc1; // 40 to 128-bits (5 to 16-bytes) + pass1 = CAST128Encryption::DEFAULT_KEYLENGTH == 16 && pass1; + pass1 = enc1.StaticGetValidKeyLength(4) == 5 && pass1; + pass1 = enc1.StaticGetValidKeyLength(5) == 5 && pass1; + pass1 = enc1.StaticGetValidKeyLength(15) == 15 && pass1; + pass1 = enc1.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc1.StaticGetValidKeyLength(17) == 16 && pass1; + + CAST128Decryption dec1; // 40 to 128-bits (5 to 16-bytes) + pass2 = CAST128Decryption::DEFAULT_KEYLENGTH == 16 && pass2; + pass2 = dec1.StaticGetValidKeyLength(4) == 5 && pass2; + pass2 = dec1.StaticGetValidKeyLength(5) == 5 && pass2; + pass2 = dec1.StaticGetValidKeyLength(15) == 15 && pass2; + pass2 = dec1.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec1.StaticGetValidKeyLength(17) == 16 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource val128(DataDir("TestData/cast128v.dat").c_str(), true, new HexDecoder); + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(16), val128, 1) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(10), val128, 1) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(5), val128, 1) && pass3; + + std::cout << "\nCAST-256 validation suite running...\n\n"; + bool pass4 = true, pass5 = true, pass6 = true; + + CAST256Encryption enc2; // 128, 160, 192, 224, or 256-bits (16 to 32-bytes, step 4) + pass1 = CAST128Encryption::DEFAULT_KEYLENGTH == 16 && pass1; + pass4 = enc2.StaticGetValidKeyLength(15) == 16 && pass4; + pass4 = enc2.StaticGetValidKeyLength(16) == 16 && pass4; + pass4 = enc2.StaticGetValidKeyLength(17) == 20 && pass4; + pass4 = enc2.StaticGetValidKeyLength(20) == 20 && pass4; + pass4 = enc2.StaticGetValidKeyLength(24) == 24 && pass4; + pass4 = enc2.StaticGetValidKeyLength(28) == 28 && pass4; + pass4 = enc2.StaticGetValidKeyLength(31) == 32 && pass4; + pass4 = enc2.StaticGetValidKeyLength(32) == 32 && pass4; + pass4 = enc2.StaticGetValidKeyLength(33) == 32 && pass4; + + CAST256Decryption dec2; // 128, 160, 192, 224, or 256-bits (16 to 32-bytes, step 4) + pass2 = CAST256Decryption::DEFAULT_KEYLENGTH == 16 && pass2; + pass5 = dec2.StaticGetValidKeyLength(15) == 16 && pass5; + pass5 = dec2.StaticGetValidKeyLength(16) == 16 && pass5; + pass5 = dec2.StaticGetValidKeyLength(17) == 20 && pass5; + pass5 = dec2.StaticGetValidKeyLength(20) == 20 && pass5; + pass5 = dec2.StaticGetValidKeyLength(24) == 24 && pass5; + pass5 = dec2.StaticGetValidKeyLength(28) == 28 && pass5; + pass5 = dec2.StaticGetValidKeyLength(31) == 32 && pass5; + pass5 = dec2.StaticGetValidKeyLength(32) == 32 && pass5; + pass5 = dec2.StaticGetValidKeyLength(33) == 32 && pass5; + std::cout << (pass4 && pass5 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource val256(DataDir("TestData/cast256v.dat").c_str(), true, new HexDecoder); + pass6 = BlockTransformationTest(FixedRoundsCipherFactory(16), val256, 1) && pass6; + pass6 = BlockTransformationTest(FixedRoundsCipherFactory(24), val256, 1) && pass6; + pass6 = BlockTransformationTest(FixedRoundsCipherFactory(32), val256, 1) && pass6; + + return pass1 && pass2 && pass3 && pass4 && pass5 && pass6; +} + +bool ValidateSquare() +{ + std::cout << "\nSquare validation suite running...\n\n"; + bool pass1 = true, pass2 = true; + + SquareEncryption enc; // 128-bits only + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(15) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(17) == 16 && pass1; + + SquareDecryption dec; // 128-bits only + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(15) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(17) == 16 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/squareva.dat").c_str(), true, new HexDecoder); + return BlockTransformationTest(FixedRoundsCipherFactory(), valdata) && pass1 && pass2; +} + +bool ValidateSKIPJACK() +{ + std::cout << "\nSKIPJACK validation suite running...\n\n"; + bool pass1 = true, pass2 = true; + + SKIPJACKEncryption enc; // 80-bits only + pass1 = enc.StaticGetValidKeyLength(8) == 10 && pass1; + pass1 = enc.StaticGetValidKeyLength(9) == 10 && pass1; + pass1 = enc.StaticGetValidKeyLength(10) == 10 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 10 && pass1; + + SKIPJACKDecryption dec; // 80-bits only + pass2 = dec.StaticGetValidKeyLength(8) == 10 && pass2; + pass2 = dec.StaticGetValidKeyLength(9) == 10 && pass2; + pass2 = dec.StaticGetValidKeyLength(10) == 10 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 10 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/skipjack.dat").c_str(), true, new HexDecoder); + return BlockTransformationTest(FixedRoundsCipherFactory(), valdata) && pass1 && pass2; +} + +bool ValidateSEAL() +{ + const byte input[] = {0x37,0xa0,0x05,0x95,0x9b,0x84,0xc4,0x9c,0xa4,0xbe,0x1e,0x05,0x06,0x73,0x53,0x0f,0x5f,0xb0,0x97,0xfd,0xf6,0xa1,0x3f,0xbd,0x6c,0x2c,0xde,0xcd,0x81,0xfd,0xee,0x7c}; + const byte key[] = {0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0}; + const byte iv[] = {0x01, 0x35, 0x77, 0xaf}; + byte output[32]; + + std::cout << "\nSEAL validation suite running...\n\n"; + + SEAL<>::Encryption seal(key, sizeof(key), iv); + unsigned int size = sizeof(input); + bool pass = true; + + memset(output, 1, size); + seal.ProcessString(output, input, size); + for (unsigned int i=0; iInitialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::EncodingLookupArray(), (const byte *)&stars[0], false) + (Name::PaddingByte(), padding) + (Name::GroupSize(), insertLineBreaks ? maxLineLength : 0) + (Name::Separator(), ConstByteArrayParameter(lineBreak)) + (Name::Terminator(), ConstByteArrayParameter(lineBreak)) + (Name::Log2Base(), 6, true))); +} + +class MyDecoder : public BaseN_Decoder +{ +public: + MyDecoder(BufferedTransformation *attachment = NULLPTR); + void IsolatedInitialize(const NameValuePairs ¶ms); + static const int * CRYPTOPP_API GetDecodingLookupArray(); +}; + +MyDecoder::MyDecoder(BufferedTransformation *attachment) + : BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) +{ +} + +void MyDecoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::DecodingLookupArray(), GetDecodingLookupArray(), false)(Name::Log2Base(), 6, true))); +} + +struct MyDecoderAlphabet +{ + MyDecoderAlphabet() { + std::fill(tab, tab+COUNTOF(tab), '*'); + } + byte tab[64]; +}; + +struct MyDecoderArray +{ + MyDecoderArray() { + std::fill(tab, tab+COUNTOF(tab), -1); + } + int tab[256]; +}; + +const int * MyDecoder::GetDecodingLookupArray() +{ + static bool s_initialized = false; + static MyDecoderAlphabet s_alpha; + static MyDecoderArray s_array; + + MEMORY_BARRIER(); + if (!s_initialized) + { + InitializeDecodingLookupArray(s_array.tab, s_alpha.tab, COUNTOF(s_alpha.tab), false); + s_initialized = true; + MEMORY_BARRIER(); + } + return s_array.tab; +} + +bool ValidateEncoder() +{ + // The default encoder and decoder alphabet are bogus. They are a + // string of '*'. To round trip a string both IsolatedInitialize + // must be called and work correctly. + std::cout << "\nCustom encoder validation running...\n\n"; + bool pass = true; + + int lookup[256]; + const char alphabet[64+1] = + "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz01234576789*"; + const char expected[] = + "ILcBMSgriDicmKmTi2oENCsuJTufN0yWjL1HnS8xKdaiOkeZK3gKock1ktmlo1q4LlsNPrAyGrG0gjO2gzQ5FQ=="; + + MyEncoder encoder; + std::string str1; + + AlgorithmParameters eparams = MakeParameters(Name::EncodingLookupArray(),(const byte*)alphabet) + (Name::InsertLineBreaks(), false); + encoder.IsolatedInitialize(eparams); + + encoder.Detach(new StringSink(str1)); + encoder.Put((const byte*) alphabet, 64); + encoder.MessageEnd(); + + MyDecoder decoder; + std::string str2; + + MyDecoder::InitializeDecodingLookupArray(lookup, (const byte*) alphabet, 64, false); + AlgorithmParameters dparams = MakeParameters(Name::DecodingLookupArray(),(const int*)lookup); + decoder.IsolatedInitialize(dparams); + + decoder.Detach(new StringSink(str2)); + decoder.Put(ConstBytePtr(str1), BytePtrSize(str1)); + decoder.MessageEnd(); + + pass = (str1 == std::string(expected)) && pass; + pass = (str2 == std::string(alphabet, 64)) && pass; + + std::cout << (pass ? "passed:" : "FAILED:"); + std::cout << " Encode and decode\n"; + + // Try forcing an empty message. This is the Monero bug + // at https://github.com/weidai11/cryptopp/issues/562. + { + MyDecoder decoder2; + SecByteBlock empty; + + AlgorithmParameters dparams2 = MakeParameters(Name::DecodingLookupArray(),(const int*)lookup); + decoder2.IsolatedInitialize(dparams2); + + decoder2.Detach(new Redirector(TheBitBucket())); + decoder2.Put(empty.BytePtr(), empty.SizeInBytes()); + decoder2.MessageEnd(); + + // Tame the optimizer + volatile lword size = decoder2.MaxRetrievable(); + lword shadow = size; + CRYPTOPP_UNUSED(shadow); + } + + std::cout << "passed: 0-length message\n"; + + return pass; +} + +bool ValidateSHACAL2() +{ + std::cout << "\nSHACAL-2 validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + SHACAL2Encryption enc; // 128 to 512-bits (16 to 64-bytes) + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(15) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(64) == 64 && pass1; + pass1 = enc.StaticGetValidKeyLength(65) == 64 && pass1; + pass1 = enc.StaticGetValidKeyLength(128) == 64 && pass1; + pass1 = enc.StaticGetValidKeyLength(0) == enc.MinKeyLength() && pass1; + pass1 = enc.StaticGetValidKeyLength(SIZE_MAX) == enc.MaxKeyLength() && pass1; + + SHACAL2Decryption dec; // 128 to 512-bits (16 to 64-bytes) + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(15) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(64) == 64 && pass2; + pass2 = dec.StaticGetValidKeyLength(65) == 64 && pass2; + pass2 = dec.StaticGetValidKeyLength(128) == 64 && pass2; + pass2 = dec.StaticGetValidKeyLength(0) == dec.MinKeyLength() && pass2; + pass2 = dec.StaticGetValidKeyLength(SIZE_MAX) == dec.MaxKeyLength() && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/shacal2v.dat").c_str(), true, new HexDecoder); + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(16), valdata, 4) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(64), valdata, 10) && pass3; + return pass1 && pass2 && pass3; +} + +bool ValidateARIA() +{ + std::cout << "\nARIA validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + ARIAEncryption enc; + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(24) == 24 && pass1; + pass1 = enc.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(64) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(128) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(0) == enc.MinKeyLength() && pass1; + pass1 = enc.StaticGetValidKeyLength(SIZE_MAX) == enc.MaxKeyLength() && pass1; + + ARIADecryption dec; + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(24) == 24 && pass2; + pass2 = dec.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(64) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(128) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(0) == dec.MinKeyLength() && pass2; + pass2 = dec.StaticGetValidKeyLength(SIZE_MAX) == dec.MaxKeyLength() && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/aria.dat").c_str(), true, new HexDecoder); + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(16), valdata, 15) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(24), valdata, 15) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(32), valdata, 15) && pass3; + return pass1 && pass2 && pass3; +} + +bool ValidateSIMECK() +{ + std::cout << "\nSIMECK validation suite running...\n"; + + return RunTestDataFile("TestVectors/simeck.txt"); +} + +bool ValidateCHAM() +{ + std::cout << "\nCHAM validation suite running...\n"; + + return RunTestDataFile("TestVectors/cham.txt"); +} + +bool ValidateHIGHT() +{ + std::cout << "\nHIGHT validation suite running...\n"; + + return RunTestDataFile("TestVectors/hight.txt"); +} + +bool ValidateLEA() +{ + std::cout << "\nLEA validation suite running...\n"; + + return RunTestDataFile("TestVectors/lea.txt"); +} + +bool ValidateSIMON() +{ + std::cout << "\nSIMON validation suite running...\n"; + + return RunTestDataFile("TestVectors/simon.txt"); +} + +bool ValidateSPECK() +{ + std::cout << "\nSPECK validation suite running...\n"; + + return RunTestDataFile("TestVectors/speck.txt"); +} + +bool ValidateCamellia() +{ + std::cout << "\nCamellia validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true; + + CamelliaEncryption enc; + pass1 = enc.StaticGetValidKeyLength(8) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc.StaticGetValidKeyLength(24) == 24 && pass1; + pass1 = enc.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(64) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(128) == 32 && pass1; + pass1 = enc.StaticGetValidKeyLength(0) == enc.MinKeyLength() && pass1; + pass1 = enc.StaticGetValidKeyLength(SIZE_MAX) == enc.MaxKeyLength() && pass1; + + CamelliaDecryption dec; + pass2 = dec.StaticGetValidKeyLength(8) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec.StaticGetValidKeyLength(24) == 24 && pass2; + pass2 = dec.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(64) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(128) == 32 && pass2; + pass2 = dec.StaticGetValidKeyLength(0) == dec.MinKeyLength() && pass2; + pass2 = dec.StaticGetValidKeyLength(SIZE_MAX) == dec.MaxKeyLength() && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + FileSource valdata(DataDir("TestData/camellia.dat").c_str(), true, new HexDecoder); + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(16), valdata, 15) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(24), valdata, 15) && pass3; + pass3 = BlockTransformationTest(FixedRoundsCipherFactory(32), valdata, 15) && pass3; + return pass1 && pass2 && pass3; +} + +bool ValidateSalsa() +{ + std::cout << "\nSalsa validation suite running...\n"; + + return RunTestDataFile("TestVectors/salsa.txt"); +} + +bool ValidateChaCha() +{ + std::cout << "\nChaCha validation suite running...\n"; + + return RunTestDataFile("TestVectors/chacha.txt"); +} + +bool ValidateChaChaTLS() +{ + std::cout << "\nChaCha-TLS validation suite running...\n"; + + return RunTestDataFile("TestVectors/chacha_tls.txt"); +} + +bool ValidateSosemanuk() +{ + std::cout << "\nSosemanuk validation suite running...\n"; + return RunTestDataFile("TestVectors/sosemanuk.txt"); +} + +bool ValidateRabbit() +{ + std::cout << "\nRabbit validation suite running...\n"; + return RunTestDataFile("TestVectors/rabbit.txt"); +} + +bool ValidateHC128() +{ + std::cout << "\nHC-128 validation suite running...\n"; + return RunTestDataFile("TestVectors/hc128.txt"); +} + +bool ValidateHC256() +{ + std::cout << "\nHC-256 validation suite running...\n"; + return RunTestDataFile("TestVectors/hc256.txt"); +} + +bool ValidateVMAC() +{ + std::cout << "\nVMAC validation suite running...\n"; + return RunTestDataFile("TestVectors/vmac.txt"); +} + +bool ValidateCCM() +{ + std::cout << "\nAES/CCM validation suite running...\n"; + return RunTestDataFile("TestVectors/ccm.txt"); +} + +bool ValidateGCM() +{ + std::cout << "\nAES/GCM validation suite running...\n"; + std::cout << "\n2K tables:"; + bool pass = RunTestDataFile("TestVectors/gcm.txt", MakeParameters(Name::TableSize(), (int)2048)); + std::cout << "\n64K tables:"; + return RunTestDataFile("TestVectors/gcm.txt", MakeParameters(Name::TableSize(), (int)64*1024)) && pass; +} + +bool ValidateXTS() +{ + std::cout << "\nAES/XTS validation suite running...\n"; + return RunTestDataFile("TestVectors/xts.txt"); +} + +bool ValidateCMAC() +{ + std::cout << "\nCMAC validation suite running...\n"; + return RunTestDataFile("TestVectors/cmac.txt"); +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/validat5.cpp b/external/ours/library/crypto/src/shared/original/validat5.cpp new file mode 100755 index 000000000..a35b95626 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/validat5.cpp @@ -0,0 +1,2225 @@ +// validat5.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017. +// Source files split in July 2018 to expedite compiles. + +#include "pch.h" + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "cpu.h" +#include "validate.h" + +#include "aes.h" +#include "crc.h" +#include "adler32.h" + +#include "md2.h" +#include "md4.h" +#include "md5.h" + +#include "sha.h" +#include "sha3.h" +#include "shake.h" +#include "keccak.h" +#include "tiger.h" +#include "blake2.h" +#include "ripemd.h" +#include "siphash.h" +#include "poly1305.h" +#include "whrlpool.h" +#include "lsh.h" + +#include "pssr.h" +#include "hkdf.h" +#include "scrypt.h" +#include "pwdbased.h" + +#include "cmac.h" +#include "dmac.h" +#include "hmac.h" +#include "ttmac.h" + +#include +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +struct HashTestTuple +{ + HashTestTuple(const char *input, const char *output, unsigned int repeatTimes=1) + : input((byte *)input), output((byte *)output), inputLen(strlen(input)), repeatTimes(repeatTimes) {} + + HashTestTuple(const char *input, unsigned int inputLen, const char *output, unsigned int repeatTimes) + : input((byte *)input), output((byte *)output), inputLen(inputLen), repeatTimes(repeatTimes) {} + + const byte *input, *output; + size_t inputLen; + unsigned int repeatTimes; +}; + +bool HashModuleTest(HashTransformation &md, const HashTestTuple *testSet, unsigned int testSetSize) +{ + bool pass=true, fail; + std::ostringstream oss; + + SecByteBlock digest(md.DigestSize()); + for (unsigned int i=0; i r', +// where 'r' is rate and acts like a blockSize, then TruncatedFinal acts +// like a traditional KDF and applies KeccakF1600 core function multiple +// times on state to create the stream. Regarding the NIST test vectors, +// the SHAKE128 KATs do not engage 'd > r'. However, the SHAKE256 KATs +// do engage it. +bool ValidateSHAKE_XOF() +{ + std::cout << "\nSHAKE XOF validation suite running...\n"; + bool pass = true, fail; + + ////// NIST test vectors SHAKE128VariableOut.rsp ////// + + // SHAKE128, COUNT = 0 (first test) + { + std::string m, msg = "84e950051876050dc851fbd99e6247b8"; + std::string o, out = "8599bd89f63a848c49ca593ec37a12c6"; + std::string r; + + StringSource(msg, true, new HexDecoder(new StringSink(m))); + StringSource(out, true, new HexDecoder(new StringSink(o))); + r.resize(o.size()); + + SHAKE128 hash((unsigned int)o.size()); + hash.Update(ConstBytePtr(m), BytePtrSize(m)); + hash.TruncatedFinal(BytePtr(r), BytePtrSize(r)); + + fail = r != o; + pass = pass & !fail; + + if (fail) + std::cout << "FAILED " << "SHAKE128 test COUNT=0" << std::endl; + + pass = pass && !fail; + } + + // SHAKE128, COUNT = 1125 (last test) + { + std::string m, msg = "0a13ad2c7a239b4ba73ea6592ae84ea9"; + std::string o, out = "5feaf99c15f48851943ff9baa6e5055d 8377f0dd347aa4dbece51ad3a6d9ce0c" + "01aee9fe2260b80a4673a909b532adcd d1e421c32d6460535b5fe392a58d2634" + "979a5a104d6c470aa3306c400b061db9 1c463b2848297bca2bc26d1864ba49d7" + "ff949ebca50fbf79a5e63716dc82b600 bd52ca7437ed774d169f6bf02e464879" + "56fba2230f34cd2a0485484d"; + std::string r; + + StringSource(msg, true, new HexDecoder(new StringSink(m))); + StringSource(out, true, new HexDecoder(new StringSink(o))); + r.resize(o.size()); + + SHAKE128 hash((unsigned int)o.size()); + hash.Update(ConstBytePtr(m), BytePtrSize(m)); + hash.TruncatedFinal(BytePtr(r), BytePtrSize(r)); + + fail = r != o; + pass = pass & !fail; + + if (fail) + std::cout << "FAILED " << "SHAKE128 test COUNT=1125" << std::endl; + + pass = pass && !fail; + } + + ////// NIST test vectors SHAKE256VariableOut.rsp ////// + + // SHAKE256, COUNT = 0 (first test) + { + std::string m, msg = "c61a9188812ae73994bc0d6d4021e31b f124dc72669749111232da7ac29e61c4"; + std::string o, out = "23ce"; + std::string r; + + StringSource(msg, true, new HexDecoder(new StringSink(m))); + StringSource(out, true, new HexDecoder(new StringSink(o))); + r.resize(o.size()); + + SHAKE256 hash((unsigned int)o.size()); + hash.Update(ConstBytePtr(m), BytePtrSize(m)); + hash.TruncatedFinal(BytePtr(r), BytePtrSize(r)); + + fail = r != o; + pass = pass & !fail; + + if (fail) + std::cout << "FAILED " << "SHAKE256 test COUNT=0" << std::endl; + + pass = pass && !fail; + } + + // SHAKE256, COUNT = 1245 (last test) + { + std::string m, msg = "8d8001e2c096f1b88e7c9224a086efd4 797fbf74a8033a2d422a2b6b8f6747e4"; + std::string o, out = "2e975f6a8a14f0704d51b13667d8195c 219f71e6345696c49fa4b9d08e9225d3" + "d39393425152c97e71dd24601c11abcf a0f12f53c680bd3ae757b8134a9c10d4" + "29615869217fdd5885c4db174985703a 6d6de94a667eac3023443a8337ae1bc6" + "01b76d7d38ec3c34463105f0d3949d78 e562a039e4469548b609395de5a4fd43" + "c46ca9fd6ee29ada5efc07d84d553249 450dab4a49c483ded250c9338f85cd93" + "7ae66bb436f3b4026e859fda1ca57143 2f3bfc09e7c03ca4d183b741111ca048" + "3d0edabc03feb23b17ee48e844ba2408 d9dcfd0139d2e8c7310125aee801c61a" + "b7900d1efc47c078281766f361c5e611 1346235e1dc38325666c"; + std::string r; + + StringSource(msg, true, new HexDecoder(new StringSink(m))); + StringSource(out, true, new HexDecoder(new StringSink(o))); + r.resize(o.size()); + + SHAKE256 hash((unsigned int)o.size()); + hash.Update(ConstBytePtr(m), BytePtrSize(m)); + hash.TruncatedFinal(BytePtr(r), BytePtrSize(r)); + + fail = r != o; + pass = pass & !fail; + + if (fail) + std::cout << "FAILED " << "SHAKE256 test COUNT=0" << std::endl; + + pass = pass && !fail; + } + + std::cout << (!pass ? "FAILED " : "passed ") << "SHAKE XOF message digests" << std::endl; + + return pass; +} + +bool ValidateTiger() +{ + std::cout << "\nTiger validation suite running...\n\n"; + + HashTestTuple testSet[] = + { + HashTestTuple("", "\x32\x93\xac\x63\x0c\x13\xf0\x24\x5f\x92\xbb\xb1\x76\x6e\x16\x16\x7a\x4e\x58\x49\x2d\xde\x73\xf3"), + HashTestTuple("a", "\x77\xBE\xFB\xEF\x2E\x7E\xF8\xAB\x2E\xC8\xF9\x3B\xF5\x87\xA7\xFC\x61\x3E\x24\x7F\x5F\x24\x78\x09"), + HashTestTuple("abc", "\x2a\xab\x14\x84\xe8\xc1\x58\xf2\xbf\xb8\xc5\xff\x41\xb5\x7a\x52\x51\x29\x13\x1c\x95\x7b\x5f\x93"), + HashTestTuple("Tiger", "\xdd\x00\x23\x07\x99\xf5\x00\x9f\xec\x6d\xeb\xc8\x38\xbb\x6a\x27\xdf\x2b\x9d\x6f\x11\x0c\x79\x37"), + HashTestTuple("message digest", "\xD9\x81\xF8\xCB\x78\x20\x1A\x95\x0D\xCF\x30\x48\x75\x1E\x44\x1C\x51\x7F\xCA\x1A\xA5\x5A\x29\xF6"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\x8d\xce\xa6\x80\xa1\x75\x83\xee\x50\x2b\xa3\x8a\x3c\x36\x86\x51\x89\x0f\xfb\xcc\xdc\x49\xa8\xcc"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", "\xf7\x1c\x85\x83\x90\x2a\xfb\x87\x9e\xdf\xe6\x10\xf8\x2c\x0d\x47\x86\xa3\xa5\x34\x50\x44\x86\xb5"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789", "\x48\xce\xeb\x63\x08\xb8\x7d\x46\xe9\x5d\x65\x61\x12\xcd\xf1\x8d\x97\x91\x5f\x97\x65\x65\x89\x57"), + HashTestTuple("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham", "\x8a\x86\x68\x29\x04\x0a\x41\x0c\x72\x9a\xd2\x3f\x5a\xda\x71\x16\x03\xb3\xcd\xd3\x57\xe4\xc1\x5e"), + HashTestTuple("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.", "\xce\x55\xa6\xaf\xd5\x91\xf5\xeb\xac\x54\x7f\xf8\x4f\x89\x22\x7f\x93\x31\xda\xb0\xb6\x11\xc8\x89"), + HashTestTuple("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.", "\x63\x1a\xbd\xd1\x03\xeb\x9a\x3d\x24\x5b\x6d\xfd\x4d\x77\xb2\x57\xfc\x74\x39\x50\x1d\x15\x68\xdd"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", "\xc5\x40\x34\xe5\xb4\x3e\xb8\x00\x58\x48\xa7\xe0\xae\x6a\xac\x76\xe4\xff\x59\x0a\xe7\x15\xfd\x25") + }; + + Tiger tiger; + + return HashModuleTest(tiger, testSet, COUNTOF(testSet)); +} + +bool ValidateRIPEMD() +{ + HashTestTuple testSet128[] = + { + HashTestTuple("", "\xcd\xf2\x62\x13\xa1\x50\xdc\x3e\xcb\x61\x0f\x18\xf6\xb3\x8b\x46"), + HashTestTuple("a", "\x86\xbe\x7a\xfa\x33\x9d\x0f\xc7\xcf\xc7\x85\xe7\x2f\x57\x8d\x33"), + HashTestTuple("abc", "\xc1\x4a\x12\x19\x9c\x66\xe4\xba\x84\x63\x6b\x0f\x69\x14\x4c\x77"), + HashTestTuple("message digest", "\x9e\x32\x7b\x3d\x6e\x52\x30\x62\xaf\xc1\x13\x2d\x7d\xf9\xd1\xb8"), + HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xfd\x2a\xa6\x07\xf7\x1d\xc8\xf5\x10\x71\x49\x22\xb3\x71\x83\x4e"), + HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\xa1\xaa\x06\x89\xd0\xfa\xfa\x2d\xdc\x22\xe8\x8b\x49\x13\x3a\x06"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xd1\xe9\x59\xeb\x17\x9c\x91\x1f\xae\xa4\x62\x4c\x60\xc5\xc7\x02"), + HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x3f\x45\xef\x19\x47\x32\xc2\xdb\xb2\xc4\xa2\xc7\x69\x79\x5f\xa3"), + HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\x4a\x7f\x57\x23\xf9\x54\xeb\xa1\x21\x6c\x9d\x8f\x63\x20\x43\x1f", 15625) + }; + + HashTestTuple testSet160[] = + { + HashTestTuple("", "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31"), + HashTestTuple("a", "\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe"), + HashTestTuple("abc", "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04\x4a\x8e\x98\xc6\xb0\x87\xf1\x5a\x0b\xfc"), + HashTestTuple("message digest", "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36"), + HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xf7\x1c\x27\x10\x9c\x69\x2c\x1b\x56\xbb\xdc\xeb\x5b\x9d\x28\x65\xb3\x70\x8d\xbc"), + HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05\xa0\x6c\x27\xdc\xf4\x9a\xda\x62\xeb\x2b"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xb0\xe2\x0b\x6e\x31\x16\x64\x02\x86\xed\x3a\x87\xa5\x71\x30\x79\xb2\x1f\x51\x89"), + HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x9b\x75\x2e\x45\x57\x3d\x4b\x39\xf4\xdb\xd3\x32\x3c\xab\x82\xbf\x63\x32\x6b\xfb"), + HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\x52\x78\x32\x43\xc1\x69\x7b\xdb\xe1\x6d\x37\xf9\x7f\x68\xf0\x83\x25\xdc\x15\x28", 15625) + }; + + HashTestTuple testSet256[] = + { + HashTestTuple("", "\x02\xba\x4c\x4e\x5f\x8e\xcd\x18\x77\xfc\x52\xd6\x4d\x30\xe3\x7a\x2d\x97\x74\xfb\x1e\x5d\x02\x63\x80\xae\x01\x68\xe3\xc5\x52\x2d"), + HashTestTuple("a", "\xf9\x33\x3e\x45\xd8\x57\xf5\xd9\x0a\x91\xba\xb7\x0a\x1e\xba\x0c\xfb\x1b\xe4\xb0\x78\x3c\x9a\xcf\xcd\x88\x3a\x91\x34\x69\x29\x25"), + HashTestTuple("abc", "\xaf\xbd\x6e\x22\x8b\x9d\x8c\xbb\xce\xf5\xca\x2d\x03\xe6\xdb\xa1\x0a\xc0\xbc\x7d\xcb\xe4\x68\x0e\x1e\x42\xd2\xe9\x75\x45\x9b\x65"), + HashTestTuple("message digest", "\x87\xe9\x71\x75\x9a\x1c\xe4\x7a\x51\x4d\x5c\x91\x4c\x39\x2c\x90\x18\xc7\xc4\x6b\xc1\x44\x65\x55\x4a\xfc\xdf\x54\xa5\x07\x0c\x0e"), + HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\x64\x9d\x30\x34\x75\x1e\xa2\x16\x77\x6b\xf9\xa1\x8a\xcc\x81\xbc\x78\x96\x11\x8a\x51\x97\x96\x87\x82\xdd\x1f\xd9\x7d\x8d\x51\x33"), + HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\x38\x43\x04\x55\x83\xaa\xc6\xc8\xc8\xd9\x12\x85\x73\xe7\xa9\x80\x9a\xfb\x2a\x0f\x34\xcc\xc3\x6e\xa9\xe7\x2f\x16\xf6\x36\x8e\x3f"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\x57\x40\xa4\x08\xac\x16\xb7\x20\xb8\x44\x24\xae\x93\x1c\xbb\x1f\xe3\x63\xd1\xd0\xbf\x40\x17\xf1\xa8\x9f\x7e\xa6\xde\x77\xa0\xb8"), + HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x06\xfd\xcc\x7a\x40\x95\x48\xaa\xf9\x13\x68\xc0\x6a\x62\x75\xb5\x53\xe3\xf0\x99\xbf\x0e\xa4\xed\xfd\x67\x78\xdf\x89\xa8\x90\xdd"), + HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\xac\x95\x37\x44\xe1\x0e\x31\x51\x4c\x15\x0d\x4d\x8d\x7b\x67\x73\x42\xe3\x33\x99\x78\x82\x96\xe4\x3a\xe4\x85\x0c\xe4\xf9\x79\x78", 15625) + }; + + HashTestTuple testSet320[] = + { + HashTestTuple("", "\x22\xd6\x5d\x56\x61\x53\x6c\xdc\x75\xc1\xfd\xf5\xc6\xde\x7b\x41\xb9\xf2\x73\x25\xeb\xc6\x1e\x85\x57\x17\x7d\x70\x5a\x0e\xc8\x80\x15\x1c\x3a\x32\xa0\x08\x99\xb8"), + HashTestTuple("a", "\xce\x78\x85\x06\x38\xf9\x26\x58\xa5\xa5\x85\x09\x75\x79\x92\x6d\xda\x66\x7a\x57\x16\x56\x2c\xfc\xf6\xfb\xe7\x7f\x63\x54\x2f\x99\xb0\x47\x05\xd6\x97\x0d\xff\x5d"), + HashTestTuple("abc", "\xde\x4c\x01\xb3\x05\x4f\x89\x30\xa7\x9d\x09\xae\x73\x8e\x92\x30\x1e\x5a\x17\x08\x5b\xef\xfd\xc1\xb8\xd1\x16\x71\x3e\x74\xf8\x2f\xa9\x42\xd6\x4c\xdb\xc4\x68\x2d"), + HashTestTuple("message digest", "\x3a\x8e\x28\x50\x2e\xd4\x5d\x42\x2f\x68\x84\x4f\x9d\xd3\x16\xe7\xb9\x85\x33\xfa\x3f\x2a\x91\xd2\x9f\x84\xd4\x25\xc8\x8d\x6b\x4e\xff\x72\x7d\xf6\x6a\x7c\x01\x97"), + HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xca\xbd\xb1\x81\x0b\x92\x47\x0a\x20\x93\xaa\x6b\xce\x05\x95\x2c\x28\x34\x8c\xf4\x3f\xf6\x08\x41\x97\x51\x66\xbb\x40\xed\x23\x40\x04\xb8\x82\x44\x63\xe6\xb0\x09"), + HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\xd0\x34\xa7\x95\x0c\xf7\x22\x02\x1b\xa4\xb8\x4d\xf7\x69\xa5\xde\x20\x60\xe2\x59\xdf\x4c\x9b\xb4\xa4\x26\x8c\x0e\x93\x5b\xbc\x74\x70\xa9\x69\xc9\xd0\x72\xa1\xac"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xed\x54\x49\x40\xc8\x6d\x67\xf2\x50\xd2\x32\xc3\x0b\x7b\x3e\x57\x70\xe0\xc6\x0c\x8c\xb9\xa4\xca\xfe\x3b\x11\x38\x8a\xf9\x92\x0e\x1b\x99\x23\x0b\x84\x3c\x86\xa4"), + HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x55\x78\x88\xaf\x5f\x6d\x8e\xd6\x2a\xb6\x69\x45\xc6\xd2\xa0\xa4\x7e\xcd\x53\x41\xe9\x15\xeb\x8f\xea\x1d\x05\x24\x95\x5f\x82\x5d\xc7\x17\xe4\xa0\x08\xab\x2d\x42"), + HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\xbd\xee\x37\xf4\x37\x1e\x20\x64\x6b\x8b\x0d\x86\x2d\xda\x16\x29\x2a\xe3\x6f\x40\x96\x5e\x8c\x85\x09\xe6\x3d\x1d\xbd\xde\xcc\x50\x3e\x2b\x63\xeb\x92\x45\xbb\x66", 15625) + }; + + bool pass = true; + + std::cout << "\nRIPEMD-128 validation suite running...\n\n"; + RIPEMD128 md128; + pass = HashModuleTest(md128, testSet128, COUNTOF(testSet128)) && pass; + + std::cout << "\nRIPEMD-160 validation suite running...\n\n"; + RIPEMD160 md160; + pass = HashModuleTest(md160, testSet160, COUNTOF(testSet160)) && pass; + + std::cout << "\nRIPEMD-256 validation suite running...\n\n"; + RIPEMD256 md256; + pass = HashModuleTest(md256, testSet256, COUNTOF(testSet256)) && pass; + + std::cout << "\nRIPEMD-320 validation suite running...\n\n"; + RIPEMD320 md320; + pass = HashModuleTest(md320, testSet320, COUNTOF(testSet320)) && pass; + + return pass; +} + +#ifdef CRYPTOPP_REMOVED +bool ValidateHAVAL() +{ + HashTestTuple testSet[] = + { + HashTestTuple("", "\xC6\x8F\x39\x91\x3F\x90\x1F\x3D\xDF\x44\xC7\x07\x35\x7A\x7D\x70"), + HashTestTuple("a", "\x4D\xA0\x8F\x51\x4A\x72\x75\xDB\xC4\xCE\xCE\x4A\x34\x73\x85\x98\x39\x83\xA8\x30"), + HashTestTuple("HAVAL", "\x0C\x13\x96\xD7\x77\x26\x89\xC4\x67\x73\xF3\xDA\xAC\xA4\xEF\xA9\x82\xAD\xBF\xB2\xF1\x46\x7E\xEA"), + HashTestTuple("0123456789", "\xBE\xBD\x78\x16\xF0\x9B\xAE\xEC\xF8\x90\x3B\x1B\x9B\xC6\x72\xD9\xFA\x42\x8E\x46\x2B\xA6\x99\xF8\x14\x84\x15\x29"), + HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xC9\xC7\xD8\xAF\xA1\x59\xFD\x9E\x96\x5C\xB8\x3F\xF5\xEE\x6F\x58\xAE\xDA\x35\x2C\x0E\xFF\x00\x55\x48\x15\x3A\x61\x55\x1C\x38\xEE"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xB4\x5C\xB6\xE6\x2F\x2B\x13\x20\xE4\xF8\xF1\xB0\xB2\x73\xD4\x5A\xDD\x47\xC3\x21\xFD\x23\x99\x9D\xCF\x40\x3A\xC3\x76\x36\xD9\x63") + }; + + bool pass=true; + + std::cout << "\nHAVAL validation suite running...\n\n"; + { + HAVAL3 md(16); + pass = HashModuleTest(md, testSet+0, 1) && pass; + } + { + HAVAL3 md(20); + pass = HashModuleTest(md, testSet+1, 1) && pass; + } + { + HAVAL4 md(24); + pass = HashModuleTest(md, testSet+2, 1) && pass; + } + { + HAVAL4 md(28); + pass = HashModuleTest(md, testSet+3, 1) && pass; + } + { + HAVAL5 md(32); + pass = HashModuleTest(md, testSet+4, 1) && pass; + } + { + HAVAL5 md(32); + pass = HashModuleTest(md, testSet+5, 1) && pass; + } + + return pass; +} +#endif + +bool ValidatePanama() +{ + std::cout << "\nPanama validation suite running...\n"; + return RunTestDataFile("TestVectors/panama.txt"); +} + +bool ValidateWhirlpool() +{ + std::cout << "\nWhirlpool validation suite running...\n"; + return RunTestDataFile("TestVectors/whrlpool.txt"); +} + +bool ValidateLSH() +{ + std::cout << "\nLSH validation suite running...\n"; + return RunTestDataFile("TestVectors/lsh.txt"); +} + +#ifdef CRYPTOPP_REMOVED +bool ValidateMD5MAC() +{ + const byte keys[2][MD5MAC::KEYLENGTH]={ + {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}, + {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}}; + + const char *TestVals[7]={ + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}; + + const byte output[2][7][MD5MAC::DIGESTSIZE]={ + {{0x1f,0x1e,0xf2,0x37,0x5c,0xc0,0xe0,0x84,0x4f,0x98,0xe7,0xe8,0x11,0xa3,0x4d,0xa8}, + {0x7a,0x76,0xee,0x64,0xca,0x71,0xef,0x23,0x7e,0x26,0x29,0xed,0x94,0x52,0x73,0x65}, + {0xe8,0x01,0x3c,0x11,0xf7,0x20,0x9d,0x13,0x28,0xc0,0xca,0xa0,0x4f,0xd0,0x12,0xa6}, + {0xc8,0x95,0x53,0x4f,0x22,0xa1,0x74,0xbc,0x3e,0x6a,0x25,0xa2,0xb2,0xef,0xd6,0x30}, + {0x91,0x72,0x86,0x7e,0xb6,0x00,0x17,0x88,0x4c,0x6f,0xa8,0xcc,0x88,0xeb,0xe7,0xc9}, + {0x3b,0xd0,0xe1,0x1d,0x5e,0x09,0x4c,0xb7,0x1e,0x35,0x44,0xac,0xa9,0xb8,0xbf,0xa2}, + {0x93,0x37,0x16,0x64,0x44,0xcc,0x95,0x35,0xb7,0xd5,0xb8,0x0f,0x91,0xe5,0x29,0xcb}}, + {{0x2f,0x6e,0x73,0x13,0xbf,0xbb,0xbf,0xcc,0x3a,0x2d,0xde,0x26,0x8b,0x59,0xcc,0x4d}, + {0x69,0xf6,0xca,0xff,0x40,0x25,0x36,0xd1,0x7a,0xe1,0x38,0x03,0x2c,0x0c,0x5f,0xfd}, + {0x56,0xd3,0x2b,0x6c,0x34,0x76,0x65,0xd9,0x74,0xd6,0xf7,0x5c,0x3f,0xc6,0xf0,0x40}, + {0xb8,0x02,0xb2,0x15,0x4e,0x59,0x8b,0x6f,0x87,0x60,0x56,0xc7,0x85,0x46,0x2c,0x0b}, + {0x5a,0xde,0xf4,0xbf,0xf8,0x04,0xbe,0x08,0x58,0x7e,0x94,0x41,0xcf,0x6d,0xbd,0x57}, + {0x18,0xe3,0x49,0xa5,0x24,0x44,0xb3,0x0e,0x5e,0xba,0x5a,0xdd,0xdc,0xd9,0xf1,0x8d}, + {0xf2,0xb9,0x06,0xa5,0xb8,0x4b,0x9b,0x4b,0xbe,0x95,0xed,0x32,0x56,0x4e,0xe7,0xeb}}}; + + byte digest[MD5MAC::DIGESTSIZE]; + bool pass=true, fail; + std::ostringstream oss; + + oss << "\nMD5MAC validation suite running...\n"; + + for (int k=0; k<2; k++) + { + MD5MAC mac(keys[k]); + oss << "\nKEY: "; + for (int j=0;j XMACC_MD5; + + const byte keys[2][XMACC_MD5::KEYLENGTH]={ + {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb}, + {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98}}; + + const word32 counters[2]={0xccddeeff, 0x76543210}; + + const char *TestVals[7]={ + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}; + + const byte output[2][7][XMACC_MD5::DIGESTSIZE]={ + {{0xcc,0xdd,0xef,0x00,0xfa,0x89,0x54,0x92,0x86,0x32,0xda,0x2a,0x3f,0x29,0xc5,0x52,0xa0,0x0d,0x05,0x13}, + {0xcc,0xdd,0xef,0x01,0xae,0xdb,0x8b,0x7b,0x69,0x71,0xc7,0x91,0x71,0x48,0x9d,0x18,0xe7,0xdf,0x9d,0x5a}, + {0xcc,0xdd,0xef,0x02,0x5e,0x01,0x2e,0x2e,0x4b,0xc3,0x83,0x62,0xc2,0xf4,0xe6,0x18,0x1c,0x44,0xaf,0xca}, + {0xcc,0xdd,0xef,0x03,0x3e,0xa9,0xf1,0xe0,0x97,0x91,0xf8,0xe2,0xbe,0xe0,0xdf,0xf3,0x41,0x03,0xb3,0x5a}, + {0xcc,0xdd,0xef,0x04,0x2e,0x6a,0x8d,0xb9,0x72,0xe3,0xce,0x9f,0xf4,0x28,0x45,0xe7,0xbc,0x80,0xa9,0xc7}, + {0xcc,0xdd,0xef,0x05,0x1a,0xd5,0x40,0x78,0xfb,0x16,0x37,0xfc,0x7a,0x1d,0xce,0xb4,0x77,0x10,0xb2,0xa0}, + {0xcc,0xdd,0xef,0x06,0x13,0x2f,0x11,0x47,0xd7,0x1b,0xb5,0x52,0x36,0x51,0x26,0xb0,0x96,0xd7,0x60,0x81}}, + {{0x76,0x54,0x32,0x11,0xe9,0xcb,0x74,0x32,0x07,0x93,0xfe,0x01,0xdd,0x27,0xdb,0xde,0x6b,0x77,0xa4,0x56}, + {0x76,0x54,0x32,0x12,0xcd,0x55,0x87,0x5c,0xc0,0x35,0x85,0x99,0x44,0x02,0xa5,0x0b,0x8c,0xe7,0x2c,0x68}, + {0x76,0x54,0x32,0x13,0xac,0xfd,0x87,0x50,0xc3,0x8f,0xcd,0x58,0xaa,0xa5,0x7e,0x7a,0x25,0x63,0x26,0xd1}, + {0x76,0x54,0x32,0x14,0xe3,0x30,0xf5,0xdd,0x27,0x2b,0x76,0x22,0x7f,0xaa,0x90,0x73,0x6a,0x48,0xdb,0x00}, + {0x76,0x54,0x32,0x15,0xfc,0x57,0x00,0x20,0x7c,0x9d,0xf6,0x30,0x6f,0xbd,0x46,0x3e,0xfb,0x8a,0x2c,0x60}, + {0x76,0x54,0x32,0x16,0xfb,0x0f,0xd3,0xdf,0x4c,0x4b,0xc3,0x05,0x9d,0x63,0x1e,0xba,0x25,0x2b,0xbe,0x35}, + {0x76,0x54,0x32,0x17,0xc6,0xfe,0xe6,0x5f,0xb1,0x35,0x8a,0xf5,0x32,0x7a,0x80,0xbd,0xb8,0x72,0xee,0xae}}}; + + // Coverity finding, also see http://stackoverflow.com/a/34509163/608639. + StreamState ss(std::cout); + + byte digest[XMACC_MD5::DIGESTSIZE]; + bool pass=true, fail; + + std::cout << "\nXMACC/MD5 validation suite running...\n"; + + for (int k=0; k<2; k++) + { + XMACC_MD5 mac(keys[k], counters[k]); + std::cout << "\nKEY: "; + for (int j=0;j pbkdf; + + std::cout << "\nPKCS #12 PBKDF validation suite running...\n\n"; + pass = TestPBKDF(pbkdf, testSet, COUNTOF(testSet)) && pass; + } + + { + // from draft-ietf-smime-password-03.txt, at http://www.imc.org/draft-ietf-smime-password + PBKDF_TestTuple testSet[] = + { + {0, 5, "70617373776f7264", "1234567878563412", "D1DAA78615F287E6"}, + {0, 500, "416C6C206E2D656E746974696573206D75737420636F6D6D756E69636174652077697468206F74686572206E2d656E74697469657320766961206E2D3120656E746974656568656568656573", "1234567878563412","6A8970BF68C92CAEA84A8DF28510858607126380CC47AB2D"} + }; + + PKCS5_PBKDF2_HMAC pbkdf; + + std::cout << "\nPKCS #5 PBKDF2 validation suite running...\n\n"; + pass = TestPBKDF(pbkdf, testSet, COUNTOF(testSet)) && pass; + } + + return pass; +} + +struct HKDF_TestTuple +{ + const char *hexSecret, *hexSalt, *hexInfo, *hexExpected; + size_t len; +}; + +bool TestHKDF(KeyDerivationFunction &kdf, const HKDF_TestTuple *testSet, unsigned int testSetSize) +{ + bool pass = true; + + for (unsigned int i=0; i") : ""); + std::cout << " "; + std::cout << (tuple.hexInfo ? (strlen(tuple.hexInfo) ? tuple.hexInfo : "<0-LEN INFO>") : ""); + std::cout << " "; + enc.Put(derived, derived.size()); + std::cout << std::endl; + } + + return pass; +} + +bool ValidateHKDF() +{ + bool pass = true; + + { + // SHA-1 from RFC 5869, Appendix A, https://tools.ietf.org/html/rfc5869 + const HKDF_TestTuple testSet[] = + { + // Test Case #4 + {"0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", "085a01ea1b10f36933068b56efa5ad81 a4f14b822f5b091568a9cdd4f155fda2 c22e422478d305f3f896", 42}, + // Test Case #5 + {"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "0bd770a74d1160f7c9f12cd5912a06eb ff6adcae899d92191fe4305673ba2ffe 8fa3f1a4e5ad79f3f334b3b202b2173c 486ea37ce3d397ed034c7f9dfeb15c5e 927336d0441f4c4300e2cff0d0900b52 d3b4", 82}, + // Test Case #6 + {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", "0ac1af7002b3d761d1e55298da9d0506 b9ae52057220a306e07b6b87e8df21d0 ea00033de03984d34918", 42}, + // Test Case #7 + {"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", NULLPTR, "", "2c91117204d745f3500d636a62f64f0 ab3bae548aa53d423b0d1f27ebba6f5e5 673a081d70cce7acfc48", 42} + }; + + HKDF hkdf; + + std::cout << "\nRFC 5869 HKDF(SHA-1) validation suite running...\n\n"; + pass = TestHKDF(hkdf, testSet, COUNTOF(testSet)) && pass; + } + + { + // SHA-256 from RFC 5869, Appendix A, https://tools.ietf.org/html/rfc5869 + const HKDF_TestTuple testSet[] = + { + // Test Case #1 + {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", "3cb25f25faacd57a90434f64d0362f2a 2d2d0a90cf1a5a4c5db02d56ecc4c5bf 34007208d5b887185865", 42}, + // Test Case #2 + {"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "b11e398dc80327a1c8e7f78c596a4934 4f012eda2d4efad8a050cc4c19afa97c 59045a99cac7827271cb41c65e590e09 da3275600c2f09b8367793a9aca3db71 cc30c58179ec3e87c14c01d5c1f3434f 1d87", 82}, + // Test Case #3 + {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", "8da4e775a563c18f715f802a063c5a31 b8a11f5c5ee1879ec3454e5f3c738d2d 9d201395faa4b61a96c8", 42} + }; + + HKDF hkdf; + + std::cout << "\nRFC 5869 HKDF(SHA-256) validation suite running...\n\n"; + pass = TestHKDF(hkdf, testSet, COUNTOF(testSet)) && pass; + } + + { + // SHA-512, Crypto++ generated, based on RFC 5869, https://tools.ietf.org/html/rfc5869 + const HKDF_TestTuple testSet[] = + { + // Test Case #0 + {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", "832390086CDA71FB47625BB5CEB168E4 C8E26A1A16ED34D9FC7FE92C14815793 38DA362CB8D9F925D7CB", 42}, + // Test Case #0 + {"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "CE6C97192805B346E6161E821ED16567 3B84F400A2B514B2FE23D84CD189DDF1 B695B48CBD1C8388441137B3CE28F16A A64BA33BA466B24DF6CFCB021ECFF235 F6A2056CE3AF1DE44D572097A8505D9E 7A93", 82}, + // Test Case #0 + {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", "F5FA02B18298A72A8C23898A8703472C 6EB179DC204C03425C970E3B164BF90F FF22D04836D0E2343BAC", 42}, + // Test Case #0 + {"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", NULLPTR, "", "1407D46013D98BC6DECEFCFEE55F0F90 B0C7F63D68EB1A80EAF07E953CFC0A3A 5240A155D6E4DAA965BB", 42} + }; + + HKDF hkdf; + + std::cout << "\nRFC 5869 HKDF(SHA-512) validation suite running...\n\n"; + pass = TestHKDF(hkdf, testSet, COUNTOF(testSet)) && pass; + } + + { + // Whirlpool, Crypto++ generated, based on RFC 5869, https://tools.ietf.org/html/rfc5869 + const HKDF_TestTuple testSet[] = + { + // Test Case #0 + {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", "0D29F74CCD8640F44B0DD9638111C1B5 766EFED752AF358109E2E7C9CD4A28EF 2F90B2AD461FBA0744D4", 42}, + // Test Case #0 + {"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "4EBE4FE2DCCEC42661699500BE279A99 3FED90351E19373B3926FAA3A410700B2 BBF77E254CF1451AE6068D64A0904D96 6F4FF25498445A501B88F50D21E3A68A8 90E09445DC5886DD00E7F4F7C58A5121 70", 82}, + // Test Case #0 + {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", "110632D0F7AEFAC31771FC66C22BB346 2614B81E4B04BA7F2B662E0BD694F564 58615F9A9CB56C57ECF2", 42}, + // Test Case #0 + {"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c" /*key*/, NULLPTR /*salt*/, "" /*info*/, "4089286EBFB23DD8A02F0C9DAA35D538 EB09CD0A8CBAB203F39083AA3E0BD313 E6F91E64F21A187510B0", 42} + }; + + HKDF hkdf; + + std::cout << "\nRFC 5869 HKDF(Whirlpool) validation suite running...\n\n"; + pass = TestHKDF(hkdf, testSet, COUNTOF(testSet)) && pass; + } + + return pass; +} + +struct Scrypt_TestTuple +{ + const char * passwd; + const char * salt; + word64 n; + word32 r; + word32 p; + const char * expect; +}; + +bool TestScrypt(KeyDerivationFunction &pbkdf, const Scrypt_TestTuple *testSet, unsigned int testSetSize) +{ + bool pass = true; + + for (unsigned int i=0; i::StaticAlgorithmName() != "Poly1305(AES)"); + std::cout << (fail ? "FAILED " : "passed ") << "algorithm name\n"; + pass = pass && !fail; + } + + // Test data from http://cr.yp.to/mac/poly1305-20050329.pdf + const Poly1305_TestTuples tests[] = + { + // Appendix B, Test 1 + { + "\xec\x07\x4c\x83\x55\x80\x74\x17\x01\x42\x5b\x62\x32\x35\xad\xd6" // Key + "\x85\x1f\xc4\x0c\x34\x67\xac\x0b\xe0\x5c\xc2\x04\x04\xf3\xf7\x00", + "\xf3\xf6", // Message + "\xfb\x44\x73\x50\xc4\xe8\x68\xc5\x2a\xc3\x27\x5c\xf9\xd4\x32\x7e", // Nonce + "\xf4\xc6\x33\xc3\x04\x4f\xc1\x45\xf8\x4f\x33\x5c\xb8\x19\x53\xde", // Digest + 32, 2, 16, 16 + }, + // Appendix B, Test 2 + { + "\x75\xde\xaa\x25\xc0\x9f\x20\x8e\x1d\xc4\xce\x6b\x5c\xad\x3f\xbf" // Key + "\x61\xee\x09\x21\x8d\x29\xb0\xaa\xed\x7e\x15\x4a\x2c\x55\x09\xcc", + "", // Message + "\x61\xee\x09\x21\x8d\x29\xb0\xaa\xed\x7e\x15\x4a\x2c\x55\x09\xcc", // Nonce + "\xdd\x3f\xab\x22\x51\xf1\x1a\xc7\x59\xf0\x88\x71\x29\xcc\x2e\xe7", // Digest + 32, 0, 16, 16 + }, + // Appendix B, Test 3 + { + "\x6a\xcb\x5f\x61\xa7\x17\x6d\xd3\x20\xc5\xc1\xeb\x2e\xdc\xdc\x74" // Key + "\x48\x44\x3d\x0b\xb0\xd2\x11\x09\xc8\x9a\x10\x0b\x5c\xe2\xc2\x08", + "\x66\x3c\xea\x19\x0f\xfb\x83\xd8\x95\x93\xf3\xf4\x76\xb6\xbc\x24" // Message + "\xd7\xe6\x79\x10\x7e\xa2\x6a\xdb\x8c\xaf\x66\x52\xd0\x65\x61\x36", + "\xae\x21\x2a\x55\x39\x97\x29\x59\x5d\xea\x45\x8b\xc6\x21\xff\x0e", // Nonce + "\x0e\xe1\xc1\x6b\xb7\x3f\x0f\x4f\xd1\x98\x81\x75\x3c\x01\xcd\xbe", // Digest + 32, 32, 16, 16 + }, + // Appendix B, Test 4 + { + "\xe1\xa5\x66\x8a\x4d\x5b\x66\xa5\xf6\x8c\xc5\x42\x4e\xd5\x98\x2d" // Key + "\x12\x97\x6a\x08\xc4\x42\x6d\x0c\xe8\xa8\x24\x07\xc4\xf4\x82\x07", + "\xab\x08\x12\x72\x4a\x7f\x1e\x34\x27\x42\xcb\xed\x37\x4d\x94\xd1" // Message + "\x36\xc6\xb8\x79\x5d\x45\xb3\x81\x98\x30\xf2\xc0\x44\x91\xfa\xf0" + "\x99\x0c\x62\xe4\x8b\x80\x18\xb2\xc3\xe4\xa0\xfa\x31\x34\xcb\x67" + "\xfa\x83\xe1\x58\xc9\x94\xd9\x61\xc4\xcb\x21\x09\x5c\x1b\xf9", + "\x9a\xe8\x31\xe7\x43\x97\x8d\x3a\x23\x52\x7c\x71\x28\x14\x9e\x3a", // Nonce + "\x51\x54\xad\x0d\x2c\xb2\x6e\x01\x27\x4f\xc5\x11\x48\x49\x1f\x1b", // Digest + 32, 63, 16, 16 + } + }; + + unsigned int count = 0; + byte digest[Poly1305::DIGESTSIZE]; + + // Positive tests + for (unsigned int i=0; i poly1305((const byte*)tests[i].key, tests[i].klen); + poly1305.Resynchronize((const byte*)tests[i].nonce, (int)tests[i].nlen); + poly1305.Update((const byte*)tests[i].message, tests[i].mlen); + poly1305.Final(digest); + + fail = memcmp(digest, tests[i].digest, tests[i].dlen) != 0; + if (fail) + { + std::cout << "FAILED " << "Poly1305 test set " << count << std::endl; + } + + count++; + pass = pass && !fail; + } + + // Positive tests + for (unsigned int i=0; i poly1305((const byte*)tests[i].key, tests[i].klen,(const byte*)tests[i].nonce, (int)tests[i].nlen); + poly1305.Update((const byte*)tests[i].message, tests[i].mlen); + poly1305.Final(digest); + + fail = memcmp(digest, tests[i].digest, tests[i].dlen) != 0; + if (fail) + { + std::cout << "FAILED " << "Poly1305 test set " << count << std::endl; + } + + count++; + pass = pass && !fail; + } + + // Negative tests + for (unsigned int i=0; i poly1305((const byte*)tests[i].key, tests[i].klen); + poly1305.Resynchronize((const byte*)tests[i].nonce, (int)tests[i].nlen); + poly1305.Update((const byte*)tests[i].message, tests[i].mlen); + poly1305.Final(digest); + + unsigned int next = (i+1) % COUNTOF(tests); + fail = memcmp(digest, tests[next].digest, tests[next].dlen) == 0; + if (fail) + { + std::cout << "FAILED " << "Poly1305 test set " << count << std::endl; + } + + count++; + pass = pass && !fail; + } + + std::cout << (!pass ? "FAILED " : "passed ") << count << " message authentication codes" << std::endl; + + return pass; +} + +bool ValidateSipHash() +{ + std::cout << "\nSipHash validation suite running...\n\n"; + bool fail, pass = true, pass1=true, pass2=true, pass3=true, pass4=true; + + { + fail = (SipHash<2,4>::StaticAlgorithmName() != "SipHash-2-4"); + std::cout << (fail ? "FAILED " : "passed ") << "SipHash-2-4 algorithm name\n"; + pass = pass && !fail; + + fail = (SipHash<2,4, false>::DIGESTSIZE != 8); + std::cout << (fail ? "FAILED " : "passed ") << "SipHash-2-4 64-bit digest size\n"; + pass = pass && !fail; + + fail = (SipHash<2,4, true>::DIGESTSIZE != 16); + std::cout << (fail ? "FAILED " : "passed ") << "SipHash-2-4 128-bit digest size\n"; + pass = pass && !fail; + + fail = (SipHash<4,8>::StaticAlgorithmName() != "SipHash-4-8"); + std::cout << (fail ? "FAILED " : "passed ") << "SipHash-4-8 algorithm name\n"; + pass = pass && !fail; + + fail = (SipHash<4,8, false>::DIGESTSIZE != 8); + std::cout << (fail ? "FAILED " : "passed ") << "SipHash-4-8 64-bit digest size\n"; + pass = pass && !fail; + + fail = (SipHash<4,8, true>::DIGESTSIZE != 16); + std::cout << (fail ? "FAILED " : "passed ") << "SipHash-4-8 128-bit digest size\n"; + pass = pass && !fail; + } + + // Siphash-2-4, 64-bit MAC + { + const byte key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; + SipHash<2,4, false> hash(key, 16); + byte digest[SipHash<2,4, false>::DIGESTSIZE]; + + hash.Update((const byte*)"", 0); + hash.Final(digest); + fail = memcmp("\x31\x0E\x0E\xDD\x47\xDB\x6F\x72", digest, COUNTOF(digest)) != 0; + pass1 = !fail && pass1; + + hash.Update((const byte*)"\x00", 1); + hash.Final(digest); + fail = memcmp("\xFD\x67\xDC\x93\xC5\x39\xF8\x74", digest, COUNTOF(digest)) != 0; + pass1 = !fail && pass1; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06", 7); + hash.Final(digest); + fail = memcmp("\x37\xD1\x01\x8B\xF5\x00\x02\xAB", digest, COUNTOF(digest)) != 0; + pass1 = !fail && pass1; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07", 8); + hash.Final(digest); + fail = memcmp("\x62\x24\x93\x9A\x79\xF5\xF5\x93", digest, COUNTOF(digest)) != 0; + pass1 = !fail && pass1; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08", 9); + hash.Final(digest); + fail = memcmp("\xB0\xE4\xA9\x0B\xDF\x82\x00\x9E", digest, COUNTOF(digest)) != 0; + pass1 = !fail && pass1; + + std::cout << (pass1 ? "passed " : "FAILED ") << "SipHash-2-4 64-bit MAC\n"; + pass = pass1 && pass; + } + + // Siphash-2-4, 128-bit MAC + { + const byte key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; + SipHash<2,4, true> hash(key, 16); + byte digest[SipHash<2,4, true>::DIGESTSIZE]; + + hash.Update((const byte*)"", 0); + hash.Final(digest); + fail = memcmp("\xA3\x81\x7F\x04\xBA\x25\xA8\xE6\x6D\xF6\x72\x14\xC7\x55\x02\x93", digest, COUNTOF(digest)) != 0; + pass3 = !fail && pass3; + + hash.Update((const byte*)"\x00", 1); + hash.Final(digest); + fail = memcmp("\xDA\x87\xC1\xD8\x6B\x99\xAF\x44\x34\x76\x59\x11\x9B\x22\xFC\x45", digest, COUNTOF(digest)) != 0; + pass3 = !fail && pass3; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06", 7); + hash.Final(digest); + fail = memcmp("\xA1\xF1\xEB\xBE\xD8\xDB\xC1\x53\xC0\xB8\x4A\xA6\x1F\xF0\x82\x39", digest, COUNTOF(digest)) != 0; + pass3 = !fail && pass3; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07", 8); + hash.Final(digest); + fail = memcmp("\x3B\x62\xA9\xBA\x62\x58\xF5\x61\x0F\x83\xE2\x64\xF3\x14\x97\xB4", digest, COUNTOF(digest)) != 0; + pass3 = !fail && pass3; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08", 9); + hash.Final(digest); + fail = memcmp("\x26\x44\x99\x06\x0A\xD9\xBA\xAB\xC4\x7F\x8B\x02\xBB\x6D\x71\xED", digest, COUNTOF(digest)) != 0; + pass3 = !fail && pass3; + + std::cout << (pass3 ? "passed " : "FAILED ") << "SipHash-2-4 128-bit MAC\n"; + pass = pass3 && pass; + } + + // Siphash-4-8, 64-bit MAC + { + const byte key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; + SipHash<4, 8, false> hash(key, 16); + byte digest[SipHash<4, 8, false>::DIGESTSIZE]; + + hash.Update((const byte*)"", 0); + hash.Final(digest); + fail = memcmp("\x41\xDA\x38\x99\x2B\x05\x79\xC8", digest, COUNTOF(digest)) != 0; + pass2 = !fail && pass2; + + hash.Update((const byte*)"\x00", 1); + hash.Final(digest); + fail = memcmp("\x51\xB8\x95\x52\xF9\x14\x59\xC8", digest, COUNTOF(digest)) != 0; + pass2 = !fail && pass2; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06", 7); + hash.Final(digest); + fail = memcmp("\x47\xD7\x3F\x71\x5A\xBE\xFD\x4E", digest, COUNTOF(digest)) != 0; + pass2 = !fail && pass2; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07", 8); + hash.Final(digest); + fail = memcmp("\x20\xB5\x8B\x9C\x07\x2F\xDB\x50", digest, COUNTOF(digest)) != 0; + pass2 = !fail && pass2; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08", 9); + hash.Final(digest); + fail = memcmp("\x36\x31\x9A\xF3\x5E\xE1\x12\x53", digest, COUNTOF(digest)) != 0; + pass2 = !fail && pass2; + + std::cout << (pass2 ? "passed " : "FAILED ") << "SipHash-4-8 64-bit MAC\n"; + pass = pass2 && pass; + } + + // Siphash-4-8, 128-bit MAC + { + const byte key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; + SipHash<4, 8, true> hash(key, 16); + byte digest[SipHash<4, 8, true>::DIGESTSIZE]; + + hash.Update((const byte*)"", 0); + hash.Final(digest); + fail = memcmp("\x1F\x64\xCE\x58\x6D\xA9\x04\xE9\xCF\xEC\xE8\x54\x83\xA7\x0A\x6C", digest, COUNTOF(digest)) != 0; + pass4 = !fail && pass4; + + hash.Update((const byte*)"\x00", 1); + hash.Final(digest); + fail = memcmp("\x47\x34\x5D\xA8\xEF\x4C\x79\x47\x6A\xF2\x7C\xA7\x91\xC7\xA2\x80", digest, COUNTOF(digest)) != 0; + pass4 = !fail && pass4; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06", 7); + hash.Final(digest); + fail = memcmp("\xED\x00\xE1\x3B\x18\x4B\xF1\xC2\x72\x6B\x8B\x54\xFF\xD2\xEE\xE0", digest, COUNTOF(digest)) != 0; + pass4 = !fail && pass4; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07", 8); + hash.Final(digest); + fail = memcmp("\xA7\xD9\x46\x13\x8F\xF9\xED\xF5\x36\x4A\x5A\x23\xAF\xCA\xE0\x63", digest, COUNTOF(digest)) != 0; + pass4 = !fail && pass4; + + hash.Update((const byte*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08", 9); + hash.Final(digest); + fail = memcmp("\x9E\x73\x14\xB7\x54\x5C\xEC\xA3\x8B\x9A\x55\x49\xE4\xFB\x0B\xE8", digest, COUNTOF(digest)) != 0; + pass4 = !fail && pass4; + + std::cout << (pass4 ? "passed " : "FAILED ") << "SipHash-4-8 128-bit MAC\n"; + pass = pass4 && pass; + } + + return pass; +} + +struct BLAKE2_TestTuples +{ + const char *key, *message, *digest; + size_t klen, mlen, dlen; +}; + +bool ValidateBLAKE2s() +{ + std::cout << "\nBLAKE2s validation suite running...\n\n"; + bool fail, pass = true; + + { + fail = strcmp(BLAKE2s::StaticAlgorithmName(), "BLAKE2s") != 0; + std::cout << (fail ? "FAILED " : "passed ") << "algorithm name\n"; + pass = pass && !fail; + } + + const BLAKE2_TestTuples tests[] = { + { + NULLPTR, + NULLPTR, + "\x8F\x38", + 0, 0, 2 + }, + { + NULLPTR, + NULLPTR, + "\x36\xE9\xD2\x46", + 0, 0, 4 + }, + { + NULLPTR, + NULLPTR, + "\xEF\x2A\x8B\x78\xDD\x80\xDA\x9C", + 0, 0, 8 + }, + { + NULLPTR, + NULLPTR, + "\x64\x55\x0D\x6F\xFE\x2C\x0A\x01\xA1\x4A\xBA\x1E\xAD\xE0\x20\x0C", + 0, 0, 16 + }, + { + NULLPTR, + NULLPTR, + "\x69\x21\x7A\x30\x79\x90\x80\x94\xE1\x11\x21\xD0\x42\x35\x4A\x7C\x1F\x55\xB6\x48\x2C\xA1\xA5\x1E\x1B\x25\x0D\xFD\x1E\xD0\xEE\xF9", + 0, 0, 32 + }, + { + NULLPTR, + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x25\xEC\xB2\xF6\xA7\x81\x82\x57\x5D\x4B\xD7\x02\x72\x6D\xE1\x82\xBB\x1E\x21\xA8\x5D\x51\x34\xAD\xA2\x25\x8D\x7E\x21\x38\x03\xA7", + 0, 15, 32 + }, + { + NULLPTR, + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xD4\x1C\x69\x87\x29\x7E\xDE\x4F\x08\x9B\x66\x9B\xC7\x0E\x62\xB9\xFA\xFA\x1C\x37\xCC\x31\x29\x22\xE0\xEA\x63\xE2\xE5\x85\xAA\x9F", + 0, 16, 32 + }, + { + NULLPTR, + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xE0\xAD\xF2\xCC\x1F\x1F\x55\x3A\xE6\xC3\xCD\x3D\xF7\x68\xEA\x66\x9C\x32\xBE\x1D\x37\xF9\xA2\x61\xD4\x4F\x45\x26\x69\xD0\xD3\xA4", + 0, 17, 32 + }, + { + NULLPTR, + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x10\x42\x65\x1C\x86\x15\xC4\x87\x69\x41\x19\x1F\xB6\xD5\xC5\x1D\xEB\x4C\xA1\x8C\xAF\xEF\xEB\x79\x69\x62\x87\x0D\x6A\x5D\xEE\x20", + 0, 31, 32 + }, + { + NULLPTR, + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xEA\xB1\xC5\xDD\xDF\xB5\x7C\x48\xC5\xB0\xB3\xF5\xBE\x5B\x47\x6D\xBB\xF5\xA3\x5C\x21\xD3\xDD\x94\x13\xA1\x04\xB8\x14\xF9\x2D\x4B", + 0, 32, 32 + }, + { + NULLPTR, + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x7E\x82\x07\x49\x14\x62\x11\x96\xC5\xE8\xF3\xCB\x0F\x21\x7B\x37\xAE\x9B\x64\x58\xF4\x66\x01\xB9\x21\x23\xAC\x48\x64\x30\x83\x8F", + 0, 33, 32 + }, + { + NULLPTR, + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x90\xB5\xA2\x5E\x8E\xA8\xA0\xC8\x74\x85\xAE\x18\x08\x9D\x92\xEB\x14\x5A\x5D\x4E\x2C\x60\x7B\xCB\x4B\x94\xD1\x0F\xAE\x59\x33\xC1", + 0, 63, 32 + }, + { + NULLPTR, + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x71\x27\x28\x45\x9E\x67\xD7\xED\xB7\xAE\xFA\x88\xFF\x5C\x7E\x7B\x5D\xA9\x94\xA1\xC3\xB1\x7B\x64\xFB\xC1\x4E\x47\xCA\xDA\x45\xDD", + 0, 64, 32 + }, + { + NULLPTR, + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x58\x72\x3B\xB1\xBE\x18\x33\x12\x31\x5E\x6E\xF7\xF2\xB1\x84\x60\x97\x2C\x19\xD3\x01\xAF\x42\x00\xAB\xDB\x04\x26\xFC\xB0\xC1\xF8", + 0, 65, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + NULLPTR, + "\x9A\xD4\x81\xEF\x81\x6C\xAC\xB6\x59\x35\x8E\x6D\x6B\x73\xF1\xE5\xAC\x71\xD6\x6E\x8B\x12\x6B\x73\xD9\xD9\x7D\x2F\xA7\xA4\x61\xB4", + 15, 0, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x61\x8C\xBE\x19\x4B\x28\xDC\xA3\x8B\xE5\x1A\x79\x37\x45\xB4\x66\x3D\xF1\x9D\xB5\x8F\xFF\xEF\xC4\x5D\x37\x82\x25\x93\xEB\xE2\x93", + 15, 15, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xF3\xEC\x81\x61\x44\x5C\x6E\x2E\xE6\x52\x6A\xCA\x5F\xD9\x25\x74\x2A\x33\xB9\x1F\xEF\x0F\x7E\x54\x4F\x50\xC2\xFB\x04\x3C\x52\xD2", + 15, 16, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xF4\x81\x43\x6E\x2F\x4C\x5D\x09\x21\x73\x24\xDA\xA6\x23\x9E\xFD\xF8\x82\xCE\x0E\x3E\x4C\xB4\x17\xCC\x27\xCD\x1A\xAE\x90\x9B\x94", + 15, 17, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x99\x5E\x74\x8E\x96\xFE\xC0\x39\x5B\x73\xA3\xC0\x4E\xC7\xF7\xBE\x89\x83\xCD\x18\x24\x60\x60\x7B\xBC\xF5\x50\xF5\x84\xD1\x71\x6B", + 15, 31, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x21\x6E\xB9\xE2\xE4\xAF\x94\x5F\x6A\xA3\xD2\xCA\x25\x72\xFB\x8F\xDB\x95\x2F\xAC\x1C\x69\xC1\x26\x28\x31\x63\x16\x25\xA5\x2C\xF8", + 15, 32, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xE3\x71\x9F\xD8\xAE\x68\xC8\xC4\x5D\x17\xDD\x21\x33\xBB\xE1\x61\x51\x22\xC2\x3B\x00\x6E\xDD\x66\x7E\x2A\x0A\x6B\x77\xA9\x0B\x8D", + 15, 33, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xD3\xF8\x5F\x1B\xBE\x9C\x53\xCB\x7F\x5F\x5F\x62\x4D\x06\x36\x8F\xF8\x15\xA7\xF5\xEB\x77\xC6\xC5\xB4\x81\x15\x01\x82\x8D\x9D\x40", + 15, 63, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xBF\xA3\xDA\x09\xF9\xDE\x1B\xE6\x57\x4B\x55\x82\x85\x69\x79\xA1\x89\xD6\xF4\x15\x8B\x03\xFA\xAC\x6E\x00\x80\x26\xF1\x6B\xA1\x28", + 15, 64, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x77\x45\xEA\x51\x24\x46\x53\x19\x6F\xE4\xED\x6B\x54\x5C\x9B\x95\x88\xF5\xD4\x2B\x4C\x3E\xE6\xB7\xA1\xA3\x9F\xC4\x3A\x27\x1E\x45", + 15, 65, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + NULLPTR, + "\xFD\x61\x6D\xA6\x8E\xEF\x10\x24\x16\xC7\xBD\x7D\xC8\xCA\xF8\x2B\x3D\x92\x7B\xCB\xDD\x06\x8E\x7C\xCA\xA7\x72\x76\xCE\x6C\x8C\xD4", + 16, 0, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x10\x18\x97\x28\xFB\x05\x1D\xA0\xA8\xD6\x8F\x1C\xAD\x81\xFC\x7C\xA2\x6D\x41\x4B\xAA\x0C\x2A\x95\xB7\xF4\xEF\x9A\x67\xB5\x26\x5F", + 16, 15, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x9E\x3B\x50\xF3\xB5\xF4\xC9\xB3\x57\x03\x74\xF1\xB3\xA0\x4B\x3C\xC1\x71\xB4\x30\x42\xE4\x65\x90\xE5\xE2\x8A\x4D\xBA\xCD\xB1\x9F", + 16, 16, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x69\x70\x88\xAB\x61\x39\x46\xEA\x3B\xEB\x98\x98\x78\xCD\x8E\xF1\xB5\x7E\x81\xFC\x42\x7D\x46\xB8\xDA\x85\xD2\xEB\xB8\x56\xE4\xAC", + 16, 17, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xD2\xDA\xAC\x63\x09\xF1\x81\xBB\xCC\x06\x0D\xCC\xB8\xFA\x67\x08\x14\xD4\x6A\x50\xD7\x4F\xBF\x3B\x4A\x2E\x39\x4D\x45\x55\x27\x2F", + 16, 31, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xEB\xB0\xF3\x27\xC3\xC4\x35\x97\x4F\x89\x73\x5A\x4D\xEB\xBB\x4C\x7C\xE9\x0C\x3E\x13\xEB\x07\x83\x74\x67\x0A\x86\xA7\xF4\xA8\x73", + 16, 32, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xC8\x96\xC3\x3A\x26\x77\x02\x84\x5D\x95\x1B\x0D\x9F\x5C\x07\xC5\x6D\x21\x5D\x7E\x20\xF1\x2F\xE0\x45\xE3\x50\x42\x9D\x58\xB0\xEA", + 16, 33, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x8A\x3C\x9F\xA4\xAC\x78\x82\xA7\x08\x76\xB9\xE1\xED\x22\x9B\x43\x45\xF4\xD4\x01\x76\xC4\xED\x5D\xA4\x5A\x41\xDE\x28\xB8\x09\x6C", + 16, 63, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x2D\x0C\x97\xBE\xD2\xF2\x13\x40\xB9\xC8\x15\x91\x6A\x55\x86\x7A\x43\xB1\xFD\xC7\x04\x08\x1B\x58\x37\x09\x12\x80\x40\x99\x7C\xED", + 16, 64, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xF7\xC0\x08\xE1\x31\x52\x9B\x71\x87\x51\xCF\xFF\x8B\x08\xA3\x14\x32\x08\x06\x8C\x22\xAD\x83\x97\x71\x95\xC5\x2C\xFC\x66\xA4\xAD", + 16, 65, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + NULLPTR, + "\xD0\xCE\x8E\x8D\xA0\xBA\xA4\x26\x0E\xD3\x1F\xD1\x7B\x78\xE6\x18\x15\xC6\xFF\xD8\x5A\xDB\x41\x8A\xE7\x36\xF0\xE7\xB9\x87\x2B\x6A", + 17, 0, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xCB\xE4\x63\xEB\x6B\x24\x6C\x08\x55\x84\x36\x30\x8E\xFA\xC1\x6B\x97\x43\xD7\x1F\x1F\x3E\x96\xBA\x7E\x87\xF2\x42\x3E\xF5\x69\x5E", + 17, 15, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xEF\x39\x55\x9D\x92\x20\xDC\xB6\x8C\x21\x79\xD6\x7C\x51\xB7\x36\xAC\x4E\xFC\xA1\xDE\x66\xC7\xED\x40\xBF\x23\x15\xD1\x25\x82\x4B", + 17, 16, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xE3\x3E\x44\x7B\xA2\x7F\x69\x21\x09\x57\x79\x72\xE7\x4B\xE0\xC7\xCD\x54\xDC\xCD\x55\x60\x75\x61\x82\x66\xD7\x5B\x6F\x60\xDD\x73", + 17, 17, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xA9\xC4\x29\x2F\x5B\x49\x9A\xE0\x71\xE7\xFD\x65\x98\x53\x42\xC0\xC0\xF1\x75\xBC\xB5\x7B\x5C\xA1\x61\xFC\x8B\x45\x44\x54\xEC\x06", + 17, 31, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x29\x60\xBD\x05\x28\xEA\xF1\xA9\x43\xEF\x2D\x87\xC7\xB5\x27\x47\x33\xBA\xC8\x0C\x9F\x1C\xF5\x72\x62\x4C\xA7\x9E\x10\x23\x66\x76", + 17, 32, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xE2\xF1\x33\x23\x9D\xD8\xBC\x60\x1F\xB7\xD8\x21\xF5\x13\x98\xE2\x5C\x24\x0E\xC0\x60\x18\xB4\x0B\x93\xF1\x04\x25\xC5\xEC\x20\x14", + 17, 33, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xEB\x4F\x8D\xB3\xF5\x03\x72\x55\x72\xCE\xF3\x91\x22\xCD\xEA\x5A\xC4\x9A\xD0\x42\xE1\xC4\x62\x90\xCE\x11\x9E\xFD\x11\xDB\xCA\x23", + 17, 63, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xB5\x9A\xA7\x74\xDA\xB8\xDE\x5C\xBB\xC3\x5A\xFC\xF0\xD7\xAF\x51\x1E\x0F\x05\x45\xDB\xDA\xB7\xA4\xA6\x52\xB2\x9E\x0E\x23\x14\x3D", + 17, 64, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x69\xA2\x95\x6C\x87\xED\x22\x76\x0A\x53\x75\x6D\x28\xF4\xCD\xC5\xF7\xF9\x88\x51\x73\xA7\xD9\x44\x0C\x96\xB1\x5F\xE5\x57\xFE\xE3", + 17, 65, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + NULLPTR, + "\x39\x4A\xB9\x85\xDD\xFF\x59\x59\x84\x5A\xF7\x54\xD6\xFC\x19\xFB\x94\x0E\xAE\xA4\xEA\x70\x54\x3E\x0D\x7E\x9D\xC7\x8A\x22\x77\x3B", + 31, 0, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x1B\x46\x57\xC0\x48\x26\x7B\xC6\x17\xEC\xD5\x76\x89\xEE\x81\xE5\x5B\xE0\xAC\xCE\xB7\x5D\x33\x2A\xAF\xB6\xE2\xF6\xC0\xBB\x93\xE6", + 31, 15, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x53\xB3\x3A\x58\x98\xD2\x0D\x25\x61\x5A\x0C\xF5\x74\x7F\x44\x2F\x51\x70\x31\x66\x5E\x41\x5E\xBC\xF5\xF0\x03\x12\x98\x12\x90\xCC", + 31, 16, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x0B\x2C\x2A\x74\x72\x12\x18\xE1\xCE\xCD\x8A\x7E\xFC\xCE\x8D\x57\xBE\x42\x1A\xCC\xA2\x20\x24\x33\xC5\x1E\x31\x54\x1F\xB6\x45\xBD", + 31, 17, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xEF\x13\x95\xD4\x42\xC9\x9A\x04\xFE\xF0\x11\xE9\x72\xA9\x37\x74\x3E\x14\xC4\x4C\x58\x0C\xAC\x81\x4A\x75\x73\x35\x05\xC0\x81\x32", + 31, 31, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x0D\x35\xCF\x7F\x82\x08\x1E\x1B\xE9\x1E\x75\xE1\x96\x05\x9F\xBD\x63\x94\x8E\xE0\x71\xEF\x53\xDE\x79\xC6\x68\x21\xD6\x8A\x5A\xE4", + 31, 32, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x74\x0D\xCB\x50\x59\x59\xB9\x48\x52\x2B\x0B\x2A\x1F\xFC\x4F\x12\xF5\x9F\x49\x11\xED\x43\x61\xA6\x38\x8D\xF9\x35\x5C\xCD\x18\xBB", + 31, 33, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xDD\x48\xE5\xE8\x86\x8E\x61\xFF\x8A\x85\xC6\x5A\xB8\x5A\x32\xD2\x2A\x9C\xA2\xC8\xDC\xB9\xD6\x0A\x44\xD3\xF1\xB4\x8B\x5B\xD3\x80", + 31, 63, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x81\xEF\xAD\x79\x16\xE4\x29\x02\xDB\x89\x8D\xF2\xA4\x6D\xB4\xC4\x2A\x8C\xC6\x7E\xDE\x9B\xF7\x63\xB2\x10\xED\x15\xED\x0A\x0E\x3C", + 31, 64, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xEB\x54\xC4\x8A\x8F\x92\x53\x4D\xDF\x1D\x78\xCA\x98\x38\xF9\x10\xE4\x05\xCD\x6D\xB6\x82\x3B\x76\xB7\x82\x3A\xD2\x20\x77\xD4\x89", + 31, 65, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + NULLPTR, + "\x18\xE3\xCE\x19\x98\x7B\xA5\x0B\x30\xDD\x14\x4C\x16\xF2\x26\x55\xEB\xA3\x14\x09\xD6\x62\x10\xBC\x38\xBB\xC1\x4B\x5D\xAB\x05\x19", + 32, 0, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x10\x9D\x6C\xB3\x37\x9C\x9E\x2B\xC9\x1C\xF9\x79\x7A\x46\xEA\xFA\x78\x5C\xA1\x54\x83\xBD\xC2\x67\x31\xFA\x66\xAC\x5D\x4C\xE7\xAB", + 32, 15, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x76\x83\x9A\x8F\xBC\x20\x81\xD6\x09\x5C\x97\x46\xD3\xD6\xA4\xC4\xC1\x17\x8E\x3B\x14\xFC\xFD\x8F\x72\x20\xEF\xC6\x0B\xD3\xFF\x42", + 32, 16, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xEA\x0C\x05\xE6\x8F\xD6\xA6\xA1\xD9\xFC\xDA\x3C\xCB\x49\x02\xA5\xF9\x5D\x80\x9E\x89\xF6\xA2\x15\x74\x48\x84\x87\x77\x47\x6D\xBB", + 32, 17, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x98\x79\xD8\x91\x48\xB3\x12\x10\xE8\x49\x73\x38\x1B\xFA\x6C\xCA\x85\x59\xF9\xF9\xFE\xD3\xF2\x98\x9E\x9D\x5C\xE8\x1E\x59\xB3\x46", + 32, 31, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xC7\x41\x7E\x23\xDD\x7D\xB0\x84\xCA\x64\x26\x5A\xE0\x98\xD7\xF2\x29\xE4\x4C\x88\xC9\xF9\x15\x00\x19\x73\xC7\xCF\x95\xF5\x30\x68", + 32, 32, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\x0F\xDA\x45\x55\xAC\x8F\xB0\x17\x1D\xF2\x41\x54\xFB\x41\x26\x16\x0C\x00\x84\x49\x3D\x54\xAE\x9F\x13\xD4\xE5\x11\x2B\x42\xB5\xF5", + 32, 33, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xF1\x1B\x54\x05\xCE\x3A\xEB\xA1\x1B\x49\x99\x43\xBF\x2C\x73\x10\x0E\x35\x6B\xEA\x40\xAC\xE5\xBC\xD8\xD5\xB0\xAE\xB2\x8E\xFB\x05", + 32, 63, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xEA\xAF\xA4\xBE\xD6\x9D\x98\x73\x5E\xDF\xFC\x35\xFD\xB8\x26\x18\xAC\x15\x9E\x2B\xB2\xF9\x36\xEC\x51\x58\x1E\xD8\x53\xB7\x11\x10", + 32, 64, 32 + }, + { + "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61", + "\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A\x7A", + "\xC3\x0A\xE0\xAB\xFA\x38\x3C\x3F\xBC\x44\xD3\x2A\x4F\xC8\xFA\x86\xF2\x15\x9E\x83\x75\x65\xE4\x78\x63\xED\xEF\x31\x79\xEC\x00\x21", + 32, 65, 32 + } + }; + + { + byte digest[BLAKE2s::DIGESTSIZE]; + for (unsigned int i=0; i +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +bool CryptoSystemValidate(PK_Decryptor &priv, PK_Encryptor &pub, bool thorough) +{ + bool pass = true, fail; + + fail = !pub.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2) || !priv.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "cryptosystem key validation\n"; + + const byte message[] = "test message"; + const int messageLen = 12; + SecByteBlock ciphertext(priv.CiphertextLength(messageLen)); + SecByteBlock plaintext(priv.MaxPlaintextLength(ciphertext.size())); + + pub.Encrypt(GlobalRNG(), message, messageLen, ciphertext); + fail = priv.Decrypt(GlobalRNG(), ciphertext, priv.CiphertextLength(messageLen), plaintext) != DecodingResult(messageLen); + fail = fail || memcmp(message, plaintext, messageLen); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "encryption and decryption\n"; + + return pass; +} + +bool SimpleKeyAgreementValidate(SimpleKeyAgreementDomain &d) +{ + if (d.GetCryptoParameters().Validate(GlobalRNG(), 3)) + std::cout << "passed simple key agreement domain parameters validation" << std::endl; + else + { + std::cout << "FAILED simple key agreement domain parameters invalid" << std::endl; + return false; + } + + SecByteBlock priv1(d.PrivateKeyLength()), priv2(d.PrivateKeyLength()); + SecByteBlock pub1(d.PublicKeyLength()), pub2(d.PublicKeyLength()); + SecByteBlock val1(d.AgreedValueLength()), val2(d.AgreedValueLength()); + + d.GenerateKeyPair(GlobalRNG(), priv1, pub1); + d.GenerateKeyPair(GlobalRNG(), priv2, pub2); + + memset(val1.begin(), 0x10, val1.size()); + memset(val2.begin(), 0x11, val2.size()); + + if (!(d.Agree(val1, priv1, pub2) && d.Agree(val2, priv2, pub1))) + { + std::cout << "FAILED simple key agreement failed" << std::endl; + return false; + } + + if (memcmp(val1.begin(), val2.begin(), d.AgreedValueLength())) + { + std::cout << "FAILED simple agreed values not equal" << std::endl; + return false; + } + + std::cout << "passed simple key agreement" << std::endl; + return true; +} + +bool AuthenticatedKeyAgreementValidate(AuthenticatedKeyAgreementDomain &d) +{ + if (d.GetCryptoParameters().Validate(GlobalRNG(), 3)) + std::cout << "passed authenticated key agreement domain parameters validation" << std::endl; + else + { + std::cout << "FAILED authenticated key agreement domain parameters invalid" << std::endl; + return false; + } + + SecByteBlock spriv1(d.StaticPrivateKeyLength()), spriv2(d.StaticPrivateKeyLength()); + SecByteBlock epriv1(d.EphemeralPrivateKeyLength()), epriv2(d.EphemeralPrivateKeyLength()); + SecByteBlock spub1(d.StaticPublicKeyLength()), spub2(d.StaticPublicKeyLength()); + SecByteBlock epub1(d.EphemeralPublicKeyLength()), epub2(d.EphemeralPublicKeyLength()); + SecByteBlock val1(d.AgreedValueLength()), val2(d.AgreedValueLength()); + + d.GenerateStaticKeyPair(GlobalRNG(), spriv1, spub1); + d.GenerateStaticKeyPair(GlobalRNG(), spriv2, spub2); + d.GenerateEphemeralKeyPair(GlobalRNG(), epriv1, epub1); + d.GenerateEphemeralKeyPair(GlobalRNG(), epriv2, epub2); + + memset(val1.begin(), 0x10, val1.size()); + memset(val2.begin(), 0x11, val2.size()); + + if (d.Agree(val1, spriv1, epriv1, spub2, epub2) && d.Agree(val2, spriv2, epriv2, spub1, epub1)) + { + std::cout << "passed authenticated key agreement protocol execution" << std::endl; + } + else + { + std::cout << "FAILED authenticated key agreement protocol execution" << std::endl; + return false; + } + + if (memcmp(val1.begin(), val2.begin(), d.AgreedValueLength())) + { + std::cout << "FAILED authenticated agreed values not equal" << std::endl; + return false; + } + + std::cout << "passed authenticated key agreement" << std::endl; + return true; +} + +bool AuthenticatedKeyAgreementWithRolesValidate(AuthenticatedKeyAgreementDomain &initiator, AuthenticatedKeyAgreementDomain &recipient) +{ + if (initiator.GetCryptoParameters().Validate(GlobalRNG(), 3)) + std::cout << "passed authenticated key agreement domain parameters validation (initiator)" << std::endl; + else + { + std::cout << "FAILED authenticated key agreement domain parameters invalid (initiator)" << std::endl; + return false; + } + + if (recipient.GetCryptoParameters().Validate(GlobalRNG(), 3)) + std::cout << "passed authenticated key agreement domain parameters validation (recipient)" << std::endl; + else + { + std::cout << "FAILED authenticated key agreement domain parameters invalid (recipient)" << std::endl; + return false; + } + + if (initiator.StaticPrivateKeyLength() != recipient.StaticPrivateKeyLength() || + initiator.EphemeralPrivateKeyLength() != recipient.EphemeralPrivateKeyLength() || + initiator.StaticPublicKeyLength() != recipient.StaticPublicKeyLength() || + initiator.EphemeralPublicKeyLength() != recipient.EphemeralPublicKeyLength() || + initiator.AgreedValueLength() != recipient.AgreedValueLength()) + { + std::cout << "FAILED authenticated key agreement domain parameter consistency" << std::endl; + return false; + } + else + { + std::cout << "passed authenticated key agreement domain parameter consistency" << std::endl; + } + + SecByteBlock spriv1(initiator.StaticPrivateKeyLength()), spriv2(recipient.StaticPrivateKeyLength()); + SecByteBlock epriv1(initiator.EphemeralPrivateKeyLength()), epriv2(recipient.EphemeralPrivateKeyLength()); + SecByteBlock spub1(initiator.StaticPublicKeyLength()), spub2(recipient.StaticPublicKeyLength()); + SecByteBlock epub1(initiator.EphemeralPublicKeyLength()), epub2(recipient.EphemeralPublicKeyLength()); + SecByteBlock val1(initiator.AgreedValueLength()), val2(recipient.AgreedValueLength()); + + initiator.GenerateStaticKeyPair(GlobalRNG(), spriv1, spub1); + recipient.GenerateStaticKeyPair(GlobalRNG(), spriv2, spub2); + initiator.GenerateEphemeralKeyPair(GlobalRNG(), epriv1, epub1); + recipient.GenerateEphemeralKeyPair(GlobalRNG(), epriv2, epub2); + + memset(val1.begin(), 0x10, val1.size()); + memset(val2.begin(), 0x11, val2.size()); + + if (initiator.Agree(val1, spriv1, epriv1, spub2, epub2) && recipient.Agree(val2, spriv2, epriv2, spub1, epub1)) + { + std::cout << "passed authenticated key agreement protocol execution" << std::endl; + } + else + { + std::cout << "FAILED authenticated key agreement protocol execution" << std::endl; + return false; + } + + if (memcmp(val1.begin(), val2.begin(), initiator.AgreedValueLength())) + { + std::cout << "FAILED authenticated agreed values not equal" << std::endl; + return false; + } + + std::cout << "passed authenticated key agreement shared secret" << std::endl; + return true; +} + +bool SignatureValidate(PK_Signer &priv, PK_Verifier &pub, bool thorough) +{ + bool pass = true, fail; + + fail = !pub.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2) || !priv.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "signature key validation\n"; + + const byte message[] = "test message"; + const int messageLen = 12; + + SecByteBlock signature(priv.MaxSignatureLength()); + size_t signatureLength = priv.SignMessage(GlobalRNG(), message, messageLen, signature); + fail = !pub.VerifyMessage(message, messageLen, signature, signatureLength); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "signature and verification\n"; + + ++signature[0]; + fail = pub.VerifyMessage(message, messageLen, signature, signatureLength); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "checking invalid signature" << std::endl; + + if (priv.MaxRecoverableLength() > 0) + { + signatureLength = priv.SignMessageWithRecovery(GlobalRNG(), message, messageLen, NULLPTR, 0, signature); + SecByteBlock recovered(priv.MaxRecoverableLengthFromSignatureLength(signatureLength)); + DecodingResult result = pub.RecoverMessage(recovered, NULLPTR, 0, signature, signatureLength); + fail = !(result.isValidCoding && result.messageLength == messageLen && memcmp(recovered, message, messageLen) == 0); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "signature and verification with recovery" << std::endl; + + ++signature[0]; + result = pub.RecoverMessage(recovered, NULLPTR, 0, signature, signatureLength); + fail = result.isValidCoding; + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "recovery with invalid signature" << std::endl; + } + + return pass; +} + +bool ValidateBBS() +{ + std::cout << "\nBlumBlumShub validation suite running...\n\n"; + + Integer p("212004934506826557583707108431463840565872545889679278744389317666981496005411448865750399674653351"); + Integer q("100677295735404212434355574418077394581488455772477016953458064183204108039226017738610663984508231"); + Integer seed("63239752671357255800299643604761065219897634268887145610573595874544114193025997412441121667211431"); + BlumBlumShub bbs(p, q, seed); + bool pass = true, fail; + int j; + + const byte output1[] = { + 0x49,0xEA,0x2C,0xFD,0xB0,0x10,0x64,0xA0,0xBB,0xB9, + 0x2A,0xF1,0x01,0xDA,0xC1,0x8A,0x94,0xF7,0xB7,0xCE}; + const byte output2[] = { + 0x74,0x45,0x48,0xAE,0xAC,0xB7,0x0E,0xDF,0xAF,0xD7, + 0xD5,0x0E,0x8E,0x29,0x83,0x75,0x6B,0x27,0x46,0xA1}; + + byte buf[20]; + std::ostringstream oss; + + bbs.GenerateBlock(buf, 20); + fail = memcmp(output1, buf, 20) != 0; + pass = pass && !fail; + + oss << (fail ? "FAILED " : "passed "); + for (j=0;j<20;j++) + oss << std::setw(2) << std::setfill('0') << std::hex << (int)buf[j]; + oss << std::endl; + + bbs.Seek(10); + bbs.GenerateBlock(buf, 10); + fail = memcmp(output1+10, buf, 10) != 0; + pass = pass && !fail; + + oss << (fail ? "FAILED " : "passed "); + for (j=0;j<10;j++) + oss << std::setw(2) << std::setfill('0') << std::hex << (int)buf[j]; + oss << std::endl; + + bbs.Seek(1234567); + bbs.GenerateBlock(buf, 20); + fail = memcmp(output2, buf, 20) != 0; + pass = pass && !fail; + + oss << (fail ? "FAILED " : "passed "); + for (j=0;j<20;j++) + oss << std::setw(2) << std::setfill('0') << std::hex << (int)buf[j]; + oss << std::endl; + + std::cout << oss.str(); + return pass; +} + +bool ValidateECP() +{ + // Remove word recommend. Some ECP curves may not be recommended depending + // on whom you ask. ECP is more descriptive item in this case. + std::cout << "\nTesting SEC 2, NIST and Brainpool ECP curves...\n\n"; + bool pass = true; OID oid; + + while (!(oid = DL_GroupParameters_EC::GetNextRecommendedParametersOID(oid)).GetValues().empty()) + { + DL_GroupParameters_EC params(oid); + pass = params.Validate(GlobalRNG(), 2); + + // Test addition of identity element + DL_GroupParameters_EC::Element e1; + e1 = params.GetCurve().Add(e1, e1); + pass = params.IsIdentity(e1) && pass; + + // Test doubling of identity element + DL_GroupParameters_EC::Element e2; + e2 = params.GetCurve().Double(e2); + pass = params.IsIdentity(e2) && pass; + + // Test multiplication of identity element + DL_GroupParameters_EC::Element e3; + Integer two = Integer::Two(); + e3 = params.GetCurve().Multiply(two, e3); + pass = params.IsIdentity(e3) && pass; + + std::cout << (pass ? "passed" : "FAILED") << " " << std::dec << params.GetCurve().GetField().MaxElementBitLength() << " bits\n"; + } + + std::cout << "\nECP validation suite running...\n\n"; + return ValidateECP_Agreement() && ValidateECP_Encrypt() && ValidateECP_NULLDigest_Encrypt() && ValidateECP_Sign() && pass; +} + +bool ValidateEC2N() +{ + // Remove word recommend. Binary curves may not be recommended depending + // on whom you ask. EC2N is more descriptive item in this case. + std::cout << "\nTesting SEC 2 EC2N curves...\n\n"; + bool pass = true; OID oid; + +#if 1 // TODO: turn this back on when I make EC2N faster for pentanomial basis + while (!(oid = DL_GroupParameters_EC::GetNextRecommendedParametersOID(oid)).GetValues().empty()) + { + DL_GroupParameters_EC params(oid); + pass = params.Validate(GlobalRNG(), 2); + + // Test addition of identity element + DL_GroupParameters_EC::Element e1; + e1 = params.GetCurve().Add(e1, e1); + pass = params.IsIdentity(e1) && pass; + + // Test doubling of identity element + DL_GroupParameters_EC::Element e2; + e2 = params.GetCurve().Double(e2); + pass = params.IsIdentity(e2) && pass; + + // Test multiplication of identity element + DL_GroupParameters_EC::Element e3; + Integer two = Integer::Two(); + e3 = params.GetCurve().Multiply(two, e3); + pass = params.IsIdentity(e3) && pass; + + std::cout << (pass ? "passed" : "FAILED") << " " << params.GetCurve().GetField().MaxElementBitLength() << " bits\n"; + } +#endif + + std::cout << "\nEC2N validation suite running...\n\n"; + return ValidateEC2N_Agreement() && ValidateEC2N_Encrypt() && ValidateEC2N_Sign() && pass; +} + +bool ValidateRSA() +{ + std::cout << "\nRSA validation suite running...\n\n"; + return ValidateRSA_Encrypt() && ValidateRSA_Sign(); +} + +bool ValidateLUC() +{ + std::cout << "\nLUC validation suite running...\n\n"; + return ValidateLUC_Encrypt() && ValidateLUC_Sign(); +} + +bool ValidateLUC_DL() +{ + // Prologue printed in each function + return ValidateLUC_DL_Encrypt() && ValidateLUC_DL_Sign(); +} + +bool ValidateRabin() +{ + std::cout << "\nRabin validation suite running...\n\n"; + return ValidateRabin_Encrypt() && ValidateRabin_Sign(); +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/validat7.cpp b/external/ours/library/crypto/src/shared/original/validat7.cpp new file mode 100755 index 000000000..32db7e4db --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/validat7.cpp @@ -0,0 +1,705 @@ +// validat7.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017. +// Source files split in July 2018 to expedite compiles. + +#include "pch.h" + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "cpu.h" +#include "validate.h" + +#include "asn.h" +#include "oids.h" + +#include "sha.h" +#include "sha3.h" + +#include "dh.h" +#include "luc.h" +#include "mqv.h" +#include "xtr.h" +#include "hmqv.h" +#include "pubkey.h" +#include "xtrcrypt.h" +#include "eccrypto.h" + +// Curve25519 +#include "xed25519.h" +#include "donna.h" +#include "naclite.h" + +#include +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +ANONYMOUS_NAMESPACE_BEGIN + +inline bool operator==(const x25519& lhs, const x25519& rhs) +{ + // This is a hack because the KeyAgreement classes do not make it easy to access the PrivateKey + ByteQueue q1, q2; + lhs.DEREncodePrivateKey(q1); + rhs.DEREncodePrivateKey(q2); + + return q1 == q2; +} + +inline bool operator!=(const x25519& lhs, const x25519& rhs) +{ + return !operator==(lhs, rhs); +} + +ANONYMOUS_NAMESPACE_END + +bool ValidateDH() +{ + std::cout << "\nDH validation suite running...\n\n"; + + FileSource f(DataDir("TestData/dh1024.dat").c_str(), true, new HexDecoder); + DH dh(f); + return SimpleKeyAgreementValidate(dh); +} + +bool ValidateX25519() +{ + std::cout << "\nx25519 validation suite running...\n\n"; + + FileSource f(DataDir("TestData/x25519.dat").c_str(), true, new HexDecoder); + x25519 dh(f); + return SimpleKeyAgreementValidate(dh); +} + +bool ValidateMQV() +{ + std::cout << "\nMQV validation suite running...\n\n"; + + FileSource f(DataDir("TestData/mqv1024.dat").c_str(), true, new HexDecoder); + MQV mqv(f); + return AuthenticatedKeyAgreementValidate(mqv); +} + +bool ValidateHMQV() +{ + std::cout << "\nHMQV validation suite running...\n\n"; + bool success = true, fail; + + FileSource f256(DataDir("TestData/hmqv256.dat").c_str(), true, new HexDecoder); + FileSource f384(DataDir("TestData/hmqv384.dat").c_str(), true, new HexDecoder); + FileSource f512(DataDir("TestData/hmqv512.dat").c_str(), true, new HexDecoder); + + ///////////////////////// + + std::cout << "HMQV with NIST P-256 and SHA-256:" << std::endl; + + ECHMQV256 hmqvB256(false); + hmqvB256.AccessGroupParameters().BERDecode(f256); + const OID oid = ASN1::secp256r1(); + ECHMQV< ECP >::Domain hmqvA256(oid, true /*client*/); + + fail = !AuthenticatedKeyAgreementWithRolesValidate(hmqvA256, hmqvB256); + success = !fail && success; + if (fail == false) + std::cout << "passed authenticated key agreement" << std::endl; + else + std::cout << "FAILED authenticated key agreement" << std::endl; + + ///////////////////////// + + std::cout << "HMQV with NIST P-384 and SHA-384:" << std::endl; + + ECHMQV384 hmqvB384(false); + hmqvB384.AccessGroupParameters().BERDecode(f384); + const OID oid384 = ASN1::secp384r1(); + ECHMQV384 hmqvA384(oid384, true /*client*/); + + fail = !AuthenticatedKeyAgreementWithRolesValidate(hmqvA384, hmqvB384); + success = !fail && success; + if (fail == false) + std::cout << "passed authenticated key agreement" << std::endl; + else + std::cout << "FAILED authenticated key agreement" << std::endl; + + ///////////////////////// + + std::cout << "HMQV with NIST P-521 and SHA-512:" << std::endl; + + ECHMQV512 hmqvB521(false); + hmqvB521.AccessGroupParameters().BERDecode(f512); + const OID oid521 = ASN1::secp521r1(); + ECHMQV512 hmqvA521(oid521, true /*client*/); + + fail = !AuthenticatedKeyAgreementWithRolesValidate(hmqvA521, hmqvB521); + success = !fail && success; + if (fail == false) + std::cout << "passed authenticated key agreement" << std::endl; + else + std::cout << "FAILED authenticated key agreement" << std::endl; + + return success; +} + +bool ValidateFHMQV() +{ + std::cout << "\nFHMQV validation suite running...\n\n"; + bool success = true, fail; + + FileSource f256(DataDir("TestData/fhmqv256.dat").c_str(), true, new HexDecoder); + FileSource f384(DataDir("TestData/fhmqv384.dat").c_str(), true, new HexDecoder); + FileSource f512(DataDir("TestData/fhmqv512.dat").c_str(), true, new HexDecoder); + + ///////////////////////// + + std::cout << "FHMQV with NIST P-256 and SHA-256:" << std::endl; + + ECFHMQV256 fhmqvB256(false); + fhmqvB256.AccessGroupParameters().BERDecode(f256); + const OID oid = ASN1::secp256r1(); + ECFHMQV< ECP >::Domain fhmqvA256(oid, true /*client*/); + + fail = !AuthenticatedKeyAgreementWithRolesValidate(fhmqvA256, fhmqvB256); + success = !fail && success; + if (fail == false) + std::cout << "passed authenticated key agreement" << std::endl; + else + std::cout << "FAILED authenticated key agreement" << std::endl; + + ///////////////////////// + + std::cout << "FHMQV with NIST P-384 and SHA-384:" << std::endl; + + ECHMQV384 fhmqvB384(false); + fhmqvB384.AccessGroupParameters().BERDecode(f384); + const OID oid384 = ASN1::secp384r1(); + ECHMQV384 fhmqvA384(oid384, true /*client*/); + + fail = !AuthenticatedKeyAgreementWithRolesValidate(fhmqvA384, fhmqvB384); + success = !fail && success; + if (fail == false) + std::cout << "passed authenticated key agreement" << std::endl; + else + std::cout << "FAILED authenticated key agreement" << std::endl; + + ///////////////////////// + + std::cout << "FHMQV with NIST P-521 and SHA-512:" << std::endl; + + ECHMQV512 fhmqvB521(false); + fhmqvB521.AccessGroupParameters().BERDecode(f512); + const OID oid521 = ASN1::secp521r1(); + ECHMQV512 fhmqvA521(oid521, true /*client*/); + + fail = !AuthenticatedKeyAgreementWithRolesValidate(fhmqvA521, fhmqvB521); + success = !fail && success; + if (fail == false) + std::cout << "passed authenticated key agreement" << std::endl; + else + std::cout << "FAILED authenticated key agreement" << std::endl; + + return success; +} + +bool ValidateLUC_DH() +{ + std::cout << "\nLUC-DH validation suite running...\n\n"; + + FileSource f(DataDir("TestData/lucd512.dat").c_str(), true, new HexDecoder); + LUC_DH dh(f); + return SimpleKeyAgreementValidate(dh); +} + +bool ValidateXTR_DH() +{ + std::cout << "\nXTR-DH validation suite running...\n\n"; + + FileSource f(DataDir("TestData/xtrdh171.dat").c_str(), true, new HexDecoder); + XTR_DH dh(f); + return SimpleKeyAgreementValidate(dh); +} + +bool ValidateECP_Agreement() +{ + ECDH::Domain ecdhc(ASN1::secp192r1()); + ECMQV::Domain ecmqvc(ASN1::secp192r1()); + bool pass = SimpleKeyAgreementValidate(ecdhc); + pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass; + + std::cout << "Turning on point compression..." << std::endl; + ecdhc.AccessGroupParameters().SetPointCompression(true); + ecmqvc.AccessGroupParameters().SetPointCompression(true); + pass = SimpleKeyAgreementValidate(ecdhc) && pass; + pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass; + + return pass; +} + +bool ValidateEC2N_Agreement() +{ + ECDH::Domain ecdhc(ASN1::sect193r1()); + ECMQV::Domain ecmqvc(ASN1::sect193r1()); + bool pass = SimpleKeyAgreementValidate(ecdhc); + pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass; + + std::cout << "Turning on point compression..." << std::endl; + ecdhc.AccessGroupParameters().SetPointCompression(true); + ecmqvc.AccessGroupParameters().SetPointCompression(true); + pass = SimpleKeyAgreementValidate(ecdhc) && pass; + pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass; + + return pass; +} + +// TestX25519 is slighty more comprehensive than ValidateX25519 +// because it cross-validates against Bernstein's NaCL library. +// TestX25519 called in Debug builds. +bool TestX25519() +{ + std::cout << "\nTesting curve25519 Key Agreements...\n\n"; + const unsigned int AGREE_COUNT = 64; + bool pass = true, fail; + + size_t i = 0; + unsigned int failed = 0; + + SecByteBlock priv1(32), priv2(32), pub1(32), pub2(32), share1(32), share2(32); + for (i=0, failed=0; i +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +ANONYMOUS_NAMESPACE_BEGIN + +inline byte* C2B(char* ptr) { + return reinterpret_cast(ptr); +} + +inline const byte* C2B(const char* ptr) { + return reinterpret_cast(ptr); +} + +inline bool operator==(const RSA::PrivateKey& lhs, const RSA::PrivateKey& rhs) { + return lhs.GetModulus() == rhs.GetModulus() && + lhs.GetPublicExponent() == rhs.GetPublicExponent() && + lhs.GetPrivateExponent() == rhs.GetPrivateExponent(); +} + +inline bool operator!=(const RSA::PrivateKey& lhs, const RSA::PrivateKey& rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator==(const RSA::PublicKey& lhs, const RSA::PublicKey& rhs) { + return lhs.GetModulus() == rhs.GetModulus() && + lhs.GetPublicExponent() == rhs.GetPublicExponent(); +} + +inline bool operator!=(const RSA::PublicKey& lhs, const RSA::PublicKey& rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator==(const LUC::PrivateKey& lhs, const LUC::PrivateKey& rhs) { + return lhs.GetModulus() == rhs.GetModulus() && + lhs.GetPublicExponent() == rhs.GetPublicExponent() && + lhs.GetPrime1() == rhs.GetPrime1() && + lhs.GetPrime2() == rhs.GetPrime2() && + lhs.GetMultiplicativeInverseOfPrime2ModPrime1() == rhs.GetMultiplicativeInverseOfPrime2ModPrime1(); +} + +inline bool operator!=(const LUC::PrivateKey& lhs, const LUC::PrivateKey& rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator==(const LUC::PublicKey& lhs, const LUC::PublicKey& rhs) { + return lhs.GetModulus() == rhs.GetModulus() && + lhs.GetPublicExponent() == rhs.GetPublicExponent(); +} + +inline bool operator!=(const LUC::PublicKey& lhs, const LUC::PublicKey& rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator==(const Rabin::PrivateKey& lhs, const Rabin::PrivateKey& rhs) { + return lhs.GetModulus() == rhs.GetModulus() && + lhs.GetQuadraticResidueModPrime1() == rhs.GetQuadraticResidueModPrime1() && + lhs.GetQuadraticResidueModPrime2() == rhs.GetQuadraticResidueModPrime2() && + lhs.GetPrime1() == rhs.GetPrime1() && + lhs.GetPrime2() == rhs.GetPrime2() && + lhs.GetMultiplicativeInverseOfPrime2ModPrime1() == rhs.GetMultiplicativeInverseOfPrime2ModPrime1(); +} + +inline bool operator!=(const Rabin::PrivateKey& lhs, const Rabin::PrivateKey& rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator==(const Rabin::PublicKey& lhs, const Rabin::PublicKey& rhs) { + return lhs.GetModulus() == rhs.GetModulus() && + lhs.GetQuadraticResidueModPrime1() == rhs.GetQuadraticResidueModPrime1() && + lhs.GetQuadraticResidueModPrime2() == rhs.GetQuadraticResidueModPrime2(); +} + +inline bool operator!=(const Rabin::PublicKey& lhs, const Rabin::PublicKey& rhs) { + return !operator==(lhs, rhs); +} + +ANONYMOUS_NAMESPACE_END + +bool ValidateRSA_Encrypt() +{ + // Must be large enough for RSA-3072 to test SHA3_256 + byte out[256], outPlain[128]; + bool pass = true, fail; + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) + { + FileSource keys(DataDir("TestData/rsa1024.dat").c_str(), true, new HexDecoder); + RSA::PrivateKey rsaPriv; rsaPriv.Load(keys); + RSA::PublicKey rsaPub(rsaPriv); + + const Integer& n = rsaPriv.GetModulus(); + const Integer& e = rsaPriv.GetPublicExponent(); + const Integer& d = rsaPriv.GetPrivateExponent(); + + RSA::PrivateKey rsaPriv2; + rsaPriv2.Initialize(n, e, d); + + fail = (rsaPriv != rsaPriv2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "RSA::PrivateKey initialization\n"; + + RSA::PublicKey rsaPub2; + rsaPub2.Initialize(n, e); + + fail = (rsaPub != rsaPub2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "RSA::PublicKey initialization\n"; + } + { + FileSource keys(DataDir("TestData/rsa1024.dat").c_str(), true, new HexDecoder); + RSA::PrivateKey rsaPriv; rsaPriv.Load(keys); + + ByteQueue q; + rsaPriv.DEREncodePrivateKey(q); + + RSA::PrivateKey rsaPriv2; + rsaPriv2.BERDecodePrivateKey(q, true, q.MaxRetrievable()); + + fail = (rsaPriv != rsaPriv2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "RSA::PrivateKey encoding and decoding\n"; + } +#endif + + { + FileSource keys(DataDir("TestData/rsa1024.dat").c_str(), true, new HexDecoder); + RSAES_PKCS1v15_Decryptor rsaPriv(keys); + RSAES_PKCS1v15_Encryptor rsaPub(rsaPriv); + + fail = !CryptoSystemValidate(rsaPriv, rsaPub); + pass = pass && !fail; + } + { + RSAES >::Decryptor rsaPriv(GlobalRNG(), 512); + RSAES >::Encryptor rsaPub(rsaPriv); + + fail = !CryptoSystemValidate(rsaPriv, rsaPub); + pass = pass && !fail; + } + { + const byte plain[] = + "\x54\x85\x9b\x34\x2c\x49\xea\x2a"; + const byte encrypted[] = + "\x14\xbd\xdd\x28\xc9\x83\x35\x19\x23\x80\xe8\xe5\x49\xb1\x58\x2a" + "\x8b\x40\xb4\x48\x6d\x03\xa6\xa5\x31\x1f\x1f\xd5\xf0\xa1\x80\xe4" + "\x17\x53\x03\x29\xa9\x34\x90\x74\xb1\x52\x13\x54\x29\x08\x24\x52" + "\x62\x51"; + const byte oaepSeed[] = + "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2" + "\xf0\x6c\xb5\x8f"; + ByteQueue bq; + bq.Put(oaepSeed, 20); + FixedRNG rng(bq); + + FileSource privFile(DataDir("TestData/rsa400pv.dat").c_str(), true, new HexDecoder); + FileSource pubFile(DataDir("TestData/rsa400pb.dat").c_str(), true, new HexDecoder); + RSAES_OAEP_SHA_Decryptor rsaPriv; + rsaPriv.AccessKey().BERDecodePrivateKey(privFile, false, 0); + RSAES_OAEP_SHA_Encryptor rsaPub(pubFile); + + memset(out, 0, 50); + memset(outPlain, 0, 8); + rsaPub.Encrypt(rng, plain, 8, out); + DecodingResult result = rsaPriv.FixedLengthDecrypt(GlobalRNG(), encrypted, outPlain); + fail = !result.isValidCoding || (result.messageLength!=8) || memcmp(out, encrypted, 50) || memcmp(plain, outPlain, 8); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "PKCS 2.0 encryption and decryption\n"; + } + + return pass; +} + +bool ValidateLUC_Encrypt() +{ + bool pass = true, fail; + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) + { + FileSource keys(DataDir("TestData/luc1024.dat").c_str(), true, new HexDecoder); + LUC::PrivateKey lucPriv; lucPriv.BERDecode(keys); + LUC::PublicKey lucPub(lucPriv); + + const Integer& n = lucPriv.GetModulus(); + const Integer& e = lucPriv.GetPublicExponent(); + const Integer& p = lucPriv.GetPrime1(); + const Integer& q = lucPriv.GetPrime2(); + const Integer& u = lucPriv.GetMultiplicativeInverseOfPrime2ModPrime1(); + + LUC::PrivateKey lucPriv2; + lucPriv2.Initialize(n, e, p, q, u); + + fail = (lucPriv != lucPriv2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "LUC::PrivateKey initialization\n"; + + LUC::PublicKey lucPub2; + lucPub2.Initialize(n, e); + + fail = (lucPub != lucPub2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "LUC::PublicKey initialization\n"; + } + { + FileSource keys(DataDir("TestData/luc1024.dat").c_str(), true, new HexDecoder); + LUC::PrivateKey lucPriv; lucPriv.BERDecode(keys); + + ByteQueue q; + lucPriv.DEREncode(q); + + LUC::PrivateKey lucPriv2; + lucPriv2.BERDecode(q); + + fail = (lucPriv != lucPriv2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "LUC::PrivateKey encoding and decoding\n"; + } + { + FileSource keys(DataDir("TestData/luc1024.dat").c_str(), true, new HexDecoder); + LUC::PrivateKey lucPriv; lucPriv.BERDecode(keys); + LUC::PublicKey lucPub(lucPriv); + + ByteQueue q; + lucPub.DEREncode(q); + + LUC::PublicKey lucPub2; + lucPub2.BERDecode(q); + + fail = (lucPub != lucPub2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "LUC::PublicKey encoding and decoding\n"; + } +#endif + + LUCES_OAEP_SHA_Decryptor priv(GlobalRNG(), 512); + LUCES_OAEP_SHA_Encryptor pub(priv); + fail = !CryptoSystemValidate(priv, pub); + pass = pass && !fail; + + return pass; +} + +bool ValidateLUC_DL_Encrypt() +{ + std::cout << "\nLUC-IES validation suite running...\n\n"; + + FileSource fc(DataDir("TestData/lucc512.dat").c_str(), true, new HexDecoder); + LUC_IES<>::Decryptor privC(fc); + LUC_IES<>::Encryptor pubC(privC); + return CryptoSystemValidate(privC, pubC); +} + +bool ValidateRabin_Encrypt() +{ + bool pass = true, fail; + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) + { + FileSource keys(DataDir("TestData/rabi1024.dat").c_str(), true, new HexDecoder); + Rabin::PrivateKey rabinPriv; rabinPriv.BERDecode(keys); + Rabin::PublicKey rabinPub(rabinPriv); + + const Integer& n = rabinPriv.GetModulus(); + const Integer& r = rabinPriv.GetQuadraticResidueModPrime1(); + const Integer& s = rabinPriv.GetQuadraticResidueModPrime2(); + const Integer& p = rabinPriv.GetPrime1(); + const Integer& q = rabinPriv.GetPrime2(); + const Integer& u = rabinPriv.GetMultiplicativeInverseOfPrime2ModPrime1(); + + Rabin::PrivateKey rabinPriv2; + rabinPriv2.Initialize(n, r, s, p, q, u); + + fail = (rabinPriv != rabinPriv2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "Rabin::PrivateKey initialization\n"; + + Rabin::PublicKey rabinPub2; + rabinPub2.Initialize(n, r, s); + + fail = (rabinPub != rabinPub2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "Rabin::PublicKey initialization\n"; + } + { + FileSource keys(DataDir("TestData/rabi1024.dat").c_str(), true, new HexDecoder); + Rabin::PrivateKey rabinPriv; rabinPriv.BERDecode(keys); + + ByteQueue q; + rabinPriv.DEREncode(q); + + Rabin::PrivateKey rabinPriv2; + rabinPriv2.BERDecode(q); + + fail = (rabinPriv != rabinPriv2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "Rabin::PrivateKey encoding and decoding\n"; + } + { + FileSource keys(DataDir("TestData/rabi1024.dat").c_str(), true, new HexDecoder); + Rabin::PrivateKey rabinPriv; rabinPriv.BERDecode(keys); + Rabin::PublicKey rabinPub(rabinPriv); + + ByteQueue q; + rabinPub.DEREncode(q); + + Rabin::PublicKey rabinPub2; + rabinPub2.BERDecode(q); + + fail = (rabinPub != rabinPub2); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "Rabin::PublicKey encoding and decoding\n"; + } +#endif + + FileSource f(DataDir("TestData/rabi1024.dat").c_str(), true, new HexDecoder); + RabinES >::Decryptor priv(f); + RabinES >::Encryptor pub(priv); + fail = !CryptoSystemValidate(priv, pub); + pass = pass && !fail; + + return pass; +} + +bool ValidateECP_Encrypt() +{ + ECIES::Decryptor cpriv(GlobalRNG(), ASN1::secp192r1()); + ECIES::Encryptor cpub(cpriv); + ByteQueue bq; + cpriv.GetKey().DEREncode(bq); + cpub.AccessKey().AccessGroupParameters().SetEncodeAsOID(true); + cpub.GetKey().DEREncode(bq); + + cpub.AccessKey().Precompute(); + cpriv.AccessKey().Precompute(); + bool pass = CryptoSystemValidate(cpriv, cpub); + + std::cout << "Turning on point compression..." << std::endl; + cpriv.AccessKey().AccessGroupParameters().SetPointCompression(true); + cpub.AccessKey().AccessGroupParameters().SetPointCompression(true); + pass = CryptoSystemValidate(cpriv, cpub) && pass; + + return pass; +} + +// https://github.com/weidai11/cryptopp/issues/856 +// Not to be confused with NullHash in trunhash.h. +class NULL_Hash : public CryptoPP::IteratedHashWithStaticTransform + +{ +public: + static void InitState(HashWordType *state) { + CRYPTOPP_UNUSED(state); + } + static void Transform(CryptoPP::word32 *digest, const CryptoPP::word32 *data) { + CRYPTOPP_UNUSED(digest); CRYPTOPP_UNUSED(data); + } + static const char *StaticAlgorithmName() { + return "NULL_Hash"; + } +}; + +// https://github.com/weidai11/cryptopp/issues/856 +template +struct ECIES_NULLDigest + : 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-NULLDigest";} +}; + +bool ValidateECP_NULLDigest_Encrypt() +{ + ECIES_NULLDigest::Decryptor cpriv(GlobalRNG(), ASN1::secp256k1()); + ECIES_NULLDigest::Encryptor cpub(cpriv); + ByteQueue bq; + cpriv.GetKey().DEREncode(bq); + cpub.AccessKey().AccessGroupParameters().SetEncodeAsOID(true); + cpub.GetKey().DEREncode(bq); + + cpub.AccessKey().Precompute(); + cpriv.AccessKey().Precompute(); + bool pass = CryptoSystemValidate(cpriv, cpub); + + std::cout << "Turning on point compression..." << std::endl; + cpriv.AccessKey().AccessGroupParameters().SetPointCompression(true); + cpub.AccessKey().AccessGroupParameters().SetPointCompression(true); + pass = CryptoSystemValidate(cpriv, cpub) && pass; + + return pass; +} + +// Ensure interop with Crypto++ 5.6.4 and earlier +bool ValidateECP_Legacy_Encrypt() +{ + std::cout << "\nLegacy ECIES ECP validation suite running...\n\n"; + bool pass = true; + { + FileSource fc(DataDir("TestData/ecies_p160.dat").c_str(), true, new HexDecoder); + ECIES::Decryptor privC(fc); + ECIES::Encryptor pubC(privC); + + pass = CryptoSystemValidate(privC, pubC) && pass; + + // Test data generated by Crypto++ 5.6.2. + // Also see https://github.com/weidai11/cryptopp/pull/857. + const std::string plain = "Yoda said, Do or do not. There is no try."; + const std::string cipher = + "\x04\xF6\xC1\xB1\xFA\xAC\x8A\xD5\xD3\x96\xE7\x13\xAE\xBD\x0C\xCE" + "\x15\xCF\x44\x54\x08\x63\xCC\xBF\x89\x4D\xD0\xB8\x38\xA1\x3A\xB2" + "\x90\x75\x86\x82\x7F\x9D\x95\x26\xA5\x74\x13\x3A\x74\x63\x11\x71" + "\x70\x4C\x01\xA4\x08\x04\x95\x69\x6A\x91\xF0\xC0\xA4\xBD\x1E\xAA" + "\x59\x57\xB8\xA9\xD2\xF7\x7C\x98\xE3\xC5\xE3\xF4\x4F\xA7\x6E\x73" + "\x83\xF3\x1E\x05\x73\xA4\xEE\x63\x55\xFD\x6D\x31\xBB\x9E\x36\x4C" + "\x79\xD0\x76\xC0\x0D\xE9"; + + std::string recover; + recover.resize(privC.MaxPlaintextLength(cipher.size())); + + DecodingResult result = privC.Decrypt(GlobalRNG(), C2B(&cipher[0]), cipher.size(), C2B(&recover[0])); + if (result.isValidCoding) + recover.resize(result.messageLength); + else + recover.resize(0); + + pass = (plain == recover) && pass; + std::cout << (pass ? "passed " : "FAILED "); + std::cout << "decryption known answer\n"; + } + return pass; +} + +// Ensure interop with Crypto++ 5.6.4 and earlier +bool ValidateEC2N_Legacy_Encrypt() +{ + std::cout << "\nLegacy ECIES EC2N validation suite running...\n\n"; + bool pass = true; + { + FileSource fc(DataDir("TestData/ecies_t163.dat").c_str(), true, new HexDecoder); + ECIES::Decryptor privC(fc); + ECIES::Encryptor pubC(privC); + + pass = CryptoSystemValidate(privC, pubC) && pass; + + // Test data generated by Crypto++ 5.6.2. + // Also see https://github.com/weidai11/cryptopp/pull/857. + const std::string plain = "Yoda said, Do or do not. There is no try."; + const std::string cipher = + "\x04\x01\x3F\x64\x94\x6A\xBE\x2B\x7E\x48\x67\x63\xA2\xD4\x01\xEF" + "\x2B\x13\x1C\x9A\x1B\x7C\x07\x4B\x89\x78\x6C\x65\x51\x1C\x1A\x4E" + "\x20\x7F\xB5\xBF\x12\x3B\x6E\x0A\x87\xFD\xB7\x94\xEF\x4B\xED\x40" + "\xD4\x7A\xCF\xB6\xFC\x9B\x6D\xB0\xB8\x43\x99\x7E\x37\xC1\xF0\xC0" + "\x95\xD4\x80\xE1\x8B\x84\xAE\x64\x9F\xA5\xBA\x32\x95\x8A\xD1\xBE" + "\x7F\xDE\x7E\xA9\xE6\x59\xBF\x89\xA6\xE9\x9F\x5B\x64\xB4\xDD\x0E" + "\x76\xB6\x82\xF6\xA9\xAD\xB5\xC4"; + + std::string recover; + recover.resize(privC.MaxPlaintextLength(cipher.size())); + + DecodingResult result = privC.Decrypt(GlobalRNG(), C2B(&cipher[0]), cipher.size(), C2B(&recover[0])); + if (result.isValidCoding) + recover.resize(result.messageLength); + else + recover.resize(0); + + pass = (plain == recover) && pass; + std::cout << (pass ? "passed " : "FAILED "); + std::cout << "decryption known answer\n"; + } + return pass; +} + +bool ValidateEC2N_Encrypt() +{ + // DEREncode() changed to Save() at Issue 569. + ECIES::Decryptor cpriv(GlobalRNG(), ASN1::sect193r1()); + ECIES::Encryptor cpub(cpriv); + ByteQueue bq; + cpriv.AccessMaterial().Save(bq); + cpub.AccessKey().AccessGroupParameters().SetEncodeAsOID(true); + cpub.AccessMaterial().Save(bq); + bool pass = CryptoSystemValidate(cpriv, cpub); + + std::cout << "Turning on point compression..." << std::endl; + cpriv.AccessKey().AccessGroupParameters().SetPointCompression(true); + cpub.AccessKey().AccessGroupParameters().SetPointCompression(true); + pass = CryptoSystemValidate(cpriv, cpub) && pass; + + return pass; +} + +bool ValidateElGamal() +{ + std::cout << "\nElGamal validation suite running...\n\n"; + bool pass = true; + { + // Data from https://github.com/weidai11/cryptopp/issues/876. + const std::string encodedPublicKey = + "MHYwTwYGKw4HAgEBMEUCIQDebUvQDd9UPMmD27BJ ovZSIgWfexL0SWkfJQPMLsJvMwIgDy/kEthwO6Q+" + "L8XHnzumnEKs+txH8QkQD+M/8u82ql0DIwACIAY6 rfW+BTcRZ9QAJovgoB8DgNLJ8ocqOeF4nEBB0DHH"; + StringSource decodedPublicKey(encodedPublicKey, true, new Base64Decoder); + + ElGamal::PublicKey publicKey; + publicKey.Load(decodedPublicKey); + pass = publicKey.Validate(GlobalRNG(), 3) && pass; + } + { + // Data from https://github.com/weidai11/cryptopp/issues/876. + const std::string encodedPrivateKey = + "MHkCAQAwTwYGKw4HAgEBMEUCIQDebUvQDd9UPMmD 27BJovZSIgWfexL0SWkfJQPMLsJvMwIgDy/kEthw" + "O6Q+L8XHnzumnEKs+txH8QkQD+M/8u82ql0EIwIh AJb0S4TZLvApTVjXZyocPJ5tUgWgRqScXm5vNqu2" + "YqdM"; + StringSource decodedPrivateKey(encodedPrivateKey, true, new Base64Decoder); + + ElGamal::PrivateKey privateKey; + privateKey.Load(decodedPrivateKey); + pass = privateKey.Validate(GlobalRNG(), 3) && pass; + } + { + FileSource fc(DataDir("TestData/elgc1024.dat").c_str(), true, new HexDecoder); + ElGamalDecryptor privC(fc); + ElGamalEncryptor pubC(privC); + privC.AccessKey().Precompute(); + ByteQueue queue; + privC.AccessKey().SavePrecomputation(queue); + privC.AccessKey().LoadPrecomputation(queue); + + pass = CryptoSystemValidate(privC, pubC) && pass; + } + return pass; +} + +bool ValidateDLIES() +{ + std::cout << "\nDLIES validation suite running...\n\n"; + bool pass = true; + { + FileSource fc(DataDir("TestData/dlie1024.dat").c_str(), true, new HexDecoder); + DLIES<>::Decryptor privC(fc); + DLIES<>::Encryptor pubC(privC); + pass = CryptoSystemValidate(privC, pubC) && pass; + } + { + std::cout << "Generating new encryption key..." << std::endl; + DLIES<>::GroupParameters gp; + gp.GenerateRandomWithKeySize(GlobalRNG(), 128); + DLIES<>::Decryptor decryptor; + decryptor.AccessKey().GenerateRandom(GlobalRNG(), gp); + DLIES<>::Encryptor encryptor(decryptor); + + pass = CryptoSystemValidate(decryptor, encryptor) && pass; + } + return pass; +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/validat9.cpp b/external/ours/library/crypto/src/shared/original/validat9.cpp new file mode 100755 index 000000000..735afe51c --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/validat9.cpp @@ -0,0 +1,704 @@ +// validat9.cpp - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017. +// Source files split in July 2018 to expedite compiles. + +#include "pch.h" + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 + +#include "cryptlib.h" +#include "cpu.h" +#include "validate.h" + +#include "asn.h" +#include "oids.h" + +#include "md2.h" +#include "md4.h" +#include "md5.h" + +#include "sha.h" +#include "sha3.h" +#include "pssr.h" +#include "ripemd.h" +#include "whrlpool.h" + +#include "rw.h" +#include "dsa.h" +#include "luc.h" +#include "rsa.h" +#include "esign.h" +#include "rabin.h" +#include "pubkey.h" +#include "eccrypto.h" + +// Curve25519 +#include "xed25519.h" +#include "donna.h" +#include "naclite.h" + +#include +#include +#include + +// Aggressive stack checking with VS2005 SP1 and above. +#if (_MSC_FULL_VER >= 140050727) +# pragma strict_gs_check (on) +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4505 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +bool ValidateRSA_Sign() +{ + // Must be large enough for RSA-3072 to test SHA3_256 + byte out[256]; + bool pass = true, fail; + + { + const char plain[] = "Everyone gets Friday off."; + const byte signature[] = + "\x05\xfa\x6a\x81\x2f\xc7\xdf\x8b\xf4\xf2\x54\x25\x09\xe0\x3e\x84" + "\x6e\x11\xb9\xc6\x20\xbe\x20\x09\xef\xb4\x40\xef\xbc\xc6\x69\x21" + "\x69\x94\xac\x04\xf3\x41\xb5\x7d\x05\x20\x2d\x42\x8f\xb2\xa2\x7b" + "\x5c\x77\xdf\xd9\xb1\x5b\xfc\x3d\x55\x93\x53\x50\x34\x10\xc1\xe1"; + + FileSource keys(DataDir("TestData/rsa512a.dat").c_str(), true, new HexDecoder); + Weak::RSASSA_PKCS1v15_MD2_Signer rsaPriv(keys); + Weak::RSASSA_PKCS1v15_MD2_Verifier rsaPub(rsaPriv); + + size_t signatureLength = rsaPriv.SignMessage(GlobalRNG(), (byte *)plain, strlen(plain), out); + CRYPTOPP_ASSERT(signatureLength <= sizeof(out)); + fail = memcmp(signature, out, signatureLength) != 0; + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "signature check against test vector\n"; + + fail = !rsaPub.VerifyMessage((byte *)plain, strlen(plain), out, signatureLength); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "verification check against test vector\n"; + + out[10]++; + fail = rsaPub.VerifyMessage((byte *)plain, strlen(plain), out, signatureLength); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "invalid signature verification\n"; + } + ///// + { + const char plain[] = "Everyone gets Friday off."; + const byte signature[] = + "\x2e\x87\xda\x1f\xe4\xda\x1d\x7a\xb7\xf2\x42\x36\xe9\xc0\x4e\xab\x3f\x03\x71\xe1" + "\x2b\xc5\x3c\xbf\x21\x21\xa8\xd6\x28\xb0\x08\xfd\x9c\xf6\x94\xbd\x37\x32\xda\xfc" + "\x42\x1c\x8e\xdb\x8a\x81\x90\x46\x45\xb4\xde\x9e\xce\x90\xfe\xa1\xfd\xbc\x5a\xce" + "\xca\x59\x89\x93\xc0\x0f\x2f\xf1\x13\xb0\xf5\x3d\xa3\x9a\x85\xb7\x40\xd9\x34\x88" + "\x29\xb2\x4a\x0f\x9b\xbe\x22\x3a\x5b\x54\x51\xb7\xf0\x10\x72\x50\xc4\x2a\xe9\xe4" + "\xc3\x82\xeb\x32\x33\x14\xb6\xf2\x7b\x30\x7a\xbf\xc2\xf3\x0f\x4d\x72\xa0\x8d\xa1" + "\xc6\xce\xd0\xa3\x3c\xf7\x23\x4b\xb7\x2c\x5e\xca\x83\x01\xc7\x5c\xd5\xd0\xd1\x94" + "\x43\xf0\xad\xa2\xe6\x72\x2b\x13\x39\xb2\x4b\x25\x91\x3a\x4f\x53\x05\x00\x8c\xc7" + "\xcf\x4f\x11\x64\xe6\xf4\x1a\x4d\x90\x7e\xf1\xfe\xed\xec\x8d\xbb\x00\x31\x2e\x03" + "\xbe\x87\x84\x60\xfb\x5e\xef\x9d\x18\x2c\x28\x3d\xaa\x67\x80\xa3\x62\x07\x06\x5e" + "\xce\xee\x3b\xd0\x78\xb5\x98\x38\x1e\xe8\x62\x19\x9c\xc3\xd4\xf7\xc2\xc5\x00\xf0" + "\xeb\x89\x65\x53\x35\xe7\x13\x7e\xbb\x26\xb0\x76\x9c\xf2\x80\xaa\xe1\xb1\x0a\xa6" + "\x47\xfc\x5f\xe0\x7f\x82\xd7\x83\x41\xc3\x50\xa1\xe0\x0e\x1a\xe4"; + + FileSource keys(DataDir("TestData/rsa2048a.dat").c_str(), true, new HexDecoder); + RSASS::Signer rsaPriv(keys); + RSASS::Verifier rsaPub(rsaPriv); + + size_t signatureLength = rsaPriv.SignMessage(GlobalRNG(), (byte *)plain, strlen(plain), out); + CRYPTOPP_ASSERT(signatureLength <= sizeof(out)); + fail = memcmp(signature, out, signatureLength) != 0; + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "signature check against test vector\n"; + + fail = !rsaPub.VerifyMessage((byte *)plain, strlen(plain), out, signatureLength); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "verification check against test vector\n"; + + out[10]++; + fail = rsaPub.VerifyMessage((byte *)plain, strlen(plain), out, signatureLength); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "invalid signature verification\n"; + } + + return pass; +} + +bool ValidateNR() +{ + std::cout << "\nNR validation suite running...\n\n"; + bool pass = true; + { + FileSource f(DataDir("TestData/nr2048.dat").c_str(), true, new HexDecoder); + NR::Signer privS(f); + privS.AccessKey().Precompute(); + NR::Verifier pubS(privS); + + pass = SignatureValidate(privS, pubS) && pass; + } + { + std::cout << "Generating new signature key..." << std::endl; + NR::Signer privS(GlobalRNG(), 256); + NR::Verifier pubS(privS); + + pass = SignatureValidate(privS, pubS) && pass; + } + return pass; +} + +bool ValidateDSA(bool thorough) +{ + std::cout << "\nDSA validation suite running...\n\n"; + + bool pass = true; + FileSource fs1(DataDir("TestData/dsa1024.dat").c_str(), true, new HexDecoder); + DSA::Signer priv(fs1); + DSA::Verifier pub(priv); + FileSource fs2(DataDir("TestData/dsa1024b.dat").c_str(), true, new HexDecoder); + DSA::Verifier pub1(fs2); + CRYPTOPP_ASSERT(pub.GetKey() == pub1.GetKey()); + pass = SignatureValidate(priv, pub, thorough) && pass; + + return pass; +} + +bool ValidateLUC_Sign() +{ + FileSource f(DataDir("TestData/luc1024.dat").c_str(), true, new HexDecoder); + LUCSSA_PKCS1v15_SHA_Signer priv(f); + LUCSSA_PKCS1v15_SHA_Verifier pub(priv); + return SignatureValidate(priv, pub); +} + +bool ValidateLUC_DL_Sign() +{ + std::cout << "\nLUC-HMP validation suite running...\n\n"; + + FileSource f(DataDir("TestData/lucs512.dat").c_str(), true, new HexDecoder); + LUC_HMP::Signer privS(f); + LUC_HMP::Verifier pubS(privS); + return SignatureValidate(privS, pubS); +} + +bool ValidateRabin_Sign() +{ + FileSource f(DataDir("TestData/rabi1024.dat").c_str(), true, new HexDecoder); + RabinSS::Signer priv(f); + RabinSS::Verifier pub(priv); + return SignatureValidate(priv, pub); +} + +bool ValidateRW() +{ + std::cout << "\nRW validation suite running...\n\n"; + + FileSource f(DataDir("TestData/rw1024.dat").c_str(), true, new HexDecoder); + RWSS::Signer priv(f); + RWSS::Verifier pub(priv); + + return SignatureValidate(priv, pub); +} + +bool ValidateECP_Sign() +{ + ECDSA::Signer spriv(GlobalRNG(), ASN1::secp192r1()); + ECDSA::Verifier spub(spriv); + ByteQueue bq; + spriv.GetKey().DEREncode(bq); + spub.AccessKey().AccessGroupParameters().SetEncodeAsOID(true); + spub.GetKey().DEREncode(bq); + spriv.AccessKey().BERDecode(bq); + spub.AccessKey().BERDecode(bq); + + spriv.AccessKey().Precompute(); + ByteQueue queue; + spriv.AccessKey().SavePrecomputation(queue); + spriv.AccessKey().LoadPrecomputation(queue); + + return SignatureValidate(spriv, spub); +} + +bool ValidateEC2N_Sign() +{ + // DEREncode() changed to Save() at Issue 569. + ECDSA::Signer spriv(GlobalRNG(), ASN1::sect193r1()); + ECDSA::Verifier spub(spriv); + ByteQueue bq; + spriv.AccessMaterial().Save(bq); + spub.AccessKey().AccessGroupParameters().SetEncodeAsOID(true); + spub.AccessMaterial().Save(bq); + spriv.AccessMaterial().Load(bq); + spub.AccessMaterial().Load(bq); + + spriv.AccessKey().Precompute(); + ByteQueue queue; + spriv.AccessKey().SavePrecomputation(queue); + spriv.AccessKey().LoadPrecomputation(queue); + + return SignatureValidate(spriv, spub); +} + +bool ValidateECDSA() +{ + std::cout << "\nECDSA validation suite running...\n\n"; + + // from Sample Test Vectors for P1363 + GF2NT gf2n(191, 9, 0); + byte a[]="\x28\x66\x53\x7B\x67\x67\x52\x63\x6A\x68\xF5\x65\x54\xE1\x26\x40\x27\x6B\x64\x9E\xF7\x52\x62\x67"; + byte b[]="\x2E\x45\xEF\x57\x1F\x00\x78\x6F\x67\xB0\x08\x1B\x94\x95\xA3\xD9\x54\x62\xF5\xDE\x0A\xA1\x85\xEC"; + EC2N ec(gf2n, PolynomialMod2(a,24), PolynomialMod2(b,24)); + + EC2N::Point P; + bool result = ec.DecodePoint(P, (byte *)"\x04\x36\xB3\xDA\xF8\xA2\x32\x06\xF9\xC4\xF2\x99\xD7\xB2\x1A\x9C\x36\x91\x37\xF2\xC8\x4A\xE1\xAA\x0D" + "\x76\x5B\xE7\x34\x33\xB3\xF9\x5E\x33\x29\x32\xE7\x0E\xA2\x45\xCA\x24\x18\xEA\x0E\xF9\x80\x18\xFB", ec.EncodedPointSize()); + CRYPTOPP_ASSERT(result); CRYPTOPP_UNUSED(result); + + Integer n("40000000000000000000000004a20e90c39067c893bbb9a5H"); + Integer d("340562e1dda332f9d2aec168249b5696ee39d0ed4d03760fH"); + EC2N::Point Q(ec.Multiply(d, P)); + ECDSA::Signer priv(ec, P, n, d); + ECDSA::Verifier pub(priv); + + Integer h("A9993E364706816ABA3E25717850C26C9CD0D89DH"); + Integer k("3eeace72b4919d991738d521879f787cb590aff8189d2b69H"); + const byte sig[]="\x03\x8e\x5a\x11\xfb\x55\xe4\xc6\x54\x71\xdc\xd4\x99\x84\x52\xb1\xe0\x2d\x8a\xf7\x09\x9b\xb9\x30" + "\x0c\x9a\x08\xc3\x44\x68\xc2\x44\xb4\xe5\xd6\xb2\x1b\x3c\x68\x36\x28\x07\x41\x60\x20\x32\x8b\x6e"; + Integer r(sig, 24); + Integer s(sig+24, 24); + + Integer rOut, sOut; + bool fail, pass=true; + + priv.RawSign(k, h, rOut, sOut); + fail = (rOut != r) || (sOut != s); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "signature check against test vector\n"; + + fail = !pub.VerifyMessage((byte *)"abc", 3, sig, sizeof(sig)); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "verification check against test vector\n"; + + fail = pub.VerifyMessage((byte *)"xyz", 3, sig, sizeof(sig)); + pass = pass && !fail; + + pass = SignatureValidate(priv, pub) && pass; + + return pass; +} + +bool ValidateECDSA_RFC6979() +{ + std::cout << "\nRFC6979 deterministic ECDSA validation suite running...\n\n"; + + DL_Algorithm_ECDSA_RFC6979 sign; + + const Integer x("09A4D6792295A7F730FC3F2B49CBC0F62E862272Fh"); + const Integer e("AF2BDBE1AA9B6EC1E2ADE1D694F41FC71A831D0268E9891562113D8A62ADD1BFh"); + const Integer q("4000000000000000000020108A2E0CC0D99F8A5EFh"); + const Integer k("23AF4074C90A02B3FE61D286D5C87F425E6BDD81Bh"); + const Integer &k_out = sign.GenerateRandom(x, q, e); + + bool pass = (k_out == k); + + std::cout << (pass ? "passed " : "FAILED "); + std::cout << "deterministic k generation against test vector\n"; + + return pass; +} + +// from http://www.teletrust.de/fileadmin/files/oid/ecgdsa_final.pdf +bool ValidateECGDSA(bool thorough) +{ + std::cout << "\nECGDSA validation suite running...\n\n"; + + bool fail, pass=true; + + // 2.4.1 Examples of ECGDSA over GF(p) with the hash function RIPEMD-160 (p. 10) + if (thorough) + { + const OID oid = ASN1::brainpoolP192r1(); + DL_GroupParameters_EC params(oid); + Integer x("0x 80F2425E 89B4F585 F27F3536 ED834D68 E3E492DE 08FE84B9"); + ECGDSA::Signer signer(params, x); + ECGDSA::Verifier verifier(signer); + + Integer e("0x 00000000 577EF842 B32FDE45 79727FFF 02F7A280 74ADC4EF"); + Integer k("0x 22C17C2A 367DD85A B8A365ED 06F19C43 F9ED1834 9A9BC044"); + + Integer r, s; + signer.RawSign(k, e, r, s); + + Integer rExp("0x 2D017BE7 F117FF99 4ED6FC63 CA5B4C7A 0430E9FA 095DAFC4"); + Integer sExp("0x C02B5CC5 C51D5411 060BF024 5049F824 839F671D 78A1BBF1"); + + fail = (r != rExp) || (s != sExp); + pass = pass && !fail; + + const byte msg[] = "Example of ECGDSA with the hash function RIPEMD-160"; + const size_t len = strlen((char*)msg); + + byte signature[48]; + r.Encode(signature+0, 24); + s.Encode(signature+24, 24); + + fail = !verifier.VerifyMessage(msg, len, signature, sizeof(signature)); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "brainpoolP192r1 using RIPEMD-160\n"; + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + } + + // 2.4.1 Examples of ECGDSA over GF(p) with the hash function RIPEMD-160 (p. 13) + if (thorough) + { + const OID oid = ASN1::brainpoolP256r1(); + DL_GroupParameters_EC params(oid); + Integer x("0x 47B3A278 62DEF037 49ACF0D6 00E69F9B 851D01ED AEFA531F 4D168E78 7307F4D8"); + ECGDSA::Signer signer(params, x); + ECGDSA::Verifier verifier(signer); + + Integer e("0x 00000000 00000000 00000000 577EF842 B32FDE45 79727FFF 02F7A280 74ADC4EF"); + Integer k("0x 908E3099 776261A4 558FF7A9 FA6DFFE0 CA6BB3F9 CB35C2E4 E1DC73FD 5E8C08A3"); + + Integer r, s; + signer.RawSign(k, e, r, s); + + Integer rExp("0x 62CCD1D2 91E62F6A 4FFBD966 C66C85AA BA990BB6 AB0C087D BD54A456 CCC84E4C"); + Integer sExp("0x 9119719B 08EEA0D6 BC56E4D1 D37369BC F3768445 EF65CAE4 A37BF6D4 3BD01646"); + + fail = (r != rExp) || (s != sExp); + pass = pass && !fail; + + const byte msg[] = "Example of ECGDSA with the hash function RIPEMD-160"; + const size_t len = strlen((char*)msg); + + byte signature[64]; + r.Encode(signature+0, 32); + s.Encode(signature+32, 32); + + fail = !verifier.VerifyMessage(msg, len, signature, sizeof(signature)); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "brainpoolP256r1 using RIPEMD-160\n"; + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + } + + // 2.4.1 Examples of ECGDSA over GF(p) with the hash function RIPEMD-160 (p. 16) + if (thorough) + { + const OID oid = ASN1::brainpoolP320r1(); + DL_GroupParameters_EC params(oid); + Integer x("0x 48683594 5A3A284F FC52629A D48D8F37 F4B2E993 9C52BC72 362A9961 40192AEF 7D2AAFF0 C73A51C5"); + ECGDSA::Signer signer(params, x); + ECGDSA::Verifier verifier(signer); + + Integer e("0x 00000000 00000000 00000000 00000000 00000000 577EF842 B32FDE45 79727FFF 02F7A280 74ADC4EF"); + Integer k("0x C70BC00A 77AD7872 5D36CEEC 27D6F956 FB546EEF 6DC90E35 31452BD8 7ECE8A4A 7AD730AD C299D81B"); + + Integer r, s; + signer.RawSign(k, e, r, s); + + Integer rExp("0x 3C925969 FAB22F7A E7B8CC5D 50CB0867 DFDB2CF4 FADA3D49 0DF75D72 F7563186 419494C9 8F9C82A6"); + Integer sExp("0x 06AB5250 B31A8E93 56194894 61733200 E4FD5C12 75C0AB37 E7E41149 5BAAE145 41DF6DE6 66B8CA56"); + + fail = (r != rExp) || (s != sExp); + pass = pass && !fail; + + const byte msg[] = "Example of ECGDSA with the hash function RIPEMD-160"; + const size_t len = strlen((char*)msg); + + byte signature[80]; + r.Encode(signature+0, 40); + s.Encode(signature+40, 40); + + fail = !verifier.VerifyMessage(msg, len, signature, sizeof(signature)); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "brainpoolP320r1 using RIPEMD-160\n"; + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + } + + // 2.4.1 Examples of ECGDSA over GF(p) with the hash function SHA-1 (p. 19) + { + const OID oid = ASN1::brainpoolP192r1(); + DL_GroupParameters_EC params(oid); + Integer x("0x 80F2425E 89B4F585 F27F3536 ED834D68 E3E492DE 08FE84B9"); + ECGDSA::Signer signer(params, x); + ECGDSA::Verifier verifier(signer); + + Integer e("0x 00000000 CF00CD42 CAA80DDF 8DDEBDFD 32F2DA15 11B53F29"); + Integer k("0x 22C17C2A 367DD85A B8A365ED 06F19C43 F9ED1834 9A9BC044"); + + Integer r, s; + signer.RawSign(k, e, r, s); + + Integer rExp("0x 2D017BE7 F117FF99 4ED6FC63 CA5B4C7A 0430E9FA 095DAFC4"); + Integer sExp("0x 18FD604E 5F00F55B 3585C052 8C319A2B 05B8F2DD EE9CF1A6"); + + fail = (r != rExp) || (s != sExp); + pass = pass && !fail; + + const byte msg[] = "Example of ECGDSA with the hash function SHA-1"; + const size_t len = strlen((char*)msg); + + byte signature[48]; + r.Encode(signature+0, 24); + s.Encode(signature+24, 24); + + fail = !verifier.VerifyMessage(msg, len, signature, sizeof(signature)); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "brainpoolP192r1 using SHA-1\n"; + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + } + + // 2.4.1 Examples of ECGDSA over GF(p) with the hash function SHA-224 (p. 23) + { + const OID oid = ASN1::brainpoolP320r1(); + DL_GroupParameters_EC params(oid); + Integer x("0x 48683594 5A3A284F FC52629A D48D8F37 F4B2E993 9C52BC72 362A9961 40192AEF 7D2AAFF0 C73A51C5"); + ECGDSA::Signer signer(params, x); + ECGDSA::Verifier verifier(signer); + + Integer e("0x 00000000 00000000 00000000 92AE8A0E 8D08EADE E9426378 714FF3E0 1957587D 2876FA70 D40E3144"); + Integer k("0x C70BC00A 77AD7872 5D36CEEC 27D6F956 FB546EEF 6DC90E35 31452BD8 7ECE8A4A 7AD730AD C299D81B"); + + Integer r, s; + signer.RawSign(k, e, r, s); + + Integer rExp("0x 3C925969 FAB22F7A E7B8CC5D 50CB0867 DFDB2CF4 FADA3D49 0DF75D72 F7563186 419494C9 8F9C82A6"); + Integer sExp("0x 6EA191CA 0D468AC3 E9568768 9338357C 7D0BACB3 F1D87E0D EC05F635 B7ADB842 75AA0086 60F812CF"); + + fail = (r != rExp) || (s != sExp); + pass = pass && !fail; + + const byte msg[] = "Example of ECGDSA with the hash function SHA-224"; + const size_t len = strlen((char*)msg); + + byte signature[80]; + r.Encode(signature+0, 40); + s.Encode(signature+40, 40); + + fail = !verifier.VerifyMessage(msg, len, signature, sizeof(signature)); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "brainpoolP320r1 using SHA-224\n"; + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + } + + // 2.4.1 Examples of ECGDSA over GF(p) with the hash function SHA-256 (p. 27) + { + const OID oid = ASN1::brainpoolP320r1(); + DL_GroupParameters_EC params(oid); + Integer x("0x 48683594 5A3A284F FC52629A D48D8F37 F4B2E993 9C52BC72 362A9961 40192AEF 7D2AAFF0 C73A51C5"); + ECGDSA::Signer signer(params, x); + ECGDSA::Verifier verifier(signer); + + Integer e("0x 00000000 00000000 37ED8AA9 4AE667DB BB753330 E050EB8E 12195807 ECDC4FB1 0E0662B4 22C219D7"); + Integer k("0x C70BC00A 77AD7872 5D36CEEC 27D6F956 FB546EEF 6DC90E35 31452BD8 7ECE8A4A 7AD730AD C299D81B"); + + Integer r, s; + signer.RawSign(k, e, r, s); + + Integer rExp("0x 3C925969 FAB22F7A E7B8CC5D 50CB0867 DFDB2CF4 FADA3D49 0DF75D72 F7563186 419494C9 8F9C82A6"); + Integer sExp("0x 24370797 A9D11717 BBBB2B76 2E08ECD0 7DD7E033 F544E47C BF3C6D16 FD90B51D CC2E4DD8 E6ECD8CD"); + + fail = (r != rExp) || (s != sExp); + pass = pass && !fail; + + const byte msg[] = "Example of ECGDSA with the hash function SHA-256"; + const size_t len = strlen((char*)msg); + + byte signature[80]; + r.Encode(signature+0, 40); + s.Encode(signature+40, 40); + + fail = !verifier.VerifyMessage(msg, len, signature, sizeof(signature)); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "brainpoolP320r1 using SHA-256\n"; + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + } + + // 2.4.1 Examples of ECGDSA over GF(p) with the hash function SHA-384 (p. 34) + { + const OID oid = ASN1::brainpoolP512r1(); + DL_GroupParameters_EC params(oid); + Integer x("0x 92006A98 8AF96D91 57AADCF8 62716962 7CE2ECC4 C58ECE5C 1A0A8642 11AB764C 04236FA0 160857A7 8E71CCAE 4D79D52E 5A69A457 8AF50658 1F598FA9 B4F7DA68"); + ECGDSA::Signer signer(params, x); + ECGDSA::Verifier verifier(signer); + + Integer e("0x 00000000 00000000 00000000 00000000 68FEAB7D 8BF8A779 4466E447 5959946B 2136C084 A86090CA 8070C980 68B1250D 88213190 6B7E0CB8 475F9054 E9290C2E"); + Integer k("0x 6942B01D 5901BEC1 506BB874 9618E22E C0FCD7F3 5159D51E D53BA77A 78752128 A58232AD 8E0E021A FDE1477F F4C74FDF FE88AE2D 15D89B56 F6D73C03 77631D2B"); + + Integer r, s; + signer.RawSign(k, e, r, s); + + Integer rExp("0x 0104918B 2B32B1A5 49BD43C3 0092953B 4164CA01 A1A97B5B 0756EA06 3AC16B41 B88A1BAB 4538CD7D 8466180B 3E3F5C86 46AC4A45 F564E9B6 8FEE72ED 00C7AC48"); + Integer sExp("0x 3D233E9F D9EB152E 889F4F7C F325B464 0894E5EA 44C51443 54305CD4 BF70D234 8257C2DB E06C5544 92CE9FDD 6861A565 77B53E5E E80E6062 31A4CF06 8FA1EC21"); + + fail = (r != rExp) || (s != sExp); + pass = pass && !fail; + + const byte msg[] = "Example of ECGDSA with the hash function SHA-384"; + const size_t len = strlen((char*)msg); + + byte signature[128]; + r.Encode(signature+0, 64); + s.Encode(signature+64, 64); + + fail = !verifier.VerifyMessage(msg, len, signature, sizeof(signature)); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "brainpoolP512r1 using SHA-384\n"; + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + } + + // 2.4.1 Examples of ECGDSA over GF(p) with the hash function SHA-512 (p. 38) + { + const OID oid = ASN1::brainpoolP512r1(); + DL_GroupParameters_EC params(oid); + Integer x("0x 92006A98 8AF96D91 57AADCF8 62716962 7CE2ECC4 C58ECE5C 1A0A8642 11AB764C 04236FA0 160857A7 8E71CCAE 4D79D52E 5A69A457 8AF50658 1F598FA9 B4F7DA68"); + ECGDSA::Signer signer(params, x); + ECGDSA::Verifier verifier(signer); + + Integer e("0x 1A95EF81 D213BD3B 8191E7FE 7F5BFD43 F51E3EE5 A4FD3D08 4A7C9BB5 411F4649 746AEBC6 623D4DEA 7E02DC5A 85E24AF2 96B5A555 AD470413 71E4BF64 380F3E34"); + Integer k("0x 6942B01D 5901BEC1 506BB874 9618E22E C0FCD7F3 5159D51E D53BA77A 78752128 A58232AD 8E0E021A FDE1477F F4C74FDF FE88AE2D 15D89B56 F6D73C03 77631D2B"); + + Integer r, s; + signer.RawSign(k, e, r, s); + + Integer rExp("0x 0104918B 2B32B1A5 49BD43C3 0092953B 4164CA01 A1A97B5B 0756EA06 3AC16B41 B88A1BAB 4538CD7D 8466180B 3E3F5C86 46AC4A45 F564E9B6 8FEE72ED 00C7AC48"); + Integer sExp("0x 17A011F8 DD7B5665 2B27AA6D 6E7BDF3C 7C23B5FA 32910FBA A107E627 0E1CA8A7 A263F661 8E6098A0 D6CD6BA1 C03544C5 425875EC B3418AF5 A3EE3F32 143E48D2"); + + fail = (r != rExp) || (s != sExp); + pass = pass && !fail; + + const byte msg[] = "Example of ECGDSA with the hash function SHA-512"; + const size_t len = strlen((char*)msg); + + byte signature[128]; + r.Encode(signature+0, 64); + s.Encode(signature+64, 64); + + fail = !verifier.VerifyMessage(msg, len, signature, sizeof(signature)); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "brainpoolP512r1 using SHA-512\n"; + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + } + + return pass; +} + +bool ValidateESIGN() +{ + std::cout << "\nESIGN validation suite running...\n\n"; + + bool pass = true, fail; + + const char plain[] = "test"; + const byte signature[] = + "\xA3\xE3\x20\x65\xDE\xDA\xE7\xEC\x05\xC1\xBF\xCD\x25\x79\x7D\x99\xCD\xD5\x73\x9D\x9D\xF3\xA4\xAA\x9A\xA4\x5A\xC8\x23\x3D\x0D\x37" + "\xFE\xBC\x76\x3F\xF1\x84\xF6\x59\x14\x91\x4F\x0C\x34\x1B\xAE\x9A\x5C\x2E\x2E\x38\x08\x78\x77\xCB\xDC\x3C\x7E\xA0\x34\x44\x5B\x0F" + "\x67\xD9\x35\x2A\x79\x47\x1A\x52\x37\x71\xDB\x12\x67\xC1\xB6\xC6\x66\x73\xB3\x40\x2E\xD6\xF2\x1A\x84\x0A\xB6\x7B\x0F\xEB\x8B\x88" + "\xAB\x33\xDD\xE4\x83\x21\x90\x63\x2D\x51\x2A\xB1\x6F\xAB\xA7\x5C\xFD\x77\x99\xF2\xE1\xEF\x67\x1A\x74\x02\x37\x0E\xED\x0A\x06\xAD" + "\xF4\x15\x65\xB8\xE1\xD1\x45\xAE\x39\x19\xB4\xFF\x5D\xF1\x45\x7B\xE0\xFE\x72\xED\x11\x92\x8F\x61\x41\x4F\x02\x00\xF2\x76\x6F\x7C" + "\x79\xA2\xE5\x52\x20\x5D\x97\x5E\xFE\x39\xAE\x21\x10\xFB\x35\xF4\x80\x81\x41\x13\xDD\xE8\x5F\xCA\x1E\x4F\xF8\x9B\xB2\x68\xFB\x28"; + + FileSource keys(DataDir("TestData/esig1536.dat").c_str(), true, new HexDecoder); + ESIGN::Signer signer(keys); + ESIGN::Verifier verifier(signer); + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + + fail = !verifier.VerifyMessage((byte *)plain, strlen(plain), signature, verifier.SignatureLength()); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "verification check against test vector\n"; + + std::cout << "Generating signature key from seed..." << std::endl; + signer.AccessKey().GenerateRandom(GlobalRNG(), MakeParameters("Seed", ConstByteArrayParameter((const byte *)"test", 4))("KeySize", 3*512)); + verifier = signer; + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + + return pass; +} + +bool ValidateEd25519() +{ + std::cout << "\ned25519 validation suite running...\n\n"; + bool pass = true, fail; + + const char plain[] = "test"; + const byte signature[] = + "\x91\x12\x44\x91\xA5\x99\xF8\x49\xBA\xB2\xC4\xF2\xBA\x0B\xAA\x99" + "\xC8\xC5\xF5\x19\xDC\x07\xD4\x4C\xF7\x31\xDE\x2F\x2B\x81\xB2\x81" + "\xF6\xA7\xDE\x33\x29\xCA\x45\xAC\x69\x2A\x80\xB7\xDB\x7F\x07\x37" + "\x77\xC4\xBF\xC5\x45\x79\x3A\xAC\xB5\x16\xAE\x4E\xD9\x16\x95\x0E"; + + FileSource keys(DataDir("TestData/ed25519.dat").c_str(), true, new HexDecoder); + ed25519::Signer signer(keys); + ed25519::Verifier verifier(signer); + + fail = !SignatureValidate(signer, verifier); + pass = pass && !fail; + + fail = !verifier.VerifyMessage((byte *)plain, strlen(plain), signature, verifier.SignatureLength()); + pass = pass && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << "verification check against test vector\n"; + + return pass; +} + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/validate.h b/external/ours/library/crypto/src/shared/original/validate.h new file mode 100755 index 000000000..d55e48f79 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/vmac.cpp b/external/ours/library/crypto/src/shared/original/vmac.cpp new file mode 100755 index 000000000..c625c6bb4 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/vmac.cpp @@ -0,0 +1,894 @@ +// vmac.cpp - originally written and placed in the public domain by Wei Dai +// based on Ted Krovetz's public domain vmac.c and draft-krovetz-vmac-01.txt + +#include "pch.h" +#include "config.h" + +#include "vmac.h" +#include "cpu.h" +#include "argnames.h" +#include "secblock.h" + +#if defined(_MSC_VER) && !CRYPTOPP_BOOL_SLOW_WORD64 +#include +#endif + +#if defined(CRYPTOPP_DISABLE_VMAC_ASM) +# undef CRYPTOPP_X86_ASM_AVAILABLE +# undef CRYPTOPP_X32_ASM_AVAILABLE +# undef CRYPTOPP_X64_ASM_AVAILABLE +# undef CRYPTOPP_SSE2_ASM_AVAILABLE +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4731) +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +#if defined(CRYPTOPP_WORD128_AVAILABLE) && !defined(CRYPTOPP_X64_ASM_AVAILABLE) +using CryptoPP::word128; +using CryptoPP::word64; +# define VMAC_BOOL_WORD128 1 +#else +using CryptoPP::word64; +# define VMAC_BOOL_WORD128 0 +#endif + +#ifdef __BORLANDC__ +#define const // Turbo C++ 2006 workaround +#endif +const word64 p64 = W64LIT(0xfffffffffffffeff); /* 2^64 - 257 prime */ +const word64 m62 = W64LIT(0x3fffffffffffffff); /* 62-bit mask */ +const word64 m63 = W64LIT(0x7fffffffffffffff); /* 63-bit mask */ +const word64 m64 = W64LIT(0xffffffffffffffff); /* 64-bit mask */ +const word64 mpoly = W64LIT(0x1fffffff1fffffff); /* Poly key mask */ +#ifdef __BORLANDC__ +#undef const +#endif + +#if VMAC_BOOL_WORD128 +// workaround GCC Bug 31690: ICE with const __uint128_t and C++ front-end +# if defined(__powerpc__) && defined (CRYPTOPP_GCC_VERSION) && (CRYPTOPP_GCC_VERSION < 50300) +# define m126 ((word128(m62)<<64)|m64) +# else +const word128 m126 = (word128(m62)<<64)|m64; /* 126-bit mask */ +# endif +#endif + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void VMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs ¶ms) +{ + int digestLength = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize()); + if (digestLength != 8 && digestLength != 16) + throw InvalidArgument("VMAC: DigestSize must be 8 or 16"); + m_is128 = digestLength == 16; + + m_L1KeyLength = params.GetIntValueWithDefault(Name::L1KeyLength(), 128); + if (m_L1KeyLength <= 0 || m_L1KeyLength % 128 != 0) + throw InvalidArgument("VMAC: L1KeyLength must be a positive multiple of 128"); + + AllocateBlocks(); + + BlockCipher &cipher = AccessCipher(); + cipher.SetKey(userKey, keylength, params); + const unsigned int blockSize = cipher.BlockSize(); + const unsigned int blockSizeInWords = blockSize / sizeof(word64); + SecBlock > out(blockSizeInWords); + AlignedSecByteBlock in; + in.CleanNew(blockSize); + size_t i; + + /* Fill nh key */ + in[0] = 0x80; + cipher.AdvancedProcessBlocks(in, NULLPTR, (byte *)m_nhKey(), m_nhKeySize()*sizeof(word64), cipher.BT_InBlockIsCounter); + ConditionalByteReverse(BIG_ENDIAN_ORDER, m_nhKey(), m_nhKey(), m_nhKeySize()*sizeof(word64)); + + /* Fill poly key */ + in[0] = 0xC0; + in[15] = 0; + for (i = 0; i <= (size_t)m_is128; i++) + { + cipher.ProcessBlock(in, out.BytePtr()); + m_polyState()[i*4+2] = GetWord(true, BIG_ENDIAN_ORDER, out.BytePtr()) & mpoly; + m_polyState()[i*4+3] = GetWord(true, BIG_ENDIAN_ORDER, out.BytePtr()+8) & mpoly; + in[15]++; + } + + /* Fill ip key */ + in[0] = 0xE0; + in[15] = 0; + word64 *l3Key = m_l3Key(); + CRYPTOPP_ASSERT(IsAlignedOn(l3Key,GetAlignmentOf())); + + for (i = 0; i <= (size_t)m_is128; i++) + do + { + cipher.ProcessBlock(in, out.BytePtr()); + l3Key[i*2+0] = GetWord(true, BIG_ENDIAN_ORDER, out.BytePtr()); + l3Key[i*2+1] = GetWord(true, BIG_ENDIAN_ORDER, out.BytePtr()+8); + in[15]++; + } while ((l3Key[i*2+0] >= p64) || (l3Key[i*2+1] >= p64)); + + m_padCached = false; + size_t nonceLength; + const byte *nonce = GetIVAndThrowIfInvalid(params, nonceLength); + Resynchronize(nonce, (int)nonceLength); +} + +void VMAC_Base::GetNextIV(RandomNumberGenerator &rng, byte *IV) +{ + SimpleKeyingInterface::GetNextIV(rng, IV); + IV[0] &= 0x7f; +} + +void VMAC_Base::Resynchronize(const byte *nonce, int len) +{ + size_t length = ThrowIfInvalidIVLength(len); + size_t s = IVSize(); + byte *storedNonce = m_nonce(); + + if (m_is128) + { + memset(storedNonce, 0, s-length); + memcpy(storedNonce+s-length, nonce, length); + AccessCipher().ProcessBlock(storedNonce, m_pad()); + } + else + { + if (m_padCached && (storedNonce[s-1] | 1) == (nonce[length-1] | 1)) + { + m_padCached = VerifyBufsEqual(storedNonce+s-length, nonce, length-1); + for (size_t i=0; m_padCached && i>64); rl = word64(p);} + #define AccumulateNH(a, b, c) a += word128(b)*(c) + #define Multiply128(r, i1, i2) r = word128(word64(i1)) * word64(i2) +#else + #if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) && (defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64)) + #define MUL32(a, b) __emulu(word32(a), word32(b)) + #else + #define MUL32(a, b) ((word64)((word32)(a)) * (word32)(b)) + #endif + #if defined(CRYPTOPP_X64_ASM_AVAILABLE) + #define DeclareNH(a) word64 a##0=0, a##1=0 + #define MUL64(rh,rl,i1,i2) asm ("mulq %3" : "=a"(rl), "=d"(rh) : "a"(i1), "g"(i2) : "cc"); + #define AccumulateNH(a, b, c) asm ("mulq %3; addq %%rax, %0; adcq %%rdx, %1" : "+r"(a##0), "+r"(a##1) : "a"(b), "g"(c) : "%rdx", "cc"); + #define ADD128(rh,rl,ih,il) asm ("addq %3, %1; adcq %2, %0" : "+r"(rh),"+r"(rl) : "r"(ih),"r"(il) : "cc"); + #elif defined(_MSC_VER) && !CRYPTOPP_BOOL_SLOW_WORD64 + #define DeclareNH(a) word64 a##0=0, a##1=0 + #define MUL64(rh,rl,i1,i2) (rl) = _umul128(i1,i2,&(rh)); + #define AccumulateNH(a, b, c) {\ + word64 ph, pl;\ + pl = _umul128(b,c,&ph);\ + a##0 += pl;\ + a##1 += ph + (a##0 < pl);} + #else + #define VMAC_BOOL_32BIT 1 + #define DeclareNH(a) word64 a##0=0, a##1=0, a##2=0 + #define MUL64(rh,rl,i1,i2) \ + { word64 _i1 = (i1), _i2 = (i2); \ + word64 m1= MUL32(_i1,_i2>>32); \ + word64 m2= MUL32(_i1>>32,_i2); \ + rh = MUL32(_i1>>32,_i2>>32); \ + rl = MUL32(_i1,_i2); \ + ADD128(rh,rl,(m1 >> 32),(m1 << 32)); \ + ADD128(rh,rl,(m2 >> 32),(m2 << 32)); \ + } + #define AccumulateNH(a, b, c) {\ + word64 p = MUL32(b, c);\ + a##1 += word32((p)>>32);\ + a##0 += word32(p);\ + p = MUL32((b)>>32, c);\ + a##2 += word32((p)>>32);\ + a##1 += word32(p);\ + p = MUL32((b)>>32, (c)>>32);\ + a##2 += p;\ + p = MUL32(b, (c)>>32);\ + a##1 += word32(p);\ + a##2 += word32(p>>32);} + #endif +#endif +#ifndef VMAC_BOOL_32BIT + #define VMAC_BOOL_32BIT 0 +#endif +#ifndef ADD128 + #define ADD128(rh,rl,ih,il) \ + { word64 _il = (il); \ + (rl) += (_il); \ + (rh) += (ih) + ((rl) < (_il)); \ + } +#endif + +template +void VMAC_Base::VHASH_Update_Template(const word64 *data, size_t blocksRemainingInWord64) +{ + CRYPTOPP_ASSERT(IsAlignedOn(m_polyState(),GetAlignmentOf())); + CRYPTOPP_ASSERT(IsAlignedOn(m_nhKey(),GetAlignmentOf())); + + #define INNER_LOOP_ITERATION(j) {\ + word64 d0 = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, data[i+2*j+0]);\ + word64 d1 = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, data[i+2*j+1]);\ + AccumulateNH(nhA, d0+nhK[i+2*j+0], d1+nhK[i+2*j+1]);\ + if (T_128BitTag)\ + AccumulateNH(nhB, d0+nhK[i+2*j+2], d1+nhK[i+2*j+3]);\ + } + + size_t L1KeyLengthInWord64 = m_L1KeyLength / 8; + size_t innerLoopEnd = L1KeyLengthInWord64; + const word64 *nhK = m_nhKey(); + word64 *polyS = (word64*)(void*)m_polyState(); + bool isFirstBlock = true; + size_t i; + + #if !VMAC_BOOL_32BIT + #if VMAC_BOOL_WORD128 + word128 a1=0, a2=0; + #else + word64 ah1=0, al1=0, ah2=0, al2=0; + #endif + word64 kh1, kl1, kh2, kl2; + kh1=(polyS+0*4+2)[0]; kl1=(polyS+0*4+2)[1]; + if (T_128BitTag) + { + kh2=(polyS+1*4+2)[0]; kl2=(polyS+1*4+2)[1]; + } + #endif + + do + { + DeclareNH(nhA); + DeclareNH(nhB); + + i = 0; + if (blocksRemainingInWord64 < L1KeyLengthInWord64) + { + if (blocksRemainingInWord64 % 8) + { + innerLoopEnd = blocksRemainingInWord64 % 8; + for (; i> 32); + nh1[0] = word32(nhA1); + nh2[0] = (nhA2 + (nhA1 >> 32)) & m62; + + if (T_128BitTag) + { + nh0[1] = word32(nhB0); + nhB1 += (nhB0 >> 32); + nh1[1] = word32(nhB1); + nh2[1] = (nhB2 + (nhB1 >> 32)) & m62; + } + + #define a0 (((word32 *)(polyS+i*4))[2+NativeByteOrder::ToEnum()]) + #define a1 (*(((word32 *)(polyS+i*4))+3-NativeByteOrder::ToEnum())) // workaround for GCC 3.2 + #define a2 (((word32 *)(polyS+i*4))[0+NativeByteOrder::ToEnum()]) + #define a3 (*(((word32 *)(polyS+i*4))+1-NativeByteOrder::ToEnum())) + #define aHi ((polyS+i*4)[0]) + #define k0 (((word32 *)(polyS+i*4+2))[2+NativeByteOrder::ToEnum()]) + #define k1 (*(((word32 *)(polyS+i*4+2))+3-NativeByteOrder::ToEnum())) + #define k2 (((word32 *)(polyS+i*4+2))[0+NativeByteOrder::ToEnum()]) + #define k3 (*(((word32 *)(polyS+i*4+2))+1-NativeByteOrder::ToEnum())) + #define kHi ((polyS+i*4+2)[0]) + + if (isFirstBlock) + { + isFirstBlock = false; + if (m_isFirstBlock) + { + m_isFirstBlock = false; + for (i=0; i<=(size_t)T_128BitTag; i++) + { + word64 t = (word64)nh0[i] + k0; + a0 = (word32)t; + t = (t >> 32) + nh1[i] + k1; + a1 = (word32)t; + aHi = (t >> 32) + nh2[i] + kHi; + } + continue; + } + } + for (i=0; i<=(size_t)T_128BitTag; i++) + { + word64 p, t; + word32 t2; + + p = MUL32(a3, 2*k3); + p += nh2[i]; + p += MUL32(a0, k2); + p += MUL32(a1, k1); + p += MUL32(a2, k0); + t2 = (word32)p; + p >>= 32; + p += MUL32(a0, k3); + p += MUL32(a1, k2); + p += MUL32(a2, k1); + p += MUL32(a3, k0); + t = (word64(word32(p) & 0x7fffffff) << 32) | t2; + p >>= 31; + p += nh0[i]; + p += MUL32(a0, k0); + p += MUL32(a1, 2*k3); + p += MUL32(a2, 2*k2); + p += MUL32(a3, 2*k1); + t2 = (word32)p; + p >>= 32; + p += nh1[i]; + p += MUL32(a0, k1); + p += MUL32(a1, k0); + p += MUL32(a2, 2*k3); + p += MUL32(a3, 2*k2); + a0 = t2; + a1 = (word32)p; + aHi = (p >> 32) + t; + } + + #undef a0 + #undef a1 + #undef a2 + #undef a3 + #undef aHi + #undef k0 + #undef k1 + #undef k2 + #undef k3 + #undef kHi + #else // #if VMAC_BOOL_32BIT + if (isFirstBlock) + { + isFirstBlock = false; + if (m_isFirstBlock) + { + m_isFirstBlock = false; + #if VMAC_BOOL_WORD128 + #define first_poly_step(a, kh, kl, m) a = (m & m126) + ((word128(kh) << 64) | kl) + + first_poly_step(a1, kh1, kl1, nhA); + if (T_128BitTag) + first_poly_step(a2, kh2, kl2, nhB); + #else + #define first_poly_step(ah, al, kh, kl, mh, ml) {\ + mh &= m62;\ + ADD128(mh, ml, kh, kl); \ + ah = mh; al = ml;} + + first_poly_step(ah1, al1, kh1, kl1, nhA1, nhA0); + if (T_128BitTag) + first_poly_step(ah2, al2, kh2, kl2, nhB1, nhB0); + #endif + continue; + } + else + { + #if VMAC_BOOL_WORD128 + a1 = (word128((polyS+0*4)[0]) << 64) | (polyS+0*4)[1]; + #else + ah1=(polyS+0*4)[0]; al1=(polyS+0*4)[1]; + #endif + if (T_128BitTag) + { + #if VMAC_BOOL_WORD128 + a2 = (word128((polyS+1*4)[0]) << 64) | (polyS+1*4)[1]; + #else + ah2=(polyS+1*4)[0]; al2=(polyS+1*4)[1]; + #endif + } + } + } + + #if VMAC_BOOL_WORD128 + #define poly_step(a, kh, kl, m) \ + { word128 t1, t2, t3, t4;\ + Multiply128(t2, a>>64, kl);\ + Multiply128(t3, a, kh);\ + Multiply128(t1, a, kl);\ + Multiply128(t4, a>>64, 2*kh);\ + t2 += t3;\ + t4 += t1;\ + t2 += t4>>64;\ + a = (word128(word64(t2)&m63) << 64) | word64(t4);\ + t2 *= 2;\ + a += m & m126;\ + a += t2>>64;} + + poly_step(a1, kh1, kl1, nhA); + if (T_128BitTag) + poly_step(a2, kh2, kl2, nhB); + #else + #define poly_step(ah, al, kh, kl, mh, ml) \ + { word64 t1h, t1l, t2h, t2l, t3h, t3l, z=0; \ + /* compute ab*cd, put bd into result registers */ \ + MUL64(t2h,t2l,ah,kl); \ + MUL64(t3h,t3l,al,kh); \ + MUL64(t1h,t1l,ah,2*kh); \ + MUL64(ah,al,al,kl); \ + /* add together ad + bc */ \ + ADD128(t2h,t2l,t3h,t3l); \ + /* add 2 * ac to result */ \ + ADD128(ah,al,t1h,t1l); \ + /* now (ah,al), (t2l,2*t2h) need summing */ \ + /* first add the high registers, carrying into t2h */ \ + ADD128(t2h,ah,z,t2l); \ + /* double t2h and add top bit of ah */ \ + t2h += t2h + (ah >> 63); \ + ah &= m63; \ + /* now add the low registers */ \ + mh &= m62; \ + ADD128(ah,al,mh,ml); \ + ADD128(ah,al,z,t2h); \ + } + + poly_step(ah1, al1, kh1, kl1, nhA1, nhA0); + if (T_128BitTag) + poly_step(ah2, al2, kh2, kl2, nhB1, nhB0); + #endif + #endif // #if VMAC_BOOL_32BIT + } while (blocksRemainingInWord64); + + #if VMAC_BOOL_WORD128 + (polyS+0*4)[0]=word64(a1>>64); (polyS+0*4)[1]=word64(a1); + if (T_128BitTag) + { + (polyS+1*4)[0]=word64(a2>>64); (polyS+1*4)[1]=word64(a2); + } + #elif !VMAC_BOOL_32BIT + (polyS+0*4)[0]=ah1; (polyS+0*4)[1]=al1; + if (T_128BitTag) + { + (polyS+1*4)[0]=ah2; (polyS+1*4)[1]=al2; + } + #endif +} + +inline void VMAC_Base::VHASH_Update(const word64 *data, size_t blocksRemainingInWord64) +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 + if (HasSSE2()) + { + VHASH_Update_SSE2(data, blocksRemainingInWord64, 0); + if (m_is128) + VHASH_Update_SSE2(data, blocksRemainingInWord64, 1); + m_isFirstBlock = false; + } + else +#endif + { + if (m_is128) + VHASH_Update_Template(data, blocksRemainingInWord64); + else + VHASH_Update_Template(data, blocksRemainingInWord64); + } +} + +size_t VMAC_Base::HashMultipleBlocks(const word64 *data, size_t length) +{ + size_t remaining = ModPowerOf2(length, m_L1KeyLength); + VHASH_Update(data, (length-remaining)/8); + return remaining; +} + +word64 L3Hash(const word64 *input, const word64 *l3Key, size_t len) +{ + word64 rh, rl, t, z=0; + word64 p1 = input[0], p2 = input[1]; + word64 k1 = l3Key[0], k2 = l3Key[1]; + + /* fully reduce (p1,p2)+(len,0) mod p127 */ + t = p1 >> 63; + p1 &= m63; + ADD128(p1, p2, len, t); + /* At this point, (p1,p2) is at most 2^127+(len<<64) */ + t = (p1 > m63) + ((p1 == m63) & (p2 == m64)); + ADD128(p1, p2, z, t); + p1 &= m63; + + /* compute (p1,p2)/(2^64-2^32) and (p1,p2)%(2^64-2^32) */ + t = p1 + (p2 >> 32); + t += (t >> 32); + t += (word32)t > 0xfffffffeU; + p1 += (t >> 32); + p2 += (p1 << 32); + + /* compute (p1+k1)%p64 and (p2+k2)%p64 */ + p1 += k1; + p1 += (0 - (p1 < k1)) & 257; + p2 += k2; + p2 += (0 - (p2 < k2)) & 257; + + /* compute (p1+k1)*(p2+k2)%p64 */ + MUL64(rh, rl, p1, p2); + t = rh >> 56; + ADD128(t, rl, z, rh); + rh <<= 8; + ADD128(t, rl, z, rh); + t += t << 8; + rl += t; + rl += (0 - (rl < t)) & 257; + rl += (0 - (rl > p64-1)) & 257; + return rl; +} + +void VMAC_Base::TruncatedFinal(byte *mac, size_t size) +{ + CRYPTOPP_ASSERT(IsAlignedOn(DataBuf(),GetAlignmentOf())); + CRYPTOPP_ASSERT(IsAlignedOn(m_polyState(),GetAlignmentOf())); + size_t len = ModPowerOf2(GetBitCountLo()/8, m_L1KeyLength); + + if (len) + { + memset(m_data()+len, 0, (0-len)%16); + VHASH_Update(DataBuf(), ((len+15)/16)*2); + len *= 8; // convert to bits + } + else if (m_isFirstBlock) + { + // special case for empty string + m_polyState()[0] = m_polyState()[2]; + m_polyState()[1] = m_polyState()[3]; + if (m_is128) + { + m_polyState()[4] = m_polyState()[6]; + m_polyState()[5] = m_polyState()[7]; + } + } + + if (m_is128) + { + word64 t[2]; + t[0] = L3Hash(m_polyState(), m_l3Key(), len) + GetWord(true, BIG_ENDIAN_ORDER, m_pad()); + t[1] = L3Hash(m_polyState()+4, m_l3Key()+2, len) + GetWord(true, BIG_ENDIAN_ORDER, m_pad()+8); + if (size == 16) + { + PutWord(false, BIG_ENDIAN_ORDER, mac, t[0]); + PutWord(false, BIG_ENDIAN_ORDER, mac+8, t[1]); + } + else + { + t[0] = ConditionalByteReverse(BIG_ENDIAN_ORDER, t[0]); + t[1] = ConditionalByteReverse(BIG_ENDIAN_ORDER, t[1]); + memcpy(mac, t, size); + } + } + else + { + word64 t = L3Hash(m_polyState(), m_l3Key(), len); + t += GetWord(true, BIG_ENDIAN_ORDER, m_pad() + (m_nonce()[IVSize()-1]&1) * 8); + if (size == 8) + PutWord(false, BIG_ENDIAN_ORDER, mac, t); + else + { + t = ConditionalByteReverse(BIG_ENDIAN_ORDER, t); + memcpy(mac, &t, size); + } + } +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/vmac.h b/external/ours/library/crypto/src/shared/original/vmac.h new file mode 100755 index 000000000..44fe09fcc --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/wake.cpp b/external/ours/library/crypto/src/shared/original/wake.cpp new file mode 100755 index 000000000..f4e43dc17 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/wake.cpp @@ -0,0 +1,111 @@ +// wake.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#include "wake.h" +#include "smartptr.h" + +ANONYMOUS_NAMESPACE_BEGIN + +const unsigned int TT[8]= { + 0x726a8f3b, 0xe69a3b5c, 0xd3c71fe5, 0xab3c73d2, + 0x4d3a8eb3, 0x0396d6e8, 0x3d4c2f7a, 0x9ee27cf3 +} ; + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void WAKE_TestInstantiations() +{ + WAKE_OFB<>::Encryption x2; + WAKE_OFB<>::Decryption x4; +} +#endif + +inline word32 WAKE_Base::M(word32 x, word32 y) +{ + word32 w = x+y; + return (w>>8) ^ t[w & 0xff]; +} + +void WAKE_Base::GenKey(word32 k0, word32 k1, word32 k2, word32 k3) +{ + // this code is mostly copied from David Wheeler's paper "A Bulk Data Encryption Algorithm" + signed int x, z, p; + + t[0] = k0; + t[1] = k1; + t[2] = k2; + t[3] = k3; + for (p=4 ; p<256 ; p++) + { + x=t[p-4]+t[p-1] ; // fill t + t[p]= (x>>3) ^ TT[x&7] ; + } + + for (p=0 ; p<23 ; p++) + t[p]+=t[p+89] ; // mix first entries + x=t[33] ; z=t[59] | 0x01000001 ; + z=z&0xff7fffff ; + for (p=0 ; p<256 ; p++) { //change top byte to + x=(x&0xff7fffff)+z ; // a permutation etc + t[p]=(t[p] & 0x00ffffff) ^ x ; } + + t[256]=t[0] ; + byte y=byte(x); + for (p=0 ; p<256 ; p++) { // further change perm. + t[p]=t[y=byte(t[p^y]^y)] ; // and other digits + t[y]=t[p+1] ; } +} + +template +void WAKE_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length); + word32 k0, k1, k2, k3; + BlockGetAndPut::Get(key)(r3)(r4)(r5)(r6)(k0)(k1)(k2)(k3); + GenKey(k0, k1, k2, k3); +} + +// OFB +template +void WAKE_Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ +#define WAKE_OUTPUT(x)\ + while (iterationCount--)\ + {\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 0, r6);\ + r3 = M(r3, r6);\ + r4 = M(r4, r3);\ + r5 = M(r5, r4);\ + r6 = M(r6, r5);\ + output += 4;\ + if (!(x & INPUT_NULL))\ + input += 4;\ + } + + typedef word32 WordType; + CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(WAKE_OUTPUT, 0); +} +/* +template +void WAKE_ROFB_Policy::Iterate(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount) +{ + KeystreamOutput keystreamOperation(operation, output, input); + + while (iterationCount--) + { + keystreamOperation(r6); + r3 = M(r3, r6); + r4 = M(r4, r3); + r5 = M(r5, r4); + r6 = M(r6, r5); + } +} +*/ +template class WAKE_Policy; +template class WAKE_Policy; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/wake.h b/external/ours/library/crypto/src/shared/original/wake.h new file mode 100755 index 000000000..adecd30f8 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/whrlpool.cpp b/external/ours/library/crypto/src/shared/original/whrlpool.cpp new file mode 100755 index 000000000..4a52a0dde --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/whrlpool.cpp @@ -0,0 +1,730 @@ +// whrlpool.cpp - 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. +// +// This is the original introductory comment: + +/** + * The Whirlpool hashing function. + * + *

+ * References + * + *

+ * The Whirlpool algorithm was developed by + * Paulo S. L. M. Barreto and + * Vincent Rijmen. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * + * + * @author Paulo S.L.M. Barreto + * @author Vincent Rijmen. + * + * @version 3.0 (2003.03.12) + * + * ============================================================================= + * + * Differences from version 2.1: + * + * - Suboptimal diffusion matrix replaced by cir(1, 1, 4, 1, 8, 5, 2, 9). + * + * ============================================================================= + * + * Differences from version 2.0: + * + * - Generation of ISO/IEC 10118-3 test vectors. + * - Bug fix: nonzero carry was ignored when tallying the data length + * (this bug apparently only manifested itself when feeding data + * in pieces rather than in a single chunk at once). + * - Support for MS Visual C++ 64-bit integer arithmetic. + * + * Differences from version 1.0: + * + * - Original S-box replaced by the tweaked, hardware-efficient version. + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "pch.h" +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(disable: 4127) +#endif + +#include "whrlpool.h" +#include "misc.h" +#include "cpu.h" + +#if defined(CRYPTOPP_DISABLE_WHIRLPOOL_ASM) +# undef CRYPTOPP_X86_ASM_AVAILABLE +# undef CRYPTOPP_X32_ASM_AVAILABLE +# undef CRYPTOPP_X64_ASM_AVAILABLE +# undef CRYPTOPP_SSE2_ASM_AVAILABLE +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) +void Whirlpool_TestInstantiations() +{ + Whirlpool x; +} +#endif + +std::string Whirlpool::AlgorithmProvider() const +{ +#if CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return "SSE2"; +#endif + return "C++"; +} + +void Whirlpool::InitState(HashWordType *state) +{ + memset(state, 0, 8*sizeof(state[0])); +} + +void Whirlpool::TruncatedFinal(byte *hash, size_t size) +{ + CRYPTOPP_ASSERT(hash != NULLPTR); + ThrowIfInvalidTruncatedSize(size); + + PadLastBlock(32); + CorrectEndianess(m_data, m_data, 32); + + m_data[m_data.size()-4] = 0; + m_data[m_data.size()-3] = 0; + m_data[m_data.size()-2] = GetBitCountHi(); + m_data[m_data.size()-1] = GetBitCountLo(); + + Transform(m_state, m_data); + CorrectEndianess(m_state, m_state, DigestSize()); + memcpy(hash, m_state, size); + + Restart(); // reinit for next use +} + +/* + * The number of rounds of the internal dedicated block cipher. + */ +#define R 10 + +/* + * Though Whirlpool is endianness-neutral, the encryption tables are listed + * in BIG-ENDIAN format, which is adopted throughout this implementation + * (but little-endian notation would be equally suitable if consistently + * employed). + */ + +#if CRYPTOPP_SSE2_ASM_AVAILABLE +CRYPTOPP_ALIGN_DATA(16) +CRYPTOPP_TABLE +const word64 Whirlpool_C[4*256+R] = { +#else +const word64 Whirlpool_C[4*256+R] = { +#endif + W64LIT(0x18186018c07830d8), W64LIT(0x23238c2305af4626), W64LIT(0xc6c63fc67ef991b8), W64LIT(0xe8e887e8136fcdfb), + W64LIT(0x878726874ca113cb), W64LIT(0xb8b8dab8a9626d11), W64LIT(0x0101040108050209), W64LIT(0x4f4f214f426e9e0d), + W64LIT(0x3636d836adee6c9b), W64LIT(0xa6a6a2a6590451ff), W64LIT(0xd2d26fd2debdb90c), W64LIT(0xf5f5f3f5fb06f70e), + W64LIT(0x7979f979ef80f296), W64LIT(0x6f6fa16f5fcede30), W64LIT(0x91917e91fcef3f6d), W64LIT(0x52525552aa07a4f8), + W64LIT(0x60609d6027fdc047), W64LIT(0xbcbccabc89766535), W64LIT(0x9b9b569baccd2b37), W64LIT(0x8e8e028e048c018a), + W64LIT(0xa3a3b6a371155bd2), W64LIT(0x0c0c300c603c186c), W64LIT(0x7b7bf17bff8af684), W64LIT(0x3535d435b5e16a80), + W64LIT(0x1d1d741de8693af5), W64LIT(0xe0e0a7e05347ddb3), W64LIT(0xd7d77bd7f6acb321), W64LIT(0xc2c22fc25eed999c), + W64LIT(0x2e2eb82e6d965c43), W64LIT(0x4b4b314b627a9629), W64LIT(0xfefedffea321e15d), W64LIT(0x575741578216aed5), + W64LIT(0x15155415a8412abd), W64LIT(0x7777c1779fb6eee8), W64LIT(0x3737dc37a5eb6e92), W64LIT(0xe5e5b3e57b56d79e), + W64LIT(0x9f9f469f8cd92313), W64LIT(0xf0f0e7f0d317fd23), W64LIT(0x4a4a354a6a7f9420), W64LIT(0xdada4fda9e95a944), + W64LIT(0x58587d58fa25b0a2), W64LIT(0xc9c903c906ca8fcf), W64LIT(0x2929a429558d527c), W64LIT(0x0a0a280a5022145a), + W64LIT(0xb1b1feb1e14f7f50), W64LIT(0xa0a0baa0691a5dc9), W64LIT(0x6b6bb16b7fdad614), W64LIT(0x85852e855cab17d9), + W64LIT(0xbdbdcebd8173673c), W64LIT(0x5d5d695dd234ba8f), W64LIT(0x1010401080502090), W64LIT(0xf4f4f7f4f303f507), + W64LIT(0xcbcb0bcb16c08bdd), W64LIT(0x3e3ef83eedc67cd3), W64LIT(0x0505140528110a2d), W64LIT(0x676781671fe6ce78), + W64LIT(0xe4e4b7e47353d597), W64LIT(0x27279c2725bb4e02), W64LIT(0x4141194132588273), W64LIT(0x8b8b168b2c9d0ba7), + W64LIT(0xa7a7a6a7510153f6), W64LIT(0x7d7de97dcf94fab2), W64LIT(0x95956e95dcfb3749), W64LIT(0xd8d847d88e9fad56), + W64LIT(0xfbfbcbfb8b30eb70), W64LIT(0xeeee9fee2371c1cd), W64LIT(0x7c7ced7cc791f8bb), W64LIT(0x6666856617e3cc71), + W64LIT(0xdddd53dda68ea77b), W64LIT(0x17175c17b84b2eaf), W64LIT(0x4747014702468e45), W64LIT(0x9e9e429e84dc211a), + W64LIT(0xcaca0fca1ec589d4), W64LIT(0x2d2db42d75995a58), W64LIT(0xbfbfc6bf9179632e), W64LIT(0x07071c07381b0e3f), + W64LIT(0xadad8ead012347ac), W64LIT(0x5a5a755aea2fb4b0), W64LIT(0x838336836cb51bef), W64LIT(0x3333cc3385ff66b6), + W64LIT(0x636391633ff2c65c), W64LIT(0x02020802100a0412), W64LIT(0xaaaa92aa39384993), W64LIT(0x7171d971afa8e2de), + W64LIT(0xc8c807c80ecf8dc6), W64LIT(0x19196419c87d32d1), W64LIT(0x494939497270923b), W64LIT(0xd9d943d9869aaf5f), + W64LIT(0xf2f2eff2c31df931), W64LIT(0xe3e3abe34b48dba8), W64LIT(0x5b5b715be22ab6b9), W64LIT(0x88881a8834920dbc), + W64LIT(0x9a9a529aa4c8293e), W64LIT(0x262698262dbe4c0b), W64LIT(0x3232c8328dfa64bf), W64LIT(0xb0b0fab0e94a7d59), + W64LIT(0xe9e983e91b6acff2), W64LIT(0x0f0f3c0f78331e77), W64LIT(0xd5d573d5e6a6b733), W64LIT(0x80803a8074ba1df4), + W64LIT(0xbebec2be997c6127), W64LIT(0xcdcd13cd26de87eb), W64LIT(0x3434d034bde46889), W64LIT(0x48483d487a759032), + W64LIT(0xffffdbffab24e354), W64LIT(0x7a7af57af78ff48d), W64LIT(0x90907a90f4ea3d64), W64LIT(0x5f5f615fc23ebe9d), + W64LIT(0x202080201da0403d), W64LIT(0x6868bd6867d5d00f), W64LIT(0x1a1a681ad07234ca), W64LIT(0xaeae82ae192c41b7), + W64LIT(0xb4b4eab4c95e757d), W64LIT(0x54544d549a19a8ce), W64LIT(0x93937693ece53b7f), W64LIT(0x222288220daa442f), + W64LIT(0x64648d6407e9c863), W64LIT(0xf1f1e3f1db12ff2a), W64LIT(0x7373d173bfa2e6cc), W64LIT(0x12124812905a2482), + W64LIT(0x40401d403a5d807a), W64LIT(0x0808200840281048), W64LIT(0xc3c32bc356e89b95), W64LIT(0xecec97ec337bc5df), + W64LIT(0xdbdb4bdb9690ab4d), W64LIT(0xa1a1bea1611f5fc0), W64LIT(0x8d8d0e8d1c830791), W64LIT(0x3d3df43df5c97ac8), + W64LIT(0x97976697ccf1335b), W64LIT(0x0000000000000000), W64LIT(0xcfcf1bcf36d483f9), W64LIT(0x2b2bac2b4587566e), + W64LIT(0x7676c57697b3ece1), W64LIT(0x8282328264b019e6), W64LIT(0xd6d67fd6fea9b128), W64LIT(0x1b1b6c1bd87736c3), + W64LIT(0xb5b5eeb5c15b7774), W64LIT(0xafaf86af112943be), W64LIT(0x6a6ab56a77dfd41d), W64LIT(0x50505d50ba0da0ea), + W64LIT(0x45450945124c8a57), W64LIT(0xf3f3ebf3cb18fb38), W64LIT(0x3030c0309df060ad), W64LIT(0xefef9bef2b74c3c4), + W64LIT(0x3f3ffc3fe5c37eda), W64LIT(0x55554955921caac7), W64LIT(0xa2a2b2a2791059db), W64LIT(0xeaea8fea0365c9e9), + W64LIT(0x656589650fecca6a), W64LIT(0xbabad2bab9686903), W64LIT(0x2f2fbc2f65935e4a), W64LIT(0xc0c027c04ee79d8e), + W64LIT(0xdede5fdebe81a160), W64LIT(0x1c1c701ce06c38fc), W64LIT(0xfdfdd3fdbb2ee746), W64LIT(0x4d4d294d52649a1f), + W64LIT(0x92927292e4e03976), W64LIT(0x7575c9758fbceafa), W64LIT(0x06061806301e0c36), W64LIT(0x8a8a128a249809ae), + W64LIT(0xb2b2f2b2f940794b), W64LIT(0xe6e6bfe66359d185), W64LIT(0x0e0e380e70361c7e), W64LIT(0x1f1f7c1ff8633ee7), + W64LIT(0x6262956237f7c455), W64LIT(0xd4d477d4eea3b53a), W64LIT(0xa8a89aa829324d81), W64LIT(0x96966296c4f43152), + W64LIT(0xf9f9c3f99b3aef62), W64LIT(0xc5c533c566f697a3), W64LIT(0x2525942535b14a10), W64LIT(0x59597959f220b2ab), + W64LIT(0x84842a8454ae15d0), W64LIT(0x7272d572b7a7e4c5), W64LIT(0x3939e439d5dd72ec), W64LIT(0x4c4c2d4c5a619816), + W64LIT(0x5e5e655eca3bbc94), W64LIT(0x7878fd78e785f09f), W64LIT(0x3838e038ddd870e5), W64LIT(0x8c8c0a8c14860598), + W64LIT(0xd1d163d1c6b2bf17), W64LIT(0xa5a5aea5410b57e4), W64LIT(0xe2e2afe2434dd9a1), W64LIT(0x616199612ff8c24e), + W64LIT(0xb3b3f6b3f1457b42), W64LIT(0x2121842115a54234), W64LIT(0x9c9c4a9c94d62508), W64LIT(0x1e1e781ef0663cee), + W64LIT(0x4343114322528661), W64LIT(0xc7c73bc776fc93b1), W64LIT(0xfcfcd7fcb32be54f), W64LIT(0x0404100420140824), + W64LIT(0x51515951b208a2e3), W64LIT(0x99995e99bcc72f25), W64LIT(0x6d6da96d4fc4da22), W64LIT(0x0d0d340d68391a65), + W64LIT(0xfafacffa8335e979), W64LIT(0xdfdf5bdfb684a369), W64LIT(0x7e7ee57ed79bfca9), W64LIT(0x242490243db44819), + W64LIT(0x3b3bec3bc5d776fe), W64LIT(0xabab96ab313d4b9a), W64LIT(0xcece1fce3ed181f0), W64LIT(0x1111441188552299), + W64LIT(0x8f8f068f0c890383), W64LIT(0x4e4e254e4a6b9c04), W64LIT(0xb7b7e6b7d1517366), W64LIT(0xebeb8beb0b60cbe0), + W64LIT(0x3c3cf03cfdcc78c1), W64LIT(0x81813e817cbf1ffd), W64LIT(0x94946a94d4fe3540), W64LIT(0xf7f7fbf7eb0cf31c), + W64LIT(0xb9b9deb9a1676f18), W64LIT(0x13134c13985f268b), W64LIT(0x2c2cb02c7d9c5851), W64LIT(0xd3d36bd3d6b8bb05), + W64LIT(0xe7e7bbe76b5cd38c), W64LIT(0x6e6ea56e57cbdc39), W64LIT(0xc4c437c46ef395aa), W64LIT(0x03030c03180f061b), + W64LIT(0x565645568a13acdc), W64LIT(0x44440d441a49885e), W64LIT(0x7f7fe17fdf9efea0), W64LIT(0xa9a99ea921374f88), + W64LIT(0x2a2aa82a4d825467), W64LIT(0xbbbbd6bbb16d6b0a), W64LIT(0xc1c123c146e29f87), W64LIT(0x53535153a202a6f1), + W64LIT(0xdcdc57dcae8ba572), W64LIT(0x0b0b2c0b58271653), W64LIT(0x9d9d4e9d9cd32701), W64LIT(0x6c6cad6c47c1d82b), + W64LIT(0x3131c43195f562a4), W64LIT(0x7474cd7487b9e8f3), W64LIT(0xf6f6fff6e309f115), W64LIT(0x464605460a438c4c), + W64LIT(0xacac8aac092645a5), W64LIT(0x89891e893c970fb5), W64LIT(0x14145014a04428b4), W64LIT(0xe1e1a3e15b42dfba), + W64LIT(0x16165816b04e2ca6), W64LIT(0x3a3ae83acdd274f7), W64LIT(0x6969b9696fd0d206), W64LIT(0x09092409482d1241), + W64LIT(0x7070dd70a7ade0d7), W64LIT(0xb6b6e2b6d954716f), W64LIT(0xd0d067d0ceb7bd1e), W64LIT(0xeded93ed3b7ec7d6), + W64LIT(0xcccc17cc2edb85e2), W64LIT(0x424215422a578468), W64LIT(0x98985a98b4c22d2c), W64LIT(0xa4a4aaa4490e55ed), + W64LIT(0x2828a0285d885075), W64LIT(0x5c5c6d5cda31b886), W64LIT(0xf8f8c7f8933fed6b), W64LIT(0x8686228644a411c2), + + W64LIT(0xd818186018c07830), W64LIT(0x2623238c2305af46), W64LIT(0xb8c6c63fc67ef991), W64LIT(0xfbe8e887e8136fcd), + W64LIT(0xcb878726874ca113), W64LIT(0x11b8b8dab8a9626d), W64LIT(0x0901010401080502), W64LIT(0x0d4f4f214f426e9e), + W64LIT(0x9b3636d836adee6c), W64LIT(0xffa6a6a2a6590451), W64LIT(0x0cd2d26fd2debdb9), W64LIT(0x0ef5f5f3f5fb06f7), + W64LIT(0x967979f979ef80f2), W64LIT(0x306f6fa16f5fcede), W64LIT(0x6d91917e91fcef3f), W64LIT(0xf852525552aa07a4), + W64LIT(0x4760609d6027fdc0), W64LIT(0x35bcbccabc897665), W64LIT(0x379b9b569baccd2b), W64LIT(0x8a8e8e028e048c01), + W64LIT(0xd2a3a3b6a371155b), W64LIT(0x6c0c0c300c603c18), W64LIT(0x847b7bf17bff8af6), W64LIT(0x803535d435b5e16a), + W64LIT(0xf51d1d741de8693a), W64LIT(0xb3e0e0a7e05347dd), W64LIT(0x21d7d77bd7f6acb3), W64LIT(0x9cc2c22fc25eed99), + W64LIT(0x432e2eb82e6d965c), W64LIT(0x294b4b314b627a96), W64LIT(0x5dfefedffea321e1), W64LIT(0xd5575741578216ae), + W64LIT(0xbd15155415a8412a), W64LIT(0xe87777c1779fb6ee), W64LIT(0x923737dc37a5eb6e), W64LIT(0x9ee5e5b3e57b56d7), + W64LIT(0x139f9f469f8cd923), W64LIT(0x23f0f0e7f0d317fd), W64LIT(0x204a4a354a6a7f94), W64LIT(0x44dada4fda9e95a9), + W64LIT(0xa258587d58fa25b0), W64LIT(0xcfc9c903c906ca8f), W64LIT(0x7c2929a429558d52), W64LIT(0x5a0a0a280a502214), + W64LIT(0x50b1b1feb1e14f7f), W64LIT(0xc9a0a0baa0691a5d), W64LIT(0x146b6bb16b7fdad6), W64LIT(0xd985852e855cab17), + W64LIT(0x3cbdbdcebd817367), W64LIT(0x8f5d5d695dd234ba), W64LIT(0x9010104010805020), W64LIT(0x07f4f4f7f4f303f5), + W64LIT(0xddcbcb0bcb16c08b), W64LIT(0xd33e3ef83eedc67c), W64LIT(0x2d0505140528110a), W64LIT(0x78676781671fe6ce), + W64LIT(0x97e4e4b7e47353d5), W64LIT(0x0227279c2725bb4e), W64LIT(0x7341411941325882), W64LIT(0xa78b8b168b2c9d0b), + W64LIT(0xf6a7a7a6a7510153), W64LIT(0xb27d7de97dcf94fa), W64LIT(0x4995956e95dcfb37), W64LIT(0x56d8d847d88e9fad), + W64LIT(0x70fbfbcbfb8b30eb), W64LIT(0xcdeeee9fee2371c1), W64LIT(0xbb7c7ced7cc791f8), W64LIT(0x716666856617e3cc), + W64LIT(0x7bdddd53dda68ea7), W64LIT(0xaf17175c17b84b2e), W64LIT(0x454747014702468e), W64LIT(0x1a9e9e429e84dc21), + W64LIT(0xd4caca0fca1ec589), W64LIT(0x582d2db42d75995a), W64LIT(0x2ebfbfc6bf917963), W64LIT(0x3f07071c07381b0e), + W64LIT(0xacadad8ead012347), W64LIT(0xb05a5a755aea2fb4), W64LIT(0xef838336836cb51b), W64LIT(0xb63333cc3385ff66), + W64LIT(0x5c636391633ff2c6), W64LIT(0x1202020802100a04), W64LIT(0x93aaaa92aa393849), W64LIT(0xde7171d971afa8e2), + W64LIT(0xc6c8c807c80ecf8d), W64LIT(0xd119196419c87d32), W64LIT(0x3b49493949727092), W64LIT(0x5fd9d943d9869aaf), + W64LIT(0x31f2f2eff2c31df9), W64LIT(0xa8e3e3abe34b48db), W64LIT(0xb95b5b715be22ab6), W64LIT(0xbc88881a8834920d), + W64LIT(0x3e9a9a529aa4c829), W64LIT(0x0b262698262dbe4c), W64LIT(0xbf3232c8328dfa64), W64LIT(0x59b0b0fab0e94a7d), + W64LIT(0xf2e9e983e91b6acf), W64LIT(0x770f0f3c0f78331e), W64LIT(0x33d5d573d5e6a6b7), W64LIT(0xf480803a8074ba1d), + W64LIT(0x27bebec2be997c61), W64LIT(0xebcdcd13cd26de87), W64LIT(0x893434d034bde468), W64LIT(0x3248483d487a7590), + W64LIT(0x54ffffdbffab24e3), W64LIT(0x8d7a7af57af78ff4), W64LIT(0x6490907a90f4ea3d), W64LIT(0x9d5f5f615fc23ebe), + W64LIT(0x3d202080201da040), W64LIT(0x0f6868bd6867d5d0), W64LIT(0xca1a1a681ad07234), W64LIT(0xb7aeae82ae192c41), + W64LIT(0x7db4b4eab4c95e75), W64LIT(0xce54544d549a19a8), W64LIT(0x7f93937693ece53b), W64LIT(0x2f222288220daa44), + W64LIT(0x6364648d6407e9c8), W64LIT(0x2af1f1e3f1db12ff), W64LIT(0xcc7373d173bfa2e6), W64LIT(0x8212124812905a24), + W64LIT(0x7a40401d403a5d80), W64LIT(0x4808082008402810), W64LIT(0x95c3c32bc356e89b), W64LIT(0xdfecec97ec337bc5), + W64LIT(0x4ddbdb4bdb9690ab), W64LIT(0xc0a1a1bea1611f5f), W64LIT(0x918d8d0e8d1c8307), W64LIT(0xc83d3df43df5c97a), + W64LIT(0x5b97976697ccf133), W64LIT(0x0000000000000000), W64LIT(0xf9cfcf1bcf36d483), W64LIT(0x6e2b2bac2b458756), + W64LIT(0xe17676c57697b3ec), W64LIT(0xe68282328264b019), W64LIT(0x28d6d67fd6fea9b1), W64LIT(0xc31b1b6c1bd87736), + W64LIT(0x74b5b5eeb5c15b77), W64LIT(0xbeafaf86af112943), W64LIT(0x1d6a6ab56a77dfd4), W64LIT(0xea50505d50ba0da0), + W64LIT(0x5745450945124c8a), W64LIT(0x38f3f3ebf3cb18fb), W64LIT(0xad3030c0309df060), W64LIT(0xc4efef9bef2b74c3), + W64LIT(0xda3f3ffc3fe5c37e), W64LIT(0xc755554955921caa), W64LIT(0xdba2a2b2a2791059), W64LIT(0xe9eaea8fea0365c9), + W64LIT(0x6a656589650fecca), W64LIT(0x03babad2bab96869), W64LIT(0x4a2f2fbc2f65935e), W64LIT(0x8ec0c027c04ee79d), + W64LIT(0x60dede5fdebe81a1), W64LIT(0xfc1c1c701ce06c38), W64LIT(0x46fdfdd3fdbb2ee7), W64LIT(0x1f4d4d294d52649a), + W64LIT(0x7692927292e4e039), W64LIT(0xfa7575c9758fbcea), W64LIT(0x3606061806301e0c), W64LIT(0xae8a8a128a249809), + W64LIT(0x4bb2b2f2b2f94079), W64LIT(0x85e6e6bfe66359d1), W64LIT(0x7e0e0e380e70361c), W64LIT(0xe71f1f7c1ff8633e), + W64LIT(0x556262956237f7c4), W64LIT(0x3ad4d477d4eea3b5), W64LIT(0x81a8a89aa829324d), W64LIT(0x5296966296c4f431), + W64LIT(0x62f9f9c3f99b3aef), W64LIT(0xa3c5c533c566f697), W64LIT(0x102525942535b14a), W64LIT(0xab59597959f220b2), + W64LIT(0xd084842a8454ae15), W64LIT(0xc57272d572b7a7e4), W64LIT(0xec3939e439d5dd72), W64LIT(0x164c4c2d4c5a6198), + W64LIT(0x945e5e655eca3bbc), W64LIT(0x9f7878fd78e785f0), W64LIT(0xe53838e038ddd870), W64LIT(0x988c8c0a8c148605), + W64LIT(0x17d1d163d1c6b2bf), W64LIT(0xe4a5a5aea5410b57), W64LIT(0xa1e2e2afe2434dd9), W64LIT(0x4e616199612ff8c2), + W64LIT(0x42b3b3f6b3f1457b), W64LIT(0x342121842115a542), W64LIT(0x089c9c4a9c94d625), W64LIT(0xee1e1e781ef0663c), + W64LIT(0x6143431143225286), W64LIT(0xb1c7c73bc776fc93), W64LIT(0x4ffcfcd7fcb32be5), W64LIT(0x2404041004201408), + W64LIT(0xe351515951b208a2), W64LIT(0x2599995e99bcc72f), W64LIT(0x226d6da96d4fc4da), W64LIT(0x650d0d340d68391a), + W64LIT(0x79fafacffa8335e9), W64LIT(0x69dfdf5bdfb684a3), W64LIT(0xa97e7ee57ed79bfc), W64LIT(0x19242490243db448), + W64LIT(0xfe3b3bec3bc5d776), W64LIT(0x9aabab96ab313d4b), W64LIT(0xf0cece1fce3ed181), W64LIT(0x9911114411885522), + W64LIT(0x838f8f068f0c8903), W64LIT(0x044e4e254e4a6b9c), W64LIT(0x66b7b7e6b7d15173), W64LIT(0xe0ebeb8beb0b60cb), + W64LIT(0xc13c3cf03cfdcc78), W64LIT(0xfd81813e817cbf1f), W64LIT(0x4094946a94d4fe35), W64LIT(0x1cf7f7fbf7eb0cf3), + W64LIT(0x18b9b9deb9a1676f), W64LIT(0x8b13134c13985f26), W64LIT(0x512c2cb02c7d9c58), W64LIT(0x05d3d36bd3d6b8bb), + W64LIT(0x8ce7e7bbe76b5cd3), W64LIT(0x396e6ea56e57cbdc), W64LIT(0xaac4c437c46ef395), W64LIT(0x1b03030c03180f06), + W64LIT(0xdc565645568a13ac), W64LIT(0x5e44440d441a4988), W64LIT(0xa07f7fe17fdf9efe), W64LIT(0x88a9a99ea921374f), + W64LIT(0x672a2aa82a4d8254), W64LIT(0x0abbbbd6bbb16d6b), W64LIT(0x87c1c123c146e29f), W64LIT(0xf153535153a202a6), + W64LIT(0x72dcdc57dcae8ba5), W64LIT(0x530b0b2c0b582716), W64LIT(0x019d9d4e9d9cd327), W64LIT(0x2b6c6cad6c47c1d8), + W64LIT(0xa43131c43195f562), W64LIT(0xf37474cd7487b9e8), W64LIT(0x15f6f6fff6e309f1), W64LIT(0x4c464605460a438c), + W64LIT(0xa5acac8aac092645), W64LIT(0xb589891e893c970f), W64LIT(0xb414145014a04428), W64LIT(0xbae1e1a3e15b42df), + W64LIT(0xa616165816b04e2c), W64LIT(0xf73a3ae83acdd274), W64LIT(0x066969b9696fd0d2), W64LIT(0x4109092409482d12), + W64LIT(0xd77070dd70a7ade0), W64LIT(0x6fb6b6e2b6d95471), W64LIT(0x1ed0d067d0ceb7bd), W64LIT(0xd6eded93ed3b7ec7), + W64LIT(0xe2cccc17cc2edb85), W64LIT(0x68424215422a5784), W64LIT(0x2c98985a98b4c22d), W64LIT(0xeda4a4aaa4490e55), + W64LIT(0x752828a0285d8850), W64LIT(0x865c5c6d5cda31b8), W64LIT(0x6bf8f8c7f8933fed), W64LIT(0xc28686228644a411), + + W64LIT(0x30d818186018c078), W64LIT(0x462623238c2305af), W64LIT(0x91b8c6c63fc67ef9), W64LIT(0xcdfbe8e887e8136f), + W64LIT(0x13cb878726874ca1), W64LIT(0x6d11b8b8dab8a962), W64LIT(0x0209010104010805), W64LIT(0x9e0d4f4f214f426e), + W64LIT(0x6c9b3636d836adee), W64LIT(0x51ffa6a6a2a65904), W64LIT(0xb90cd2d26fd2debd), W64LIT(0xf70ef5f5f3f5fb06), + W64LIT(0xf2967979f979ef80), W64LIT(0xde306f6fa16f5fce), W64LIT(0x3f6d91917e91fcef), W64LIT(0xa4f852525552aa07), + W64LIT(0xc04760609d6027fd), W64LIT(0x6535bcbccabc8976), W64LIT(0x2b379b9b569baccd), W64LIT(0x018a8e8e028e048c), + W64LIT(0x5bd2a3a3b6a37115), W64LIT(0x186c0c0c300c603c), W64LIT(0xf6847b7bf17bff8a), W64LIT(0x6a803535d435b5e1), + W64LIT(0x3af51d1d741de869), W64LIT(0xddb3e0e0a7e05347), W64LIT(0xb321d7d77bd7f6ac), W64LIT(0x999cc2c22fc25eed), + W64LIT(0x5c432e2eb82e6d96), W64LIT(0x96294b4b314b627a), W64LIT(0xe15dfefedffea321), W64LIT(0xaed5575741578216), + W64LIT(0x2abd15155415a841), W64LIT(0xeee87777c1779fb6), W64LIT(0x6e923737dc37a5eb), W64LIT(0xd79ee5e5b3e57b56), + W64LIT(0x23139f9f469f8cd9), W64LIT(0xfd23f0f0e7f0d317), W64LIT(0x94204a4a354a6a7f), W64LIT(0xa944dada4fda9e95), + W64LIT(0xb0a258587d58fa25), W64LIT(0x8fcfc9c903c906ca), W64LIT(0x527c2929a429558d), W64LIT(0x145a0a0a280a5022), + W64LIT(0x7f50b1b1feb1e14f), W64LIT(0x5dc9a0a0baa0691a), W64LIT(0xd6146b6bb16b7fda), W64LIT(0x17d985852e855cab), + W64LIT(0x673cbdbdcebd8173), W64LIT(0xba8f5d5d695dd234), W64LIT(0x2090101040108050), W64LIT(0xf507f4f4f7f4f303), + W64LIT(0x8bddcbcb0bcb16c0), W64LIT(0x7cd33e3ef83eedc6), W64LIT(0x0a2d050514052811), W64LIT(0xce78676781671fe6), + W64LIT(0xd597e4e4b7e47353), W64LIT(0x4e0227279c2725bb), W64LIT(0x8273414119413258), W64LIT(0x0ba78b8b168b2c9d), + W64LIT(0x53f6a7a7a6a75101), W64LIT(0xfab27d7de97dcf94), W64LIT(0x374995956e95dcfb), W64LIT(0xad56d8d847d88e9f), + W64LIT(0xeb70fbfbcbfb8b30), W64LIT(0xc1cdeeee9fee2371), W64LIT(0xf8bb7c7ced7cc791), W64LIT(0xcc716666856617e3), + W64LIT(0xa77bdddd53dda68e), W64LIT(0x2eaf17175c17b84b), W64LIT(0x8e45474701470246), W64LIT(0x211a9e9e429e84dc), + W64LIT(0x89d4caca0fca1ec5), W64LIT(0x5a582d2db42d7599), W64LIT(0x632ebfbfc6bf9179), W64LIT(0x0e3f07071c07381b), + W64LIT(0x47acadad8ead0123), W64LIT(0xb4b05a5a755aea2f), W64LIT(0x1bef838336836cb5), W64LIT(0x66b63333cc3385ff), + W64LIT(0xc65c636391633ff2), W64LIT(0x041202020802100a), W64LIT(0x4993aaaa92aa3938), W64LIT(0xe2de7171d971afa8), + W64LIT(0x8dc6c8c807c80ecf), W64LIT(0x32d119196419c87d), W64LIT(0x923b494939497270), W64LIT(0xaf5fd9d943d9869a), + W64LIT(0xf931f2f2eff2c31d), W64LIT(0xdba8e3e3abe34b48), W64LIT(0xb6b95b5b715be22a), W64LIT(0x0dbc88881a883492), + W64LIT(0x293e9a9a529aa4c8), W64LIT(0x4c0b262698262dbe), W64LIT(0x64bf3232c8328dfa), W64LIT(0x7d59b0b0fab0e94a), + W64LIT(0xcff2e9e983e91b6a), W64LIT(0x1e770f0f3c0f7833), W64LIT(0xb733d5d573d5e6a6), W64LIT(0x1df480803a8074ba), + W64LIT(0x6127bebec2be997c), W64LIT(0x87ebcdcd13cd26de), W64LIT(0x68893434d034bde4), W64LIT(0x903248483d487a75), + W64LIT(0xe354ffffdbffab24), W64LIT(0xf48d7a7af57af78f), W64LIT(0x3d6490907a90f4ea), W64LIT(0xbe9d5f5f615fc23e), + W64LIT(0x403d202080201da0), W64LIT(0xd00f6868bd6867d5), W64LIT(0x34ca1a1a681ad072), W64LIT(0x41b7aeae82ae192c), + W64LIT(0x757db4b4eab4c95e), W64LIT(0xa8ce54544d549a19), W64LIT(0x3b7f93937693ece5), W64LIT(0x442f222288220daa), + W64LIT(0xc86364648d6407e9), W64LIT(0xff2af1f1e3f1db12), W64LIT(0xe6cc7373d173bfa2), W64LIT(0x248212124812905a), + W64LIT(0x807a40401d403a5d), W64LIT(0x1048080820084028), W64LIT(0x9b95c3c32bc356e8), W64LIT(0xc5dfecec97ec337b), + W64LIT(0xab4ddbdb4bdb9690), W64LIT(0x5fc0a1a1bea1611f), W64LIT(0x07918d8d0e8d1c83), W64LIT(0x7ac83d3df43df5c9), + W64LIT(0x335b97976697ccf1), W64LIT(0x0000000000000000), W64LIT(0x83f9cfcf1bcf36d4), W64LIT(0x566e2b2bac2b4587), + W64LIT(0xece17676c57697b3), W64LIT(0x19e68282328264b0), W64LIT(0xb128d6d67fd6fea9), W64LIT(0x36c31b1b6c1bd877), + W64LIT(0x7774b5b5eeb5c15b), W64LIT(0x43beafaf86af1129), W64LIT(0xd41d6a6ab56a77df), W64LIT(0xa0ea50505d50ba0d), + W64LIT(0x8a5745450945124c), W64LIT(0xfb38f3f3ebf3cb18), W64LIT(0x60ad3030c0309df0), W64LIT(0xc3c4efef9bef2b74), + W64LIT(0x7eda3f3ffc3fe5c3), W64LIT(0xaac755554955921c), W64LIT(0x59dba2a2b2a27910), W64LIT(0xc9e9eaea8fea0365), + W64LIT(0xca6a656589650fec), W64LIT(0x6903babad2bab968), W64LIT(0x5e4a2f2fbc2f6593), W64LIT(0x9d8ec0c027c04ee7), + W64LIT(0xa160dede5fdebe81), W64LIT(0x38fc1c1c701ce06c), W64LIT(0xe746fdfdd3fdbb2e), W64LIT(0x9a1f4d4d294d5264), + W64LIT(0x397692927292e4e0), W64LIT(0xeafa7575c9758fbc), W64LIT(0x0c3606061806301e), W64LIT(0x09ae8a8a128a2498), + W64LIT(0x794bb2b2f2b2f940), W64LIT(0xd185e6e6bfe66359), W64LIT(0x1c7e0e0e380e7036), W64LIT(0x3ee71f1f7c1ff863), + W64LIT(0xc4556262956237f7), W64LIT(0xb53ad4d477d4eea3), W64LIT(0x4d81a8a89aa82932), W64LIT(0x315296966296c4f4), + W64LIT(0xef62f9f9c3f99b3a), W64LIT(0x97a3c5c533c566f6), W64LIT(0x4a102525942535b1), W64LIT(0xb2ab59597959f220), + W64LIT(0x15d084842a8454ae), W64LIT(0xe4c57272d572b7a7), W64LIT(0x72ec3939e439d5dd), W64LIT(0x98164c4c2d4c5a61), + W64LIT(0xbc945e5e655eca3b), W64LIT(0xf09f7878fd78e785), W64LIT(0x70e53838e038ddd8), W64LIT(0x05988c8c0a8c1486), + W64LIT(0xbf17d1d163d1c6b2), W64LIT(0x57e4a5a5aea5410b), W64LIT(0xd9a1e2e2afe2434d), W64LIT(0xc24e616199612ff8), + W64LIT(0x7b42b3b3f6b3f145), W64LIT(0x42342121842115a5), W64LIT(0x25089c9c4a9c94d6), W64LIT(0x3cee1e1e781ef066), + W64LIT(0x8661434311432252), W64LIT(0x93b1c7c73bc776fc), W64LIT(0xe54ffcfcd7fcb32b), W64LIT(0x0824040410042014), + W64LIT(0xa2e351515951b208), W64LIT(0x2f2599995e99bcc7), W64LIT(0xda226d6da96d4fc4), W64LIT(0x1a650d0d340d6839), + W64LIT(0xe979fafacffa8335), W64LIT(0xa369dfdf5bdfb684), W64LIT(0xfca97e7ee57ed79b), W64LIT(0x4819242490243db4), + W64LIT(0x76fe3b3bec3bc5d7), W64LIT(0x4b9aabab96ab313d), W64LIT(0x81f0cece1fce3ed1), W64LIT(0x2299111144118855), + W64LIT(0x03838f8f068f0c89), W64LIT(0x9c044e4e254e4a6b), W64LIT(0x7366b7b7e6b7d151), W64LIT(0xcbe0ebeb8beb0b60), + W64LIT(0x78c13c3cf03cfdcc), W64LIT(0x1ffd81813e817cbf), W64LIT(0x354094946a94d4fe), W64LIT(0xf31cf7f7fbf7eb0c), + W64LIT(0x6f18b9b9deb9a167), W64LIT(0x268b13134c13985f), W64LIT(0x58512c2cb02c7d9c), W64LIT(0xbb05d3d36bd3d6b8), + W64LIT(0xd38ce7e7bbe76b5c), W64LIT(0xdc396e6ea56e57cb), W64LIT(0x95aac4c437c46ef3), W64LIT(0x061b03030c03180f), + W64LIT(0xacdc565645568a13), W64LIT(0x885e44440d441a49), W64LIT(0xfea07f7fe17fdf9e), W64LIT(0x4f88a9a99ea92137), + W64LIT(0x54672a2aa82a4d82), W64LIT(0x6b0abbbbd6bbb16d), W64LIT(0x9f87c1c123c146e2), W64LIT(0xa6f153535153a202), + W64LIT(0xa572dcdc57dcae8b), W64LIT(0x16530b0b2c0b5827), W64LIT(0x27019d9d4e9d9cd3), W64LIT(0xd82b6c6cad6c47c1), + W64LIT(0x62a43131c43195f5), W64LIT(0xe8f37474cd7487b9), W64LIT(0xf115f6f6fff6e309), W64LIT(0x8c4c464605460a43), + W64LIT(0x45a5acac8aac0926), W64LIT(0x0fb589891e893c97), W64LIT(0x28b414145014a044), W64LIT(0xdfbae1e1a3e15b42), + W64LIT(0x2ca616165816b04e), W64LIT(0x74f73a3ae83acdd2), W64LIT(0xd2066969b9696fd0), W64LIT(0x124109092409482d), + W64LIT(0xe0d77070dd70a7ad), W64LIT(0x716fb6b6e2b6d954), W64LIT(0xbd1ed0d067d0ceb7), W64LIT(0xc7d6eded93ed3b7e), + W64LIT(0x85e2cccc17cc2edb), W64LIT(0x8468424215422a57), W64LIT(0x2d2c98985a98b4c2), W64LIT(0x55eda4a4aaa4490e), + W64LIT(0x50752828a0285d88), W64LIT(0xb8865c5c6d5cda31), W64LIT(0xed6bf8f8c7f8933f), W64LIT(0x11c28686228644a4), + + W64LIT(0x7830d818186018c0), W64LIT(0xaf462623238c2305), W64LIT(0xf991b8c6c63fc67e), W64LIT(0x6fcdfbe8e887e813), + W64LIT(0xa113cb878726874c), W64LIT(0x626d11b8b8dab8a9), W64LIT(0x0502090101040108), W64LIT(0x6e9e0d4f4f214f42), + W64LIT(0xee6c9b3636d836ad), W64LIT(0x0451ffa6a6a2a659), W64LIT(0xbdb90cd2d26fd2de), W64LIT(0x06f70ef5f5f3f5fb), + W64LIT(0x80f2967979f979ef), W64LIT(0xcede306f6fa16f5f), W64LIT(0xef3f6d91917e91fc), W64LIT(0x07a4f852525552aa), + W64LIT(0xfdc04760609d6027), W64LIT(0x766535bcbccabc89), W64LIT(0xcd2b379b9b569bac), W64LIT(0x8c018a8e8e028e04), + W64LIT(0x155bd2a3a3b6a371), W64LIT(0x3c186c0c0c300c60), W64LIT(0x8af6847b7bf17bff), W64LIT(0xe16a803535d435b5), + W64LIT(0x693af51d1d741de8), W64LIT(0x47ddb3e0e0a7e053), W64LIT(0xacb321d7d77bd7f6), W64LIT(0xed999cc2c22fc25e), + W64LIT(0x965c432e2eb82e6d), W64LIT(0x7a96294b4b314b62), W64LIT(0x21e15dfefedffea3), W64LIT(0x16aed55757415782), + W64LIT(0x412abd15155415a8), W64LIT(0xb6eee87777c1779f), W64LIT(0xeb6e923737dc37a5), W64LIT(0x56d79ee5e5b3e57b), + W64LIT(0xd923139f9f469f8c), W64LIT(0x17fd23f0f0e7f0d3), W64LIT(0x7f94204a4a354a6a), W64LIT(0x95a944dada4fda9e), + W64LIT(0x25b0a258587d58fa), W64LIT(0xca8fcfc9c903c906), W64LIT(0x8d527c2929a42955), W64LIT(0x22145a0a0a280a50), + W64LIT(0x4f7f50b1b1feb1e1), W64LIT(0x1a5dc9a0a0baa069), W64LIT(0xdad6146b6bb16b7f), W64LIT(0xab17d985852e855c), + W64LIT(0x73673cbdbdcebd81), W64LIT(0x34ba8f5d5d695dd2), W64LIT(0x5020901010401080), W64LIT(0x03f507f4f4f7f4f3), + W64LIT(0xc08bddcbcb0bcb16), W64LIT(0xc67cd33e3ef83eed), W64LIT(0x110a2d0505140528), W64LIT(0xe6ce78676781671f), + W64LIT(0x53d597e4e4b7e473), W64LIT(0xbb4e0227279c2725), W64LIT(0x5882734141194132), W64LIT(0x9d0ba78b8b168b2c), + W64LIT(0x0153f6a7a7a6a751), W64LIT(0x94fab27d7de97dcf), W64LIT(0xfb374995956e95dc), W64LIT(0x9fad56d8d847d88e), + W64LIT(0x30eb70fbfbcbfb8b), W64LIT(0x71c1cdeeee9fee23), W64LIT(0x91f8bb7c7ced7cc7), W64LIT(0xe3cc716666856617), + W64LIT(0x8ea77bdddd53dda6), W64LIT(0x4b2eaf17175c17b8), W64LIT(0x468e454747014702), W64LIT(0xdc211a9e9e429e84), + W64LIT(0xc589d4caca0fca1e), W64LIT(0x995a582d2db42d75), W64LIT(0x79632ebfbfc6bf91), W64LIT(0x1b0e3f07071c0738), + W64LIT(0x2347acadad8ead01), W64LIT(0x2fb4b05a5a755aea), W64LIT(0xb51bef838336836c), W64LIT(0xff66b63333cc3385), + W64LIT(0xf2c65c636391633f), W64LIT(0x0a04120202080210), W64LIT(0x384993aaaa92aa39), W64LIT(0xa8e2de7171d971af), + W64LIT(0xcf8dc6c8c807c80e), W64LIT(0x7d32d119196419c8), W64LIT(0x70923b4949394972), W64LIT(0x9aaf5fd9d943d986), + W64LIT(0x1df931f2f2eff2c3), W64LIT(0x48dba8e3e3abe34b), W64LIT(0x2ab6b95b5b715be2), W64LIT(0x920dbc88881a8834), + W64LIT(0xc8293e9a9a529aa4), W64LIT(0xbe4c0b262698262d), W64LIT(0xfa64bf3232c8328d), W64LIT(0x4a7d59b0b0fab0e9), + W64LIT(0x6acff2e9e983e91b), W64LIT(0x331e770f0f3c0f78), W64LIT(0xa6b733d5d573d5e6), W64LIT(0xba1df480803a8074), + W64LIT(0x7c6127bebec2be99), W64LIT(0xde87ebcdcd13cd26), W64LIT(0xe468893434d034bd), W64LIT(0x75903248483d487a), + W64LIT(0x24e354ffffdbffab), W64LIT(0x8ff48d7a7af57af7), W64LIT(0xea3d6490907a90f4), W64LIT(0x3ebe9d5f5f615fc2), + W64LIT(0xa0403d202080201d), W64LIT(0xd5d00f6868bd6867), W64LIT(0x7234ca1a1a681ad0), W64LIT(0x2c41b7aeae82ae19), + W64LIT(0x5e757db4b4eab4c9), W64LIT(0x19a8ce54544d549a), W64LIT(0xe53b7f93937693ec), W64LIT(0xaa442f222288220d), + W64LIT(0xe9c86364648d6407), W64LIT(0x12ff2af1f1e3f1db), W64LIT(0xa2e6cc7373d173bf), W64LIT(0x5a24821212481290), + W64LIT(0x5d807a40401d403a), W64LIT(0x2810480808200840), W64LIT(0xe89b95c3c32bc356), W64LIT(0x7bc5dfecec97ec33), + W64LIT(0x90ab4ddbdb4bdb96), W64LIT(0x1f5fc0a1a1bea161), W64LIT(0x8307918d8d0e8d1c), W64LIT(0xc97ac83d3df43df5), + W64LIT(0xf1335b97976697cc), W64LIT(0x0000000000000000), W64LIT(0xd483f9cfcf1bcf36), W64LIT(0x87566e2b2bac2b45), + W64LIT(0xb3ece17676c57697), W64LIT(0xb019e68282328264), W64LIT(0xa9b128d6d67fd6fe), W64LIT(0x7736c31b1b6c1bd8), + W64LIT(0x5b7774b5b5eeb5c1), W64LIT(0x2943beafaf86af11), W64LIT(0xdfd41d6a6ab56a77), W64LIT(0x0da0ea50505d50ba), + W64LIT(0x4c8a574545094512), W64LIT(0x18fb38f3f3ebf3cb), W64LIT(0xf060ad3030c0309d), W64LIT(0x74c3c4efef9bef2b), + W64LIT(0xc37eda3f3ffc3fe5), W64LIT(0x1caac75555495592), W64LIT(0x1059dba2a2b2a279), W64LIT(0x65c9e9eaea8fea03), + W64LIT(0xecca6a656589650f), W64LIT(0x686903babad2bab9), W64LIT(0x935e4a2f2fbc2f65), W64LIT(0xe79d8ec0c027c04e), + W64LIT(0x81a160dede5fdebe), W64LIT(0x6c38fc1c1c701ce0), W64LIT(0x2ee746fdfdd3fdbb), W64LIT(0x649a1f4d4d294d52), + W64LIT(0xe0397692927292e4), W64LIT(0xbceafa7575c9758f), W64LIT(0x1e0c360606180630), W64LIT(0x9809ae8a8a128a24), + W64LIT(0x40794bb2b2f2b2f9), W64LIT(0x59d185e6e6bfe663), W64LIT(0x361c7e0e0e380e70), W64LIT(0x633ee71f1f7c1ff8), + W64LIT(0xf7c4556262956237), W64LIT(0xa3b53ad4d477d4ee), W64LIT(0x324d81a8a89aa829), W64LIT(0xf4315296966296c4), + W64LIT(0x3aef62f9f9c3f99b), W64LIT(0xf697a3c5c533c566), W64LIT(0xb14a102525942535), W64LIT(0x20b2ab59597959f2), + W64LIT(0xae15d084842a8454), W64LIT(0xa7e4c57272d572b7), W64LIT(0xdd72ec3939e439d5), W64LIT(0x6198164c4c2d4c5a), + W64LIT(0x3bbc945e5e655eca), W64LIT(0x85f09f7878fd78e7), W64LIT(0xd870e53838e038dd), W64LIT(0x8605988c8c0a8c14), + W64LIT(0xb2bf17d1d163d1c6), W64LIT(0x0b57e4a5a5aea541), W64LIT(0x4dd9a1e2e2afe243), W64LIT(0xf8c24e616199612f), + W64LIT(0x457b42b3b3f6b3f1), W64LIT(0xa542342121842115), W64LIT(0xd625089c9c4a9c94), W64LIT(0x663cee1e1e781ef0), + W64LIT(0x5286614343114322), W64LIT(0xfc93b1c7c73bc776), W64LIT(0x2be54ffcfcd7fcb3), W64LIT(0x1408240404100420), + W64LIT(0x08a2e351515951b2), W64LIT(0xc72f2599995e99bc), W64LIT(0xc4da226d6da96d4f), W64LIT(0x391a650d0d340d68), + W64LIT(0x35e979fafacffa83), W64LIT(0x84a369dfdf5bdfb6), W64LIT(0x9bfca97e7ee57ed7), W64LIT(0xb44819242490243d), + W64LIT(0xd776fe3b3bec3bc5), W64LIT(0x3d4b9aabab96ab31), W64LIT(0xd181f0cece1fce3e), W64LIT(0x5522991111441188), + W64LIT(0x8903838f8f068f0c), W64LIT(0x6b9c044e4e254e4a), W64LIT(0x517366b7b7e6b7d1), W64LIT(0x60cbe0ebeb8beb0b), + W64LIT(0xcc78c13c3cf03cfd), W64LIT(0xbf1ffd81813e817c), W64LIT(0xfe354094946a94d4), W64LIT(0x0cf31cf7f7fbf7eb), + W64LIT(0x676f18b9b9deb9a1), W64LIT(0x5f268b13134c1398), W64LIT(0x9c58512c2cb02c7d), W64LIT(0xb8bb05d3d36bd3d6), + W64LIT(0x5cd38ce7e7bbe76b), W64LIT(0xcbdc396e6ea56e57), W64LIT(0xf395aac4c437c46e), W64LIT(0x0f061b03030c0318), + W64LIT(0x13acdc565645568a), W64LIT(0x49885e44440d441a), W64LIT(0x9efea07f7fe17fdf), W64LIT(0x374f88a9a99ea921), + W64LIT(0x8254672a2aa82a4d), W64LIT(0x6d6b0abbbbd6bbb1), W64LIT(0xe29f87c1c123c146), W64LIT(0x02a6f153535153a2), + W64LIT(0x8ba572dcdc57dcae), W64LIT(0x2716530b0b2c0b58), W64LIT(0xd327019d9d4e9d9c), W64LIT(0xc1d82b6c6cad6c47), + W64LIT(0xf562a43131c43195), W64LIT(0xb9e8f37474cd7487), W64LIT(0x09f115f6f6fff6e3), W64LIT(0x438c4c464605460a), + W64LIT(0x2645a5acac8aac09), W64LIT(0x970fb589891e893c), W64LIT(0x4428b414145014a0), W64LIT(0x42dfbae1e1a3e15b), + W64LIT(0x4e2ca616165816b0), W64LIT(0xd274f73a3ae83acd), W64LIT(0xd0d2066969b9696f), W64LIT(0x2d12410909240948), + W64LIT(0xade0d77070dd70a7), W64LIT(0x54716fb6b6e2b6d9), W64LIT(0xb7bd1ed0d067d0ce), W64LIT(0x7ec7d6eded93ed3b), + W64LIT(0xdb85e2cccc17cc2e), W64LIT(0x578468424215422a), W64LIT(0xc22d2c98985a98b4), W64LIT(0x0e55eda4a4aaa449), + W64LIT(0x8850752828a0285d), W64LIT(0x31b8865c5c6d5cda), W64LIT(0x3fed6bf8f8c7f893), W64LIT(0xa411c28686228644), + + W64LIT(0x1823c6e887b8014f), + W64LIT(0x36a6d2f5796f9152), + W64LIT(0x60bc9b8ea30c7b35), + W64LIT(0x1de0d7c22e4bfe57), + W64LIT(0x157737e59ff04ada), + W64LIT(0x58c9290ab1a06b85), + W64LIT(0xbd5d10f4cb3e0567), + W64LIT(0xe427418ba77d95d8), + W64LIT(0xfbee7c66dd17479e), + W64LIT(0xca2dbf07ad5a8333) +}; + +// Whirlpool basic transformation. Transforms state based on block. +void Whirlpool::Transform(word64 *digest, const word64 *block) +{ + CRYPTOPP_ASSERT(digest != NULLPTR); + CRYPTOPP_ASSERT(block != NULLPTR); + +#if CRYPTOPP_SSE2_ASM_AVAILABLE + if (HasSSE2()) + { + // MMX version has the same structure as C version below +#ifdef __GNUC__ + #if CRYPTOPP_BOOL_X64 + word64 workspace[16]; + #endif + __asm__ __volatile__ + ( + INTEL_NOPREFIX + AS_PUSH_IF86( bx) + AS2( mov AS_REG_6, WORD_REG(ax)) +#else + AS2( lea AS_REG_6, [Whirlpool_C]) + AS2( mov WORD_REG(cx), digest) + AS2( mov WORD_REG(dx), block) +#endif +#if CRYPTOPP_BOOL_X86 + AS2( mov eax, esp) + AS2( and esp, -16) + AS2( sub esp, 16*8) + AS_PUSH_IF86( ax) + #if CRYPTOPP_BOOL_X86 + #define SSE2_workspace esp+WORD_SZ + #endif +#else + #define SSE2_workspace %3 +#endif + AS2( xor esi, esi) + ASL(0) + AS2( movq mm0, [WORD_REG(cx)+8*WORD_REG(si)]) + AS2( movq [SSE2_workspace+8*WORD_REG(si)], mm0) // k + AS2( pxor mm0, [WORD_REG(dx)+8*WORD_REG(si)]) + AS2( movq [SSE2_workspace+64+8*WORD_REG(si)], mm0) // s + AS2( movq [WORD_REG(cx)+8*WORD_REG(si)], mm0) + AS1( inc WORD_REG(si)) + AS2( cmp WORD_REG(si), 8) + ASJ( jne, 0, b) + + AS2( xor esi, esi) + ASL(1) + +#define KSL0(a, b) AS2(movq mm##a, b) +#define KSL1(a, b) AS2(pxor mm##a, b) + +#define KSL(op, i, a, b, c, d) \ + AS2(mov eax, [SSE2_workspace+8*i])\ + AS2(movzx edi, al)\ + KSL##op(a, [AS_REG_6+3*2048+8*WORD_REG(di)])\ + AS2(movzx edi, ah)\ + KSL##op(b, [AS_REG_6+2*2048+8*WORD_REG(di)])\ + AS2(shr eax, 16)\ + AS2(movzx edi, al)\ + AS2(shr eax, 8)\ + KSL##op(c, [AS_REG_6+1*2048+8*WORD_REG(di)])\ + KSL##op(d, [AS_REG_6+0*2048+8*WORD_REG(ax)]) + +#define KSH0(a, b) \ + ASS(pshufw mm##a, mm##a, 1, 0, 3, 2)\ + AS2(pxor mm##a, b) +#define KSH1(a, b) \ + AS2(pxor mm##a, b) +#define KSH2(a, b) \ + AS2(pxor mm##a, b)\ + AS2(movq [SSE2_workspace+8*a], mm##a) + +#define KSH(op, i, a, b, c, d) \ + AS2(mov eax, [SSE2_workspace+8*((i+4)-8*((i+4)/8))+4])\ + AS2(movzx edi, al)\ + KSH##op(a, [AS_REG_6+3*2048+8*WORD_REG(di)])\ + AS2(movzx edi, ah)\ + KSH##op(b, [AS_REG_6+2*2048+8*WORD_REG(di)])\ + AS2(shr eax, 16)\ + AS2(movzx edi, al)\ + AS2(shr eax, 8)\ + KSH##op(c, [AS_REG_6+1*2048+8*WORD_REG(di)])\ + KSH##op(d, [AS_REG_6+0*2048+8*WORD_REG(ax)]) + +#define TSL(op, i, a, b, c, d) \ + AS2(mov eax, [SSE2_workspace+64+8*i])\ + AS2(movzx edi, al)\ + KSL##op(a, [AS_REG_6+3*2048+8*WORD_REG(di)])\ + AS2(movzx edi, ah)\ + KSL##op(b, [AS_REG_6+2*2048+8*WORD_REG(di)])\ + AS2(shr eax, 16)\ + AS2(movzx edi, al)\ + AS2(shr eax, 8)\ + KSL##op(c, [AS_REG_6+1*2048+8*WORD_REG(di)])\ + KSL##op(d, [AS_REG_6+0*2048+8*WORD_REG(ax)]) + +#define TSH0(a, b) \ + ASS(pshufw mm##a, mm##a, 1, 0, 3, 2)\ + AS2(pxor mm##a, [SSE2_workspace+8*a])\ + AS2(pxor mm##a, b) +#define TSH1(a, b) \ + AS2(pxor mm##a, b) +#define TSH2(a, b) \ + AS2(pxor mm##a, b)\ + AS2(movq [SSE2_workspace+64+8*a], mm##a) +#define TSH3(a, b) \ + AS2(pxor mm##a, b)\ + AS2(pxor mm##a, [WORD_REG(cx)+8*a])\ + AS2(movq [WORD_REG(cx)+8*a], mm##a) + +#define TSH(op, i, a, b, c, d) \ + AS2(mov eax, [SSE2_workspace+64+8*((i+4)-8*((i+4)/8))+4])\ + AS2(movzx edi, al)\ + TSH##op(a, [AS_REG_6+3*2048+8*WORD_REG(di)])\ + AS2(movzx edi, ah)\ + TSH##op(b, [AS_REG_6+2*2048+8*WORD_REG(di)])\ + AS2(shr eax, 16)\ + AS2(movzx edi, al)\ + AS2(shr eax, 8)\ + TSH##op(c, [AS_REG_6+1*2048+8*WORD_REG(di)])\ + TSH##op(d, [AS_REG_6+0*2048+8*WORD_REG(ax)]) + + KSL(0, 4, 3, 2, 1, 0) + KSL(0, 0, 7, 6, 5, 4) + KSL(1, 1, 0, 7, 6, 5) + KSL(1, 2, 1, 0, 7, 6) + KSL(1, 3, 2, 1, 0, 7) + KSL(1, 5, 4, 3, 2, 1) + KSL(1, 6, 5, 4, 3, 2) + KSL(1, 7, 6, 5, 4, 3) + KSH(0, 0, 7, 6, 5, 4) + KSH(0, 4, 3, 2, 1, 0) + KSH(1, 1, 0, 7, 6, 5) + KSH(1, 2, 1, 0, 7, 6) + KSH(1, 5, 4, 3, 2, 1) + KSH(1, 6, 5, 4, 3, 2) + KSH(2, 3, 2, 1, 0, 7) + KSH(2, 7, 6, 5, 4, 3) + + AS2( pxor mm0, [AS_REG_6 + 8*1024 + WORD_REG(si)*8]) + AS2( movq [SSE2_workspace], mm0) + + TSL(0, 4, 3, 2, 1, 0) + TSL(0, 0, 7, 6, 5, 4) + TSL(1, 1, 0, 7, 6, 5) + TSL(1, 2, 1, 0, 7, 6) + TSL(1, 3, 2, 1, 0, 7) + TSL(1, 5, 4, 3, 2, 1) + TSL(1, 6, 5, 4, 3, 2) + TSL(1, 7, 6, 5, 4, 3) + TSH(0, 0, 7, 6, 5, 4) + TSH(0, 4, 3, 2, 1, 0) + TSH(1, 1, 0, 7, 6, 5) + TSH(1, 2, 1, 0, 7, 6) + TSH(1, 5, 4, 3, 2, 1) + TSH(1, 6, 5, 4, 3, 2) + + AS1( inc WORD_REG(si)) + AS2( cmp WORD_REG(si), 10) + ASJ( je, 2, f) + + TSH(2, 3, 2, 1, 0, 7) + TSH(2, 7, 6, 5, 4, 3) + + ASJ( jmp, 1, b) + ASL(2) + + TSH(3, 3, 2, 1, 0, 7) + TSH(3, 7, 6, 5, 4, 3) + +#undef KSL +#undef KSH +#undef TSL +#undef TSH + + AS_POP_IF86( sp) + AS1( emms) + +#if defined(__GNUC__) + AS_POP_IF86( bx) +#endif +#ifdef __GNUC__ + ATT_PREFIX + : + : "a" (Whirlpool_C), "c" (digest), "d" (block) + #if CRYPTOPP_BOOL_X64 + , "r" (workspace) + #endif + : "%esi", "%edi", "memory", "cc" + #if CRYPTOPP_BOOL_X64 + , "%r9" + #endif + ); +#endif + } + else +#endif // #ifdef CRYPTOPP_X86_ASM_AVAILABLE + { + word64 s[8]; // the cipher state + word64 k[8]; // the round key + + // Compute and apply K^0 to the cipher state + // Also apply part of the Miyaguchi-Preneel compression function + for (int i=0; i<8; i++) + digest[i] = s[i] = block[i] ^ (k[i] = digest[i]); + +#define KSL(op, i, a, b, c, d) \ + t = (word32)k[i];\ + w##a = Whirlpool_C[3*256 + (byte)t] ^ (op ? w##a : 0);\ + t >>= 8;\ + w##b = Whirlpool_C[2*256 + (byte)t] ^ (op ? w##b : 0);\ + t >>= 8;\ + w##c = Whirlpool_C[1*256 + (byte)t] ^ (op ? w##c : 0);\ + t >>= 8;\ + w##d = Whirlpool_C[0*256 + t] ^ (op ? w##d : 0); + +#define KSH(op, i, a, b, c, d) \ + t = (word32)(k[(i+4)%8]>>32);\ + w##a = Whirlpool_C[3*256 + (byte)t] ^ (op ? w##a : rotrConstant<32>(w##a));\ + if (op==2) k[a] = w##a;\ + t >>= 8;\ + w##b = Whirlpool_C[2*256 + (byte)t] ^ (op ? w##b : rotrConstant<32>(w##b));\ + if (op==2) k[b] = w##b;\ + t >>= 8;\ + w##c = Whirlpool_C[1*256 + (byte)t] ^ (op ? w##c : rotrConstant<32>(w##c));\ + if (op==2) k[c] = w##c;\ + t >>= 8;\ + w##d = Whirlpool_C[0*256 + t] ^ (op ? w##d : rotrConstant<32>(w##d));\ + if (op==2) k[d] = w##d;\ + +#define TSL(op, i, a, b, c, d) \ + t = (word32)s[i];\ + w##a = Whirlpool_C[3*256 + (byte)t] ^ (op ? w##a : 0);\ + t >>= 8;\ + w##b = Whirlpool_C[2*256 + (byte)t] ^ (op ? w##b : 0);\ + t >>= 8;\ + w##c = Whirlpool_C[1*256 + (byte)t] ^ (op ? w##c : 0);\ + t >>= 8;\ + w##d = Whirlpool_C[0*256 + t] ^ (op ? w##d : 0); + +#define TSH_OP(op, a, b) \ + w##a = Whirlpool_C[b*256 + (byte)t] ^ (op ? w##a : rotrConstant<32>(w##a) ^ k[a]);\ + if (op==2) s[a] = w##a;\ + if (op==3) digest[a] ^= w##a;\ + +#define TSH(op, i, a, b, c, d) \ + t = (word32)(s[(i+4)%8]>>32);\ + TSH_OP(op, a, 3);\ + t >>= 8;\ + TSH_OP(op, b, 2);\ + t >>= 8;\ + TSH_OP(op, c, 1);\ + t >>= 8;\ + TSH_OP(op, d, 0);\ + + // Iterate over all rounds: + int r=0; + while (true) + { + // Added initialization due to Coverity findings. + word64 w0=0, w1=0, w2=0, w3=0, w4=0, w5=0, w6=0, w7=0; + word32 t=0; + + KSL(0, 4, 3, 2, 1, 0) + KSL(0, 0, 7, 6, 5, 4) + KSL(1, 1, 0, 7, 6, 5) + KSL(1, 2, 1, 0, 7, 6) + KSL(1, 3, 2, 1, 0, 7) + KSL(1, 5, 4, 3, 2, 1) + KSL(1, 6, 5, 4, 3, 2) + KSL(1, 7, 6, 5, 4, 3) + KSH(0, 0, 7, 6, 5, 4) + KSH(0, 4, 3, 2, 1, 0) + KSH(1, 1, 0, 7, 6, 5) + KSH(1, 2, 1, 0, 7, 6) + KSH(1, 5, 4, 3, 2, 1) + KSH(1, 6, 5, 4, 3, 2) + KSH(2, 3, 2, 1, 0, 7) + KSH(2, 7, 6, 5, 4, 3) + + k[0] ^= Whirlpool_C[1024+r]; + + TSL(0, 4, 3, 2, 1, 0) + TSL(0, 0, 7, 6, 5, 4) + TSL(1, 1, 0, 7, 6, 5) + TSL(1, 2, 1, 0, 7, 6) + TSL(1, 3, 2, 1, 0, 7) + TSL(1, 5, 4, 3, 2, 1) + TSL(1, 6, 5, 4, 3, 2) + TSL(1, 7, 6, 5, 4, 3) + TSH(0, 0, 7, 6, 5, 4) + TSH(0, 4, 3, 2, 1, 0) + TSH(1, 1, 0, 7, 6, 5) + TSH(1, 2, 1, 0, 7, 6) + TSH(1, 5, 4, 3, 2, 1) + TSH(1, 6, 5, 4, 3, 2) + + if (++r < R) + { + TSH(2, 3, 2, 1, 0, 7) + TSH(2, 7, 6, 5, 4, 3) + } + else + { + TSH(3, 3, 2, 1, 0, 7) + TSH(3, 7, 6, 5, 4, 3) + break; + } + } + } +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/whrlpool.h b/external/ours/library/crypto/src/shared/original/whrlpool.h new file mode 100755 index 000000000..33e4b3020 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/words.h b/external/ours/library/crypto/src/shared/original/words.h index 8849b6107..86698a3f4 100755 --- a/external/ours/library/crypto/src/shared/original/words.h +++ b/external/ours/library/crypto/src/shared/original/words.h @@ -1,103 +1,225 @@ -#ifndef CRYPTOPP_WORDS_H -#define CRYPTOPP_WORDS_H - -#include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -inline unsigned int CountWords(const word *X, unsigned int N) -{ - while (N && X[N-1]==0) - N--; - return N; -} - -inline void SetWords(word *r, word a, unsigned int n) -{ - for (unsigned int i=0; i> (WORD_BITS-shiftBits); - } - return carry; -} - -inline word ShiftWordsRightByBits(word *r, unsigned int n, unsigned int shiftBits) -{ - assert (shiftBits=0; i--) - { - u = r[i]; - r[i] = (u >> shiftBits) | carry; - carry = u << (WORD_BITS-shiftBits); - } - return carry; -} - -inline void ShiftWordsLeftByWords(word *r, unsigned int n, unsigned int shiftWords) -{ - shiftWords = STDMIN(shiftWords, n); - if (shiftWords) - { - for (unsigned int i=n-1; i>=shiftWords; i--) - r[i] = r[i-shiftWords]; - SetWords(r, 0, shiftWords); - } -} - -inline void ShiftWordsRightByWords(word *r, unsigned int n, unsigned int shiftWords) -{ - shiftWords = STDMIN(shiftWords, n); - if (shiftWords) - { - for (unsigned int i=0; i+shiftWords> (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+shiftWords> 8) & 1); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +// ******************** x25519 Agreement ************************* // + +x25519::x25519(const byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) +{ + std::memcpy(m_pk, y, PUBLIC_KEYLENGTH); + std::memcpy(m_sk, x, SECRET_KEYLENGTH); + + CRYPTOPP_ASSERT(IsClamped(m_sk) == true); + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); +} + +x25519::x25519(const byte x[SECRET_KEYLENGTH]) +{ + std::memcpy(m_sk, x, SECRET_KEYLENGTH); + Donna::curve25519_mult(m_pk, m_sk); + + CRYPTOPP_ASSERT(IsClamped(m_sk) == true); + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); +} + +x25519::x25519(const Integer &y, const Integer &x) +{ + CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH); + CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); + + y.Encode(m_pk, PUBLIC_KEYLENGTH); std::reverse(m_pk+0, m_pk+PUBLIC_KEYLENGTH); + x.Encode(m_sk, SECRET_KEYLENGTH); std::reverse(m_sk+0, m_sk+SECRET_KEYLENGTH); + + CRYPTOPP_ASSERT(IsClamped(m_sk) == true); + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); +} + +x25519::x25519(const Integer &x) +{ + CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); + + x.Encode(m_sk, SECRET_KEYLENGTH); + std::reverse(m_sk+0, m_sk+SECRET_KEYLENGTH); + Donna::curve25519_mult(m_pk, m_sk); + + CRYPTOPP_ASSERT(IsClamped(m_sk) == true); + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); +} + +x25519::x25519(RandomNumberGenerator &rng) +{ + rng.GenerateBlock(m_sk, SECRET_KEYLENGTH); + ClampKey(m_sk); + SecretToPublicKey(m_pk, m_sk); +} + +x25519::x25519(BufferedTransformation ¶ms) +{ + Load(params); +} + +void x25519::ClampKey(byte x[SECRET_KEYLENGTH]) const +{ + x[0] &= 248; x[31] &= 127; x[31] |= 64; +} + +bool x25519::IsClamped(const byte x[SECRET_KEYLENGTH]) const +{ + return (x[0] & 248) == x[0] && (x[31] & 127) == x[31] && (x[31] | 64) == x[31]; +} + +bool x25519::IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const +{ + return HasSmallOrder(y); +} + +void x25519::SecretToPublicKey(byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) const +{ + Donna::curve25519_mult(y, x); +} + +void x25519::BERDecodeAndCheckAlgorithmID(BufferedTransformation &bt) +{ + // We have not yet determined the OID to use for this object. + // We can't use OID's decoder because it throws BERDecodeError + // if the OIDs do not match. + OID oid(bt); + + // 1.3.6.1.4.1.3029.1.5.1/curvey25519 from Cryptlib used by OpenPGP. + // https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-rfc4880bis + if (!m_oid.Empty() && m_oid != oid) + BERDecodeError(); // Only accept user specified OID + else if (oid == ASN1::curve25519() || oid == ASN1::X25519() || + oid == OID(1)+3+6+1+4+1+3029+1+5) + m_oid = oid; // Accept any of the x25519 OIDs + else + BERDecodeError(); +} + +void x25519::BERDecode(BufferedTransformation &bt) +{ + // https://tools.ietf.org/html/rfc8410, section 7 and + // https://www.cryptopp.com/wiki/curve25519_keys + BERSequenceDecoder privateKeyInfo(bt); + word32 version; + BERDecodeUnsigned(privateKeyInfo, version, INTEGER, 0, 1); // check version + + BERSequenceDecoder algorithm(privateKeyInfo); + // GetAlgorithmID().BERDecodeAndCheck(algorithm); + BERDecodeAndCheckAlgorithmID(algorithm); + algorithm.MessageEnd(); + + BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING); + BERDecodePrivateKey(octetString, false, (size_t)privateKeyInfo.RemainingLength()); + octetString.MessageEnd(); + + // publicKey [1] IMPLICIT PublicKey OPTIONAL + bool generatePublicKey = true; + if (privateKeyInfo.EndReached() == false /*version == 1?*/) + { + // Should we test this before decoding? In either case we + // just throw a BERDecodeErr() when we can't parse it. + BERGeneralDecoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1); + SecByteBlock subjectPublicKey; + unsigned int unusedBits; + BERDecodeBitString(publicKey, subjectPublicKey, unusedBits); + CRYPTOPP_ASSERT(unusedBits == 0); + CRYPTOPP_ASSERT(subjectPublicKey.size() == PUBLIC_KEYLENGTH); + if (subjectPublicKey.size() != PUBLIC_KEYLENGTH) + BERDecodeError(); + std::memcpy(m_pk.begin(), subjectPublicKey, PUBLIC_KEYLENGTH); + generatePublicKey = false; + publicKey.MessageEnd(); + } + + privateKeyInfo.MessageEnd(); + + if (generatePublicKey) + Donna::curve25519_mult(m_pk, m_sk); + + CRYPTOPP_ASSERT(IsClamped(m_sk) == true); + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); +} + +void x25519::DEREncode(BufferedTransformation &bt, int version) const +{ + // https://tools.ietf.org/html/rfc8410, section 7 and + // https://www.cryptopp.com/wiki/curve25519_keys + CRYPTOPP_ASSERT(version == 0 || version == 1); + + DERSequenceEncoder privateKeyInfo(bt); + DEREncodeUnsigned(privateKeyInfo, version); + + DERSequenceEncoder algorithm(privateKeyInfo); + GetAlgorithmID().DEREncode(algorithm); + algorithm.MessageEnd(); + + DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING); + DEREncodePrivateKey(octetString); + octetString.MessageEnd(); + + if (version == 1) + { + DERGeneralEncoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1); + DEREncodeBitString(publicKey, m_pk, PUBLIC_KEYLENGTH); + publicKey.MessageEnd(); + } + + privateKeyInfo.MessageEnd(); +} + +void x25519::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t /*size*/) +{ + // https://tools.ietf.org/html/rfc8410 and + // https://www.cryptopp.com/wiki/curve25519_keys + + BERGeneralDecoder privateKey(bt, OCTET_STRING); + + if (!privateKey.IsDefiniteLength()) + BERDecodeError(); + + size_t size = privateKey.Get(m_sk, SECRET_KEYLENGTH); + if (size != SECRET_KEYLENGTH) + BERDecodeError(); + + // We don't know how to decode them + if (parametersPresent) + BERDecodeError(); + + privateKey.MessageEnd(); +} + +void x25519::DEREncodePrivateKey(BufferedTransformation &bt) const +{ + // https://tools.ietf.org/html/rfc8410 + DERGeneralEncoder privateKey(bt, OCTET_STRING); + privateKey.Put(m_sk, SECRET_KEYLENGTH); + privateKey.MessageEnd(); +} + +bool x25519::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + CRYPTOPP_UNUSED(rng); + CRYPTOPP_ASSERT(IsClamped(m_sk) == true); + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); + + if (level >= 1 && IsClamped(m_sk) == false) + return false; + if (level >= 2 && IsSmallOrder(m_pk) == true) + return false; + if (level >= 3) + { + // Verify m_pk is pairwise consistent with m_sk + SecByteBlock pk(PUBLIC_KEYLENGTH); + SecretToPublicKey(pk, m_sk); + + if (VerifyBufsEqual(pk, m_pk, PUBLIC_KEYLENGTH) == false) + return false; + } + + return true; +} + +bool x25519::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (std::strcmp(name, Name::PrivateExponent()) == 0 || std::strcmp(name, "SecretKey") == 0) + { + this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); + reinterpret_cast(pValue)->Assign(m_sk, SECRET_KEYLENGTH, false); + return true; + } + + if (std::strcmp(name, Name::PublicElement()) == 0) + { + this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); + reinterpret_cast(pValue)->Assign(m_pk, PUBLIC_KEYLENGTH, false); + return true; + } + + if (std::strcmp(name, Name::GroupOID()) == 0) + { + if (m_oid.Empty()) + return false; + + this->ThrowIfTypeMismatch(name, typeid(OID), valueType); + *reinterpret_cast(pValue) = m_oid; + return true; + } + + return false; +} + +void x25519::AssignFrom(const NameValuePairs &source) +{ + ConstByteArrayParameter val; + if (source.GetValue(Name::PrivateExponent(), val) || source.GetValue("SecretKey", val)) + { + std::memcpy(m_sk, val.begin(), SECRET_KEYLENGTH); + } + + if (source.GetValue(Name::PublicElement(), val)) + { + std::memcpy(m_pk, val.begin(), PUBLIC_KEYLENGTH); + } + + OID oid; + if (source.GetValue(Name::GroupOID(), oid)) + { + m_oid = oid; + } + + bool derive = false; + if (source.GetValue("DerivePublicKey", derive) && derive == true) + SecretToPublicKey(m_pk, m_sk); +} + +void x25519::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) +{ + ConstByteArrayParameter seed; + if (params.GetValue(Name::Seed(), seed) && rng.CanIncorporateEntropy()) + rng.IncorporateEntropy(seed.begin(), seed.size()); + + rng.GenerateBlock(m_sk, SECRET_KEYLENGTH); + ClampKey(m_sk); + SecretToPublicKey(m_pk, m_sk); +} + +void x25519::GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const +{ + rng.GenerateBlock(privateKey, SECRET_KEYLENGTH); + ClampKey(privateKey); +} + +void x25519::GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const +{ + CRYPTOPP_UNUSED(rng); + SecretToPublicKey(publicKey, privateKey); +} + +bool x25519::Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey) const +{ + CRYPTOPP_ASSERT(agreedValue != NULLPTR); + CRYPTOPP_ASSERT(otherPublicKey != NULLPTR); + + if (validateOtherPublicKey && IsSmallOrder(otherPublicKey)) + return false; + + return Donna::curve25519_mult(agreedValue, privateKey, otherPublicKey) == 0; +} + +// ******************** ed25519 Signer ************************* // + +void ed25519PrivateKey::SecretToPublicKey(byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) const +{ + int ret = Donna::ed25519_publickey(y, x); + CRYPTOPP_ASSERT(ret == 0); CRYPTOPP_UNUSED(ret); +} + +bool ed25519PrivateKey::IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const +{ + return HasSmallOrder(y); +} + +bool ed25519PrivateKey::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + CRYPTOPP_UNUSED(rng); + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); + + if (level >= 1 && IsSmallOrder(m_pk) == true) + return false; + if (level >= 3) + { + // Verify m_pk is pairwise consistent with m_sk + SecByteBlock pk(PUBLIC_KEYLENGTH); + SecretToPublicKey(pk, m_sk); + + if (VerifyBufsEqual(pk, m_pk, PUBLIC_KEYLENGTH) == false) + return false; + } + + return true; +} + +bool ed25519PrivateKey::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (std::strcmp(name, Name::PrivateExponent()) == 0 || std::strcmp(name, "SecretKey") == 0) + { + this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); + reinterpret_cast(pValue)->Assign(m_sk, SECRET_KEYLENGTH, false); + return true; + } + + if (std::strcmp(name, Name::PublicElement()) == 0) + { + this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); + reinterpret_cast(pValue)->Assign(m_pk, PUBLIC_KEYLENGTH, false); + return true; + } + + if (std::strcmp(name, Name::GroupOID()) == 0) + { + if (m_oid.Empty()) + return false; + + this->ThrowIfTypeMismatch(name, typeid(OID), valueType); + *reinterpret_cast(pValue) = m_oid; + return true; + } + + return false; +} + +void ed25519PrivateKey::AssignFrom(const NameValuePairs &source) +{ + ConstByteArrayParameter val; + if (source.GetValue(Name::PrivateExponent(), val) || source.GetValue("SecretKey", val)) + { + CRYPTOPP_ASSERT(val.size() == SECRET_KEYLENGTH); + std::memcpy(m_sk, val.begin(), SECRET_KEYLENGTH); + } + if (source.GetValue(Name::PublicElement(), val)) + { + CRYPTOPP_ASSERT(val.size() == PUBLIC_KEYLENGTH); + std::memcpy(m_pk, val.begin(), PUBLIC_KEYLENGTH); + } + + OID oid; + if (source.GetValue(Name::GroupOID(), oid)) + { + m_oid = oid; + } + + bool derive = false; + if (source.GetValue("DerivePublicKey", derive) && derive == true) + SecretToPublicKey(m_pk, m_sk); + + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); +} + +void ed25519PrivateKey::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms=g_nullNameValuePairs) +{ + ConstByteArrayParameter seed; + if (params.GetValue(Name::Seed(), seed) && rng.CanIncorporateEntropy()) + rng.IncorporateEntropy(seed.begin(), seed.size()); + + rng.GenerateBlock(m_sk, SECRET_KEYLENGTH); + int ret = Donna::ed25519_publickey(m_pk, m_sk); + CRYPTOPP_ASSERT(ret == 0); CRYPTOPP_UNUSED(ret); +} + +void ed25519PrivateKey::MakePublicKey (PublicKey &pub) const +{ + pub.AssignFrom(MakeParameters + (Name::PublicElement(), ConstByteArrayParameter(m_pk.begin(), PUBLIC_KEYLENGTH)) + (Name::GroupOID(), GetAlgorithmID())); +} + +void ed25519PrivateKey::BERDecodeAndCheckAlgorithmID(BufferedTransformation &bt) +{ + // We have not yet determined the OID to use for this object. + // We can't use OID's decoder because it throws BERDecodeError + // if the OIDs do not match. + OID oid(bt); + + if (!m_oid.Empty() && m_oid != oid) + BERDecodeError(); // Only accept user specified OID + else if (oid == ASN1::curve25519() || oid == ASN1::Ed25519()) + m_oid = oid; // Accept any of the ed25519PrivateKey OIDs + else + BERDecodeError(); +} + +void ed25519PrivateKey::BERDecode(BufferedTransformation &bt) +{ + // https://tools.ietf.org/html/rfc8410, section 7 and + // https://www.cryptopp.com/wiki/curve25519_keys + BERSequenceDecoder privateKeyInfo(bt); + word32 version; + BERDecodeUnsigned(privateKeyInfo, version, INTEGER, 0, 1); // check version + + BERSequenceDecoder algorithm(privateKeyInfo); + // GetAlgorithmID().BERDecodeAndCheck(algorithm); + BERDecodeAndCheckAlgorithmID(algorithm); + algorithm.MessageEnd(); + + BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING); + BERDecodePrivateKey(octetString, false, (size_t)privateKeyInfo.RemainingLength()); + octetString.MessageEnd(); + + // publicKey [1] IMPLICIT PublicKey OPTIONAL + bool generatePublicKey = true; + if (privateKeyInfo.EndReached() == false /*version == 1?*/) + { + // Should we test this before decoding? In either case we + // just throw a BERDecodeErr() when we can't parse it. + BERGeneralDecoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1); + SecByteBlock subjectPublicKey; + unsigned int unusedBits; + BERDecodeBitString(publicKey, subjectPublicKey, unusedBits); + CRYPTOPP_ASSERT(unusedBits == 0); + CRYPTOPP_ASSERT(subjectPublicKey.size() == PUBLIC_KEYLENGTH); + if (subjectPublicKey.size() != PUBLIC_KEYLENGTH) + BERDecodeError(); + std::memcpy(m_pk.begin(), subjectPublicKey, PUBLIC_KEYLENGTH); + generatePublicKey = false; + publicKey.MessageEnd(); + } + + privateKeyInfo.MessageEnd(); + + if (generatePublicKey) + Donna::ed25519_publickey(m_pk, m_sk); + + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); +} + +void ed25519PrivateKey::DEREncode(BufferedTransformation &bt, int version) const +{ + // https://tools.ietf.org/html/rfc8410, section 7 and + // https://www.cryptopp.com/wiki/curve25519_keys + CRYPTOPP_ASSERT(version == 0 || version == 1); + + DERSequenceEncoder privateKeyInfo(bt); + DEREncodeUnsigned(privateKeyInfo, version); + + DERSequenceEncoder algorithm(privateKeyInfo); + GetAlgorithmID().DEREncode(algorithm); + algorithm.MessageEnd(); + + DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING); + DEREncodePrivateKey(octetString); + octetString.MessageEnd(); + + if (version == 1) + { + DERGeneralEncoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1); + DEREncodeBitString(publicKey, m_pk, PUBLIC_KEYLENGTH); + publicKey.MessageEnd(); + } + + privateKeyInfo.MessageEnd(); +} + +void ed25519PrivateKey::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t /*size*/) +{ + // https://tools.ietf.org/html/rfc8410 and + // https://www.cryptopp.com/wiki/curve25519_keys + + BERGeneralDecoder privateKey(bt, OCTET_STRING); + + if (!privateKey.IsDefiniteLength()) + BERDecodeError(); + + size_t size = privateKey.Get(m_sk, SECRET_KEYLENGTH); + if (size != SECRET_KEYLENGTH) + BERDecodeError(); + + // We don't know how to decode them + if (parametersPresent) + BERDecodeError(); + + privateKey.MessageEnd(); +} + +void ed25519PrivateKey::DEREncodePrivateKey(BufferedTransformation &bt) const +{ + // https://tools.ietf.org/html/rfc8410 + DERGeneralEncoder privateKey(bt, OCTET_STRING); + privateKey.Put(m_sk, SECRET_KEYLENGTH); + privateKey.MessageEnd(); +} + +void ed25519PrivateKey::SetPrivateExponent (const byte x[SECRET_KEYLENGTH]) +{ + AssignFrom(MakeParameters + (Name::PrivateExponent(), ConstByteArrayParameter(x, SECRET_KEYLENGTH)) + ("DerivePublicKey", true)); +} + +void ed25519PrivateKey::SetPrivateExponent (const Integer &x) +{ + CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); + + SecByteBlock bx(SECRET_KEYLENGTH); + x.Encode(bx, SECRET_KEYLENGTH); std::reverse(bx+0, bx+SECRET_KEYLENGTH); + + AssignFrom(MakeParameters + (Name::PrivateExponent(), ConstByteArrayParameter(bx, SECRET_KEYLENGTH, false)) + ("DerivePublicKey", true)); +} + +const Integer& ed25519PrivateKey::GetPrivateExponent() const +{ + m_x = Integer(m_sk, SECRET_KEYLENGTH, Integer::UNSIGNED, LITTLE_ENDIAN_ORDER); + return m_x; +} + +//////////////////////// + +ed25519Signer::ed25519Signer(const byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) +{ + AccessPrivateKey().AssignFrom(MakeParameters + (Name::PrivateExponent(), ConstByteArrayParameter(x, SECRET_KEYLENGTH, false)) + (Name::PublicElement(), ConstByteArrayParameter(y, PUBLIC_KEYLENGTH, false))); +} + +ed25519Signer::ed25519Signer(const byte x[SECRET_KEYLENGTH]) +{ + AccessPrivateKey().AssignFrom(MakeParameters + (Name::PrivateExponent(), ConstByteArrayParameter(x, SECRET_KEYLENGTH, false)) + ("DerivePublicKey", true)); +} + +ed25519Signer::ed25519Signer(const Integer &y, const Integer &x) +{ + CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH); + CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); + + SecByteBlock by(PUBLIC_KEYLENGTH), bx(SECRET_KEYLENGTH); + y.Encode(by, PUBLIC_KEYLENGTH); std::reverse(by+0, by+PUBLIC_KEYLENGTH); + x.Encode(bx, SECRET_KEYLENGTH); std::reverse(bx+0, bx+SECRET_KEYLENGTH); + + AccessPrivateKey().AssignFrom(MakeParameters + (Name::PublicElement(), ConstByteArrayParameter(by, PUBLIC_KEYLENGTH, false)) + (Name::PrivateExponent(), ConstByteArrayParameter(bx, SECRET_KEYLENGTH, false))); +} + +ed25519Signer::ed25519Signer(const Integer &x) +{ + CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); + + SecByteBlock bx(SECRET_KEYLENGTH); + x.Encode(bx, SECRET_KEYLENGTH); std::reverse(bx+0, bx+SECRET_KEYLENGTH); + + AccessPrivateKey().AssignFrom(MakeParameters + (Name::PrivateExponent(), ConstByteArrayParameter(bx, SECRET_KEYLENGTH, false)) + ("DerivePublicKey", true)); +} + +ed25519Signer::ed25519Signer(const PKCS8PrivateKey &key) +{ + // Load all fields from the other key + ByteQueue queue; + key.Save(queue); + AccessPrivateKey().Load(queue); +} + +ed25519Signer::ed25519Signer(RandomNumberGenerator &rng) +{ + AccessPrivateKey().GenerateRandom(rng); +} + +ed25519Signer::ed25519Signer(BufferedTransformation ¶ms) +{ + AccessPrivateKey().Load(params); +} + +size_t ed25519Signer::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const +{ + CRYPTOPP_ASSERT(signature != NULLPTR); CRYPTOPP_UNUSED(rng); + + ed25519_MessageAccumulator& accum = dynamic_cast(messageAccumulator); + const ed25519PrivateKey& pk = dynamic_cast(GetPrivateKey()); + int ret = Donna::ed25519_sign(accum.data(), accum.size(), pk.GetPrivateKeyBytePtr(), pk.GetPublicKeyBytePtr(), signature); + CRYPTOPP_ASSERT(ret == 0); + + if (restart) + accum.Restart(); + + return ret == 0 ? SIGNATURE_LENGTH : 0; +} + +size_t ed25519Signer::SignStream (RandomNumberGenerator &rng, std::istream& stream, byte *signature) const +{ + CRYPTOPP_ASSERT(signature != NULLPTR); CRYPTOPP_UNUSED(rng); + + const ed25519PrivateKey& pk = dynamic_cast(GetPrivateKey()); + int ret = Donna::ed25519_sign(stream, pk.GetPrivateKeyBytePtr(), pk.GetPublicKeyBytePtr(), signature); + CRYPTOPP_ASSERT(ret == 0); + + return ret == 0 ? SIGNATURE_LENGTH : 0; +} + +// ******************** ed25519 Verifier ************************* // + +bool ed25519PublicKey::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (std::strcmp(name, Name::PublicElement()) == 0) + { + this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); + reinterpret_cast(pValue)->Assign(m_pk, PUBLIC_KEYLENGTH, false); + return true; + } + + if (std::strcmp(name, Name::GroupOID()) == 0) + { + if (m_oid.Empty()) + return false; + + this->ThrowIfTypeMismatch(name, typeid(OID), valueType); + *reinterpret_cast(pValue) = m_oid; + return true; + } + + return false; +} + +void ed25519PublicKey::AssignFrom(const NameValuePairs &source) +{ + ConstByteArrayParameter ba; + if (source.GetValue(Name::PublicElement(), ba)) + { + std::memcpy(m_pk, ba.begin(), PUBLIC_KEYLENGTH); + } + + OID oid; + if (source.GetValue(Name::GroupOID(), oid)) + { + m_oid = oid; + } +} + +void ed25519PublicKey::BERDecodeAndCheckAlgorithmID(BufferedTransformation& bt) +{ + // We have not yet determined the OID to use for this object. + // We can't use OID's decoder because it throws BERDecodeError + // if the OIDs do not match. + OID oid(bt); + + if (!m_oid.Empty() && m_oid != oid) + BERDecodeError(); // Only accept user specified OID + else if (oid == ASN1::curve25519() || oid == ASN1::Ed25519()) + m_oid = oid; // Accept any of the ed25519PublicKey OIDs + else + BERDecodeError(); +} + +void ed25519PublicKey::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder publicKeyInfo(bt); + + BERSequenceDecoder algorithm(publicKeyInfo); + // GetAlgorithmID().BERDecodeAndCheck(algorithm); + BERDecodeAndCheckAlgorithmID(algorithm); + algorithm.MessageEnd(); + + BERDecodePublicKey(publicKeyInfo, false, (size_t)publicKeyInfo.RemainingLength()); + + publicKeyInfo.MessageEnd(); +} + +void ed25519PublicKey::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder publicKeyInfo(bt); + + DERSequenceEncoder algorithm(publicKeyInfo); + GetAlgorithmID().DEREncode(algorithm); + algorithm.MessageEnd(); + + DEREncodePublicKey(publicKeyInfo); + + publicKeyInfo.MessageEnd(); +} + +void ed25519PublicKey::BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t /*size*/) +{ + // We don't know how to decode them + if (parametersPresent) + BERDecodeError(); + + SecByteBlock subjectPublicKey; + unsigned int unusedBits; + BERDecodeBitString(bt, subjectPublicKey, unusedBits); + + CRYPTOPP_ASSERT(unusedBits == 0); + CRYPTOPP_ASSERT(subjectPublicKey.size() == PUBLIC_KEYLENGTH); + if (subjectPublicKey.size() != PUBLIC_KEYLENGTH) + BERDecodeError(); + + std::memcpy(m_pk.begin(), subjectPublicKey, PUBLIC_KEYLENGTH); +} + +void ed25519PublicKey::DEREncodePublicKey(BufferedTransformation &bt) const +{ + DEREncodeBitString(bt, m_pk, PUBLIC_KEYLENGTH); +} + +void ed25519PublicKey::SetPublicElement (const byte y[PUBLIC_KEYLENGTH]) +{ + std::memcpy(m_pk, y, PUBLIC_KEYLENGTH); +} + +void ed25519PublicKey::SetPublicElement (const Integer &y) +{ + CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH); + + SecByteBlock by(PUBLIC_KEYLENGTH); + y.Encode(by, PUBLIC_KEYLENGTH); std::reverse(by+0, by+PUBLIC_KEYLENGTH); + + std::memcpy(m_pk, by, PUBLIC_KEYLENGTH); +} + +const Integer& ed25519PublicKey::GetPublicElement() const +{ + m_y = Integer(m_pk, PUBLIC_KEYLENGTH, Integer::UNSIGNED, LITTLE_ENDIAN_ORDER); + return m_y; +} + +bool ed25519PublicKey::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(level); + return true; +} + +//////////////////////// + +ed25519Verifier::ed25519Verifier(const byte y[PUBLIC_KEYLENGTH]) +{ + AccessPublicKey().AssignFrom(MakeParameters + (Name::PublicElement(), ConstByteArrayParameter(y, PUBLIC_KEYLENGTH))); +} + +ed25519Verifier::ed25519Verifier(const Integer &y) +{ + CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH); + + SecByteBlock by(PUBLIC_KEYLENGTH); + y.Encode(by, PUBLIC_KEYLENGTH); std::reverse(by+0, by+PUBLIC_KEYLENGTH); + + AccessPublicKey().AssignFrom(MakeParameters + (Name::PublicElement(), ConstByteArrayParameter(by, PUBLIC_KEYLENGTH, false))); +} + +ed25519Verifier::ed25519Verifier(const X509PublicKey &key) +{ + // Load all fields from the other key + ByteQueue queue; + key.Save(queue); + AccessPublicKey().Load(queue); +} + +ed25519Verifier::ed25519Verifier(BufferedTransformation ¶ms) +{ + AccessPublicKey().Load(params); +} + +ed25519Verifier::ed25519Verifier(const ed25519Signer& signer) +{ + const ed25519PrivateKey& priv = dynamic_cast(signer.GetPrivateKey()); + priv.MakePublicKey(AccessPublicKey()); +} + +bool ed25519Verifier::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const +{ + ed25519_MessageAccumulator& accum = static_cast(messageAccumulator); + const ed25519PublicKey& pk = dynamic_cast(GetPublicKey()); + int ret = Donna::ed25519_sign_open(accum.data(), accum.size(), pk.GetPublicKeyBytePtr(), accum.signature()); + accum.Restart(); + + return ret == 0; +} + +bool ed25519Verifier::VerifyStream(std::istream& stream, const byte *signature, size_t signatureLen) const +{ + CRYPTOPP_ASSERT(signatureLen == SIGNATURE_LENGTH); + CRYPTOPP_UNUSED(signatureLen); + + const ed25519PublicKey& pk = static_cast(GetPublicKey()); + int ret = Donna::ed25519_sign_open(stream, pk.GetPublicKeyBytePtr(), signature); + + return ret == 0; +} + +NAMESPACE_END // CryptoPP diff --git a/external/ours/library/crypto/src/shared/original/xed25519.h b/external/ours/library/crypto/src/shared/original/xed25519.h new file mode 100755 index 000000000..3dcbd2565 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/xed25519.h @@ -0,0 +1,825 @@ +// xed25519.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, +// http://github.com/floodyberry/curve25519-donna and +// http://github.com/floodyberry/ed25519-donna. + +// Typically the key agreement classes encapsulate their data more +// than x25519 does below. They are a little more accessible +// due to crypto_box operations. + +/// \file xed25519.h +/// \brief Classes for x25519 and ed25519 operations +/// \details This implementation integrates Andrew Moon's public domain code +/// for curve25519-donna and ed25519-donna. +/// \details Moving keys into and out of the library proceeds as follows. +/// If an Integer class is accepted or returned, then the data is in big +/// endian format. That is, the MSB is at byte position 0, and the LSB +/// is at byte position 31. The Integer will work as expected, just like +/// an int or a long. +/// \details If a byte array is accepted, then the byte array is in little +/// endian format. That is, the LSB is at byte position 0, and the MSB is +/// at byte position 31. This follows the implementation where byte 0 is +/// clamed with 248. That is my_arr[0] &= 248 to mask the lower 3 bits. +/// \details PKCS8 and X509 keys encoded using ASN.1 follow little endian +/// arrays. The format is specified in draft-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 perfoming 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 perfoms 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 siganture + /// \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 siganture + /// \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() perfoms 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/external/ours/library/crypto/src/shared/original/xtr.cpp b/external/ours/library/crypto/src/shared/original/xtr.cpp new file mode 100755 index 000000000..fe49b1eaa --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/xtr.cpp @@ -0,0 +1,120 @@ +// xtr.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#include "xtr.h" +#include "nbtheory.h" +#include "integer.h" +#include "algebra.h" +#include "modarith.h" +#include "algebra.cpp" + +NAMESPACE_BEGIN(CryptoPP) + +const GFP2Element & GFP2Element::Zero() +{ +#if defined(CRYPTOPP_CXX11_STATIC_INIT) + static const GFP2Element s_zero; + return s_zero; +#else + return Singleton().Ref(); +#endif +} + +void XTR_FindPrimesAndGenerator(RandomNumberGenerator &rng, Integer &p, Integer &q, GFP2Element &g, unsigned int pbits, unsigned int qbits) +{ + CRYPTOPP_ASSERT(qbits > 9); // no primes exist for pbits = 10, qbits = 9 + CRYPTOPP_ASSERT(pbits > qbits); + + const Integer minQ = Integer::Power2(qbits - 1); + const Integer maxQ = Integer::Power2(qbits) - 1; + const Integer minP = Integer::Power2(pbits - 1); + const Integer maxP = Integer::Power2(pbits) - 1; + +top: + + Integer r1, r2; + do + { + (void)q.Randomize(rng, minQ, maxQ, Integer::PRIME, 7, 12); + // Solution always exists because q === 7 mod 12. + (void)SolveModularQuadraticEquation(r1, r2, 1, -1, 1, q); + // I believe k_i, r1 and r2 are being used slightly different than the + // paper's algorithm. I believe it is leading to the failed asserts. + // Just make the assert part of the condition. + if(!p.Randomize(rng, minP, maxP, Integer::PRIME, CRT(rng.GenerateBit() ? + r1 : r2, q, 2, 3, EuclideanMultiplicativeInverse(p, 3)), 3 * q)) { continue; } + } while (((p % 3U) != 2) || (((p.Squared() - p + 1) % q).NotZero())); + + // CRYPTOPP_ASSERT((p % 3U) == 2); + // CRYPTOPP_ASSERT(((p.Squared() - p + 1) % q).IsZero()); + + GFP2_ONB gfp2(p); + GFP2Element three = gfp2.ConvertIn(3), t; + + while (true) + { + g.c1.Randomize(rng, Integer::Zero(), p-1); + g.c2.Randomize(rng, Integer::Zero(), p-1); + t = XTR_Exponentiate(g, p+1, p); + if (t.c1 == t.c2) + continue; + g = XTR_Exponentiate(g, (p.Squared()-p+1)/q, p); + if (g != three) + break; + } + + if (XTR_Exponentiate(g, q, p) != three) + goto top; + + // CRYPTOPP_ASSERT(XTR_Exponentiate(g, q, p) == three); +} + +GFP2Element XTR_Exponentiate(const GFP2Element &b, const Integer &e, const Integer &p) +{ + unsigned int bitCount = e.BitCount(); + if (bitCount == 0) + return GFP2Element(-3, -3); + + // find the lowest bit of e that is 1 + unsigned int lowest1bit; + for (lowest1bit=0; e.GetBit(lowest1bit) == 0; lowest1bit++) {} + + GFP2_ONB gfp2(p); + GFP2Element c = gfp2.ConvertIn(b); + GFP2Element cp = gfp2.PthPower(c); + GFP2Element S[5] = {gfp2.ConvertIn(3), c, gfp2.SpecialOperation1(c)}; + + // do all exponents bits except the lowest zeros starting from the top + unsigned int i; + for (i = e.BitCount() - 1; i>lowest1bit; i--) + { + if (e.GetBit(i)) + { + gfp2.RaiseToPthPower(S[0]); + gfp2.Accumulate(S[0], gfp2.SpecialOperation2(S[2], c, S[1])); + S[1] = gfp2.SpecialOperation1(S[1]); + S[2] = gfp2.SpecialOperation1(S[2]); + S[0].swap(S[1]); + } + else + { + gfp2.RaiseToPthPower(S[2]); + gfp2.Accumulate(S[2], gfp2.SpecialOperation2(S[0], cp, S[1])); + S[1] = gfp2.SpecialOperation1(S[1]); + S[0] = gfp2.SpecialOperation1(S[0]); + S[2].swap(S[1]); + } + } + + // now do the lowest zeros + while (i--) + S[1] = gfp2.SpecialOperation1(S[1]); + + return gfp2.ConvertOut(S[1]); +} + +template class AbstractRing; +template class AbstractGroup; + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/xtr.h b/external/ours/library/crypto/src/shared/original/xtr.h new file mode 100755 index 000000000..29479d8ca --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/xtrcrypt.cpp b/external/ours/library/crypto/src/shared/original/xtrcrypt.cpp new file mode 100755 index 000000000..aa106aa44 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/xtrcrypt.cpp @@ -0,0 +1,122 @@ +// xtrcrypt.cpp - originally written and placed in the public domain by Wei Dai + +#include "pch.h" + +#include "asn.h" +#include "integer.h" +#include "xtrcrypt.h" +#include "nbtheory.h" +#include "modarith.h" +#include "argnames.h" + +NAMESPACE_BEGIN(CryptoPP) + +XTR_DH::XTR_DH(const Integer &p, const Integer &q, const GFP2Element &g) + : m_p(p), m_q(q), m_g(g) +{ +} + +XTR_DH::XTR_DH(RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits) +{ + XTR_FindPrimesAndGenerator(rng, m_p, m_q, m_g, pbits, qbits); +} + +XTR_DH::XTR_DH(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + m_p.BERDecode(seq); + m_q.BERDecode(seq); + m_g.c1.BERDecode(seq); + m_g.c2.BERDecode(seq); + seq.MessageEnd(); +} + +void XTR_DH::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + m_p.DEREncode(seq); + m_q.DEREncode(seq); + m_g.c1.DEREncode(seq); + m_g.c2.DEREncode(seq); + seq.MessageEnd(); +} + +bool XTR_DH::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = true; + pass = pass && m_p > Integer::One() && m_p.IsOdd(); + CRYPTOPP_ASSERT(pass); + pass = pass && m_q > Integer::One() && m_q.IsOdd(); + CRYPTOPP_ASSERT(pass); + GFP2Element three = GFP2_ONB(m_p).ConvertIn(3); + CRYPTOPP_ASSERT(pass); + pass = pass && !(m_g.c1.IsNegative() || m_g.c2.IsNegative() || m_g.c1 >= m_p || m_g.c2 >= m_p || m_g == three); + CRYPTOPP_ASSERT(pass); + if (level >= 1) + { + pass = pass && ((m_p.Squared()-m_p+1)%m_q).IsZero(); + CRYPTOPP_ASSERT(pass); + } + if (level >= 2) + { + pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2); + CRYPTOPP_ASSERT(pass); + pass = pass && XTR_Exponentiate(m_g, (m_p.Squared()-m_p+1)/m_q, m_p) != three; + CRYPTOPP_ASSERT(pass); + pass = pass && XTR_Exponentiate(m_g, m_q, m_p) == three; + CRYPTOPP_ASSERT(pass); + } + return pass; +} + +bool XTR_DH::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder) + CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator) + ; +} + +void XTR_DH::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder) + CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupGenerator) + ; +} + +void XTR_DH::GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const +{ + Integer x(rng, Integer::Zero(), m_q-1); + x.Encode(privateKey, PrivateKeyLength()); +} + +void XTR_DH::GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const +{ + CRYPTOPP_UNUSED(rng); + Integer x(privateKey, PrivateKeyLength()); + GFP2Element y = XTR_Exponentiate(m_g, x, m_p); + y.Encode(publicKey, PublicKeyLength()); +} + +bool XTR_DH::Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey) const +{ + GFP2Element w(otherPublicKey, PublicKeyLength()); + if (validateOtherPublicKey) + { + GFP2_ONB gfp2(m_p); + GFP2Element three = gfp2.ConvertIn(3); + if (w.c1.IsNegative() || w.c2.IsNegative() || w.c1 >= m_p || w.c2 >= m_p || w == three) + return false; + if (XTR_Exponentiate(w, m_q, m_p) != three) + return false; + } + Integer s(privateKey, PrivateKeyLength()); + GFP2Element z = XTR_Exponentiate(w, s, m_p); + z.Encode(agreedValue, AgreedValueLength()); + return true; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/xtrcrypt.h b/external/ours/library/crypto/src/shared/original/xtrcrypt.h new file mode 100755 index 000000000..64c9430ba --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/xts.cpp b/external/ours/library/crypto/src/shared/original/xts.cpp new file mode 100755 index 000000000..27fbf76cd --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/xts.cpp @@ -0,0 +1,512 @@ +// xts.cpp - written and placed in the public domain by Jeffrey Walton + +// Aarch32, Aarch64, Altivec and X86_64 include SIMD as part of the +// base architecture. We can use the SIMD code below without an +// architecture option. No runtime tests are required. Unfortunately, +// we can't use it on Altivec because an architecture switch is required. +// The updated XorBuffer gains 0.3 to 1.5 cpb on the architectures for +// 16-byte block sizes. + +#include "pch.h" + +#include "xts.h" +#include "misc.h" +#include "modes.h" +#include "cpu.h" + +#if defined(CRYPTOPP_DEBUG) +# include "aes.h" +# include "threefish.h" +#endif + +// 0.3 to 0.4 cpb profit +#if defined(__SSE2__) || defined(_M_X64) +# include +#endif + +#if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64) +# if (CRYPTOPP_ARM_NEON_HEADER) +# include +# endif +#endif + +#if defined(__ALTIVEC__) +# include "ppc_simd.h" +#endif + +ANONYMOUS_NAMESPACE_BEGIN + +using namespace CryptoPP; + +#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) + +using CryptoPP::AES; +using CryptoPP::XTS_Mode; +using CryptoPP::Threefish512; + +void Modes_TestInstantiations() +{ + XTS_Mode::Encryption m0; + XTS_Mode::Decryption m1; + XTS_Mode::Encryption m2; + XTS_Mode::Decryption m3; + +#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS + XTS_Mode::Encryption m4; + XTS_Mode::Decryption m5; +#endif +} +#endif // CRYPTOPP_DEBUG + +inline void XorBuffer(byte *output, const byte *input, const byte *mask, size_t count) +{ + CRYPTOPP_ASSERT(count >= 16 && (count % 16 == 0)); + +#if defined(CRYPTOPP_DISABLE_ASM) + xorbuf(output, input, mask, count); + +#elif defined(__SSE2__) || defined(_M_X64) + for (size_t i=0; i(false, LITTLE_ENDIAN_ORDER, in+idx); + word64 y = (x >> 63); x = (x << 1) + carry; + PutWord(false, LITTLE_ENDIAN_ORDER, out+idx, x); + carry = y; + } +#else + word32 carry = 0, x; + for (size_t i=0, idx=0; i(false, LITTLE_ENDIAN_ORDER, in+idx); + word32 y = (x >> 31); x = (x << 1) + carry; + PutWord(false, LITTLE_ENDIAN_ORDER, out+idx, x); + carry = y; + } +#endif + +#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS + + CRYPTOPP_ASSERT(IsPowerOf2(len)); + CRYPTOPP_ASSERT(len >= 16); + CRYPTOPP_ASSERT(len <= 128); + + byte* k = out; + if (carry) + { + switch (len) + { + case 16: + { + const size_t LEIDX = 16-1; + k[LEIDX-15] ^= 0x87; + break; + } + case 32: + { + // https://crypto.stackexchange.com/q/9815/10496 + // Polynomial x^256 + x^10 + x^5 + x^2 + 1 + const size_t LEIDX = 32-1; + k[LEIDX-30] ^= 4; + k[LEIDX-31] ^= 0x25; + break; + } + case 64: + { + // https://crypto.stackexchange.com/q/9815/10496 + // Polynomial x^512 + x^8 + x^5 + x^2 + 1 + const size_t LEIDX = 64-1; + k[LEIDX-62] ^= 1; + k[LEIDX-63] ^= 0x25; + break; + } + case 128: + { + // https://crypto.stackexchange.com/q/9815/10496 + // Polynomial x^1024 + x^19 + x^6 + x + 1 + const size_t LEIDX = 128-1; + k[LEIDX-125] ^= 8; + k[LEIDX-126] ^= 0x00; + k[LEIDX-127] ^= 0x43; + break; + } + default: + CRYPTOPP_ASSERT(0); + } + } +#else + CRYPTOPP_ASSERT(len == 16); + + byte* k = out; + if (carry) + { + k[0] ^= 0x87; + return; + } +#endif // CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS +} + +inline void GF_Double(byte *inout, unsigned int len) +{ + GF_Double(inout, inout, len); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void XTS_ModeBase::ThrowIfInvalidBlockSize(size_t length) +{ +#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS + CRYPTOPP_ASSERT(length >= 16 && length <= 128 && IsPowerOf2(length)); + if (length < 16 || length > 128 || !IsPowerOf2(length)) + throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not valid"); +#else + CRYPTOPP_ASSERT(length == 16); + if (length != 16) + throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16"); +#endif +} + +void XTS_ModeBase::ThrowIfInvalidKeyLength(size_t length) +{ + CRYPTOPP_ASSERT(length % 2 == 0); + if (!GetBlockCipher().IsValidKeyLength((length+1)/2)) + throw InvalidKeyLength(AlgorithmName(), length); +} + +void XTS_ModeBase::SetKey(const byte *key, size_t length, const NameValuePairs ¶ms) +{ + ThrowIfInvalidKeyLength(length); + ThrowIfInvalidBlockSize(BlockSize()); + + const size_t klen = length/2; + AccessBlockCipher().SetKey(key+0, klen, params); + AccessTweakCipher().SetKey(key+klen, klen, params); + + ResizeBuffers(); + + size_t ivLength; + const byte *iv = GetIVAndThrowIfInvalid(params, ivLength); + Resynchronize(iv, (int)ivLength); +} + +void XTS_ModeBase::Resynchronize(const byte *iv, int ivLength) +{ + BlockOrientedCipherModeBase::Resynchronize(iv, ivLength); + std::memcpy(m_xregister, m_register, ivLength); + GetTweakCipher().ProcessBlock(m_xregister); +} + +void XTS_ModeBase::Resynchronize(word64 sector, ByteOrder order) +{ + SecByteBlock iv(GetTweakCipher().BlockSize()); + PutWord(false, order, iv, sector); + std::memset(iv+8, 0x00, iv.size()-8); + + BlockOrientedCipherModeBase::Resynchronize(iv, (int)iv.size()); + std::memcpy(m_xregister, iv, iv.size()); + GetTweakCipher().ProcessBlock(m_xregister); +} + +void XTS_ModeBase::ResizeBuffers() +{ + BlockOrientedCipherModeBase::ResizeBuffers(); + m_xworkspace.New(GetBlockCipher().BlockSize()*ParallelBlocks); + m_xregister.New(GetBlockCipher().BlockSize()*ParallelBlocks); +} + +// ProcessData runs either 12-4-1 blocks, 8-2-1 or 4-1 blocks. Which is +// selected depends on ParallelBlocks in the header file. 12-4-1 or 8-2-1 +// can be used on Aarch64 and PowerPC. Intel should use 4-1 due to lack +// of registers. The unneeded code paths should be removed by optimizer. +// The extra gyrations save us 1.8 cpb on Aarch64 and 2.1 cpb on PowerPC. +void XTS_ModeBase::ProcessData(byte *outString, const byte *inString, size_t length) +{ + // data unit is multiple of 16 bytes + CRYPTOPP_ASSERT(length % BlockSize() == 0); + + enum { lastParallelBlock = ParallelBlocks-1 }; + const unsigned int blockSize = GetBlockCipher().BlockSize(); + const size_t parallelSize = blockSize*ParallelBlocks; + + // encrypt the data unit, optimal size at a time + while (length >= parallelSize) + { + // m_xregister[0] always points to the next tweak. + GF_Double(m_xregister+1*blockSize, m_xregister+0*blockSize, blockSize); + GF_Double(m_xregister+2*blockSize, m_xregister+1*blockSize, blockSize); + GF_Double(m_xregister+3*blockSize, m_xregister+2*blockSize, blockSize); + + if (ParallelBlocks > 4) + { + GF_Double(m_xregister+4*blockSize, m_xregister+3*blockSize, blockSize); + GF_Double(m_xregister+5*blockSize, m_xregister+4*blockSize, blockSize); + GF_Double(m_xregister+6*blockSize, m_xregister+5*blockSize, blockSize); + GF_Double(m_xregister+7*blockSize, m_xregister+6*blockSize, blockSize); + } + if (ParallelBlocks > 8) + { + GF_Double(m_xregister+8*blockSize, m_xregister+7*blockSize, blockSize); + GF_Double(m_xregister+9*blockSize, m_xregister+8*blockSize, blockSize); + GF_Double(m_xregister+10*blockSize, m_xregister+9*blockSize, blockSize); + GF_Double(m_xregister+11*blockSize, m_xregister+10*blockSize, blockSize); + } + + // merge the tweak into the input block + XorBuffer(m_xworkspace, inString, m_xregister, parallelSize); + + // encrypt one block, merge the tweak into the output block + GetBlockCipher().AdvancedProcessBlocks(m_xworkspace, m_xregister, + outString, parallelSize, BlockTransformation::BT_AllowParallel); + + // m_xregister[0] always points to the next tweak. + GF_Double(m_xregister+0, m_xregister+lastParallelBlock*blockSize, blockSize); + + inString += parallelSize; + outString += parallelSize; + length -= parallelSize; + } + + // encrypt the data unit, 4 blocks at a time + while (ParallelBlocks == 12 && length >= blockSize*4) + { + // m_xregister[0] always points to the next tweak. + GF_Double(m_xregister+1*blockSize, m_xregister+0*blockSize, blockSize); + GF_Double(m_xregister+2*blockSize, m_xregister+1*blockSize, blockSize); + GF_Double(m_xregister+3*blockSize, m_xregister+2*blockSize, blockSize); + + // merge the tweak into the input block + XorBuffer(m_xworkspace, inString, m_xregister, blockSize*4); + + // encrypt one block, merge the tweak into the output block + GetBlockCipher().AdvancedProcessBlocks(m_xworkspace, m_xregister, + outString, blockSize*4, BlockTransformation::BT_AllowParallel); + + // m_xregister[0] always points to the next tweak. + GF_Double(m_xregister+0, m_xregister+3*blockSize, blockSize); + + inString += blockSize*4; + outString += blockSize*4; + length -= blockSize*4; + } + + // encrypt the data unit, 2 blocks at a time + while (ParallelBlocks == 8 && length >= blockSize*2) + { + // m_xregister[0] always points to the next tweak. + GF_Double(m_xregister+1*blockSize, m_xregister+0*blockSize, blockSize); + + // merge the tweak into the input block + XorBuffer(m_xworkspace, inString, m_xregister, blockSize*2); + + // encrypt one block, merge the tweak into the output block + GetBlockCipher().AdvancedProcessBlocks(m_xworkspace, m_xregister, + outString, blockSize*2, BlockTransformation::BT_AllowParallel); + + // m_xregister[0] always points to the next tweak. + GF_Double(m_xregister+0, m_xregister+1*blockSize, blockSize); + + inString += blockSize*2; + outString += blockSize*2; + length -= blockSize*2; + } + + // encrypt the data unit, blocksize at a time + while (length) + { + // merge the tweak into the input block + XorBuffer(m_xworkspace, inString, m_xregister, blockSize); + + // encrypt one block + GetBlockCipher().ProcessBlock(m_xworkspace); + + // merge the tweak into the output block + XorBuffer(outString, m_xworkspace, m_xregister, blockSize); + + // Multiply T by alpha + GF_Double(m_xregister, blockSize); + + inString += blockSize; + outString += blockSize; + length -= blockSize; + } +} + +size_t XTS_ModeBase::ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength) +{ + // need at least a full AES block + CRYPTOPP_ASSERT(inLength >= BlockSize()); + + if (inLength < BlockSize()) + throw InvalidArgument("XTS: message is too short for ciphertext stealing"); + + if (IsForwardTransformation()) + return ProcessLastPlainBlock(outString, outLength, inString, inLength); + else + return ProcessLastCipherBlock(outString, outLength, inString, inLength); +} + +size_t XTS_ModeBase::ProcessLastPlainBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength) +{ + // ensure output buffer is large enough + CRYPTOPP_ASSERT(outLength >= inLength); + + const unsigned int blockSize = GetBlockCipher().BlockSize(); + const size_t blocks = inLength / blockSize; + const size_t tail = inLength % blockSize; + outLength = inLength; + + if (tail == 0) + { + // Allow ProcessData to handle all the full blocks + ProcessData(outString, inString, inLength); + return inLength; + } + else if (blocks > 1) + { + // Allow ProcessData to handle full blocks except one + const size_t head = (blocks-1)*blockSize; + ProcessData(outString, inString, inLength-head); + + outString += head; + inString += head; inLength -= head; + } + + ///// handle the full block ///// + + // merge the tweak into the input block + XorBuffer(m_xworkspace, inString, m_xregister, blockSize); + + // encrypt one block + GetBlockCipher().ProcessBlock(m_xworkspace); + + // merge the tweak into the output block + XorBuffer(outString, m_xworkspace, m_xregister, blockSize); + + // Multiply T by alpha + GF_Double(m_xregister, blockSize); + + ///// handle final partial block ///// + + inString += blockSize; + outString += blockSize; + const size_t len = inLength-blockSize; + + // copy in the final plaintext bytes + std::memcpy(m_xworkspace, inString, len); + // and copy out the final ciphertext bytes + std::memcpy(outString, outString-blockSize, len); + // "steal" ciphertext to complete the block + std::memcpy(m_xworkspace+len, outString-blockSize+len, blockSize-len); + + // merge the tweak into the input block + XorBuffer(m_xworkspace, m_xregister, blockSize); + + // encrypt one block + GetBlockCipher().ProcessBlock(m_xworkspace); + + // merge the tweak into the previous output block + XorBuffer(outString-blockSize, m_xworkspace, m_xregister, blockSize); + + return outLength; +} + +size_t XTS_ModeBase::ProcessLastCipherBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength) +{ + // ensure output buffer is large enough + CRYPTOPP_ASSERT(outLength >= inLength); + + const unsigned int blockSize = GetBlockCipher().BlockSize(); + const size_t blocks = inLength / blockSize; + const size_t tail = inLength % blockSize; + outLength = inLength; + + if (tail == 0) + { + // Allow ProcessData to handle all the full blocks + ProcessData(outString, inString, inLength); + return inLength; + } + else if (blocks > 1) + { + // Allow ProcessData to handle full blocks except one + const size_t head = (blocks-1)*blockSize; + ProcessData(outString, inString, inLength-head); + + outString += head; + inString += head; inLength -= head; + } + + #define poly1 (m_xregister+0*blockSize) + #define poly2 (m_xregister+1*blockSize) + GF_Double(poly2, poly1, blockSize); + + ///// handle final partial block ///// + + inString += blockSize; + outString += blockSize; + const size_t len = inLength-blockSize; + + // merge the tweak into the input block + XorBuffer(m_xworkspace, inString-blockSize, poly2, blockSize); + + // encrypt one block + GetBlockCipher().ProcessBlock(m_xworkspace); + + // merge the tweak into the output block + XorBuffer(m_xworkspace, poly2, blockSize); + + // copy in the final plaintext bytes + std::memcpy(outString-blockSize, inString, len); + // and copy out the final ciphertext bytes + std::memcpy(outString, m_xworkspace, len); + // "steal" ciphertext to complete the block + std::memcpy(outString-blockSize+len, m_xworkspace+len, blockSize-len); + + ///// handle the full previous block ///// + + inString -= blockSize; + outString -= blockSize; + + // merge the tweak into the input block + XorBuffer(m_xworkspace, outString, poly1, blockSize); + + // encrypt one block + GetBlockCipher().ProcessBlock(m_xworkspace); + + // merge the tweak into the output block + XorBuffer(outString, m_xworkspace, poly1, blockSize); + + return outLength; +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/xts.h b/external/ours/library/crypto/src/shared/original/xts.h new file mode 100755 index 000000000..4ac70e3ed --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/zdeflate.cpp b/external/ours/library/crypto/src/shared/original/zdeflate.cpp new file mode 100755 index 000000000..44413ab5e --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/zdeflate.cpp @@ -0,0 +1,821 @@ +// zdeflate.cpp - originally written and placed in the public domain by Wei Dai + +// Many of the algorithms and tables used here came from the deflate implementation +// by Jean-loup Gailly, which was included in Crypto++ 4.0 and earlier. I completely +// rewrote it in order to fix a bug that I could not figure out. This code +// is less clever, but hopefully more understandable and maintainable. + +#include "pch.h" +#include "zdeflate.h" +#include "stdcpp.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if (defined(_MSC_VER) && (_MSC_VER < 1400)) && !defined(__MWERKS__) + // VC60 and VC7 workaround: built-in std::reverse_iterator has two template parameters, Dinkumware only has one + typedef std::reverse_bidirectional_iterator RevIt; +#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) + typedef std::reverse_iterator RevIt; +#else + typedef std::reverse_iterator RevIt; +#endif + +LowFirstBitWriter::LowFirstBitWriter(BufferedTransformation *attachment) + : Filter(attachment), m_counting(false), m_bitCount(0), m_buffer(0) + , m_bitsBuffered(0), m_bytesBuffered(0) +{ +} + +void LowFirstBitWriter::StartCounting() +{ + CRYPTOPP_ASSERT(!m_counting); + m_counting = true; + m_bitCount = 0; +} + +unsigned long LowFirstBitWriter::FinishCounting() +{ + CRYPTOPP_ASSERT(m_counting); + m_counting = false; + return m_bitCount; +} + +void LowFirstBitWriter::PutBits(unsigned long value, unsigned int length) +{ + if (m_counting) + m_bitCount += length; + else + { + m_buffer |= value << m_bitsBuffered; + m_bitsBuffered += length; + CRYPTOPP_ASSERT(m_bitsBuffered <= sizeof(unsigned long)*8); + while (m_bitsBuffered >= 8) + { + m_outputBuffer[m_bytesBuffered++] = (byte)m_buffer; + if (m_bytesBuffered == m_outputBuffer.size()) + { + AttachedTransformation()->PutModifiable(m_outputBuffer, m_bytesBuffered); + m_bytesBuffered = 0; + } + m_buffer >>= 8; + m_bitsBuffered -= 8; + } + } +} + +void LowFirstBitWriter::FlushBitBuffer() +{ + if (m_counting) + m_bitCount += 8*(m_bitsBuffered > 0); + else + { + if (m_bytesBuffered > 0) + { + AttachedTransformation()->PutModifiable(m_outputBuffer, m_bytesBuffered); + m_bytesBuffered = 0; + } + if (m_bitsBuffered > 0) + { + AttachedTransformation()->Put((byte)m_buffer); + m_buffer = 0; + m_bitsBuffered = 0; + } + } +} + +void LowFirstBitWriter::ClearBitBuffer() +{ + m_buffer = 0; + m_bytesBuffered = 0; + m_bitsBuffered = 0; +} + +HuffmanEncoder::HuffmanEncoder(const unsigned int *codeBits, unsigned int nCodes) +{ + Initialize(codeBits, nCodes); +} + +struct HuffmanNode +{ + HuffmanNode() + : symbol(0), parent(0) {} + HuffmanNode(const HuffmanNode& rhs) + : symbol(rhs.symbol), parent(rhs.parent) {} + HuffmanNode& operator=(const HuffmanNode& rhs) + { + // No this guard + symbol = rhs.symbol; + parent = rhs.parent; + return *this; + } + + size_t symbol; + union {size_t parent; unsigned depth, freq;}; +}; + +struct FreqLessThan +{ + inline bool operator()(unsigned int lhs, const HuffmanNode &rhs) {return lhs < rhs.freq;} + inline bool operator()(const HuffmanNode &lhs, const HuffmanNode &rhs) const {return lhs.freq < rhs.freq;} + // needed for MSVC .NET 2005 + inline bool operator()(const HuffmanNode &lhs, unsigned int rhs) {return lhs.freq < rhs;} +}; + +void HuffmanEncoder::GenerateCodeLengths(unsigned int *codeBits, unsigned int maxCodeBits, const unsigned int *codeCounts, size_t nCodes) +{ + CRYPTOPP_ASSERT(nCodes > 0); + CRYPTOPP_ASSERT(nCodes <= ((size_t)1 << maxCodeBits)); + + size_t i; + SecBlockWithHint tree(nCodes); + for (i=0; i= 2) + for (i=tree.size()-2; i>=nCodes; i--) + tree[i].depth = tree[tree[i].parent].depth + 1; + unsigned int sum = 0; + SecBlockWithHint blCount(maxCodeBits+1); + std::fill(blCount.begin(), blCount.end(), 0); + for (i=treeBegin; i (unsigned int)(1 << maxCodeBits) ? sum - (1 << maxCodeBits) : 0; + + while (overflow--) + { + unsigned int bits = maxCodeBits-1; + while (blCount[bits] == 0) + bits--; + blCount[bits]--; + blCount[bits+1] += 2; + CRYPTOPP_ASSERT(blCount[maxCodeBits] > 0); + blCount[maxCodeBits]--; + } + + for (i=0; i 0); + unsigned int maxCodeBits = *std::max_element(codeBits, codeBits+nCodes); + if (maxCodeBits == 0) + return; // assume this object won't be used + + SecBlockWithHint blCount(maxCodeBits+1); + std::fill(blCount.begin(), blCount.end(), 0); + unsigned int i; + for (i=0; i nextCode(maxCodeBits+1); + nextCode[1] = 0; + for (i=2; i<=maxCodeBits; i++) + { + code = (code + blCount[i-1]) << 1; + nextCode[i] = code; + } + CRYPTOPP_ASSERT(maxCodeBits == 1 || code == (1 << maxCodeBits) - blCount[maxCodeBits]); + + m_valueToCode.resize(nCodes); + for (i=0; i> (8*sizeof(code_t)-len); + } +} + +inline void HuffmanEncoder::Encode(LowFirstBitWriter &writer, value_t value) const +{ + CRYPTOPP_ASSERT(m_valueToCode[value].len > 0); + writer.PutBits(m_valueToCode[value].code, m_valueToCode[value].len); +} + +Deflator::Deflator(BufferedTransformation *attachment, int deflateLevel, int log2WindowSize, bool detectUncompressible) + : LowFirstBitWriter(attachment) + , m_deflateLevel(-1) +{ + InitializeStaticEncoders(); + Deflator::IsolatedInitialize(MakeParameters("DeflateLevel", deflateLevel)("Log2WindowSize", log2WindowSize)("DetectUncompressible", detectUncompressible)); +} + +Deflator::Deflator(const NameValuePairs ¶meters, BufferedTransformation *attachment) + : LowFirstBitWriter(attachment) + , m_deflateLevel(-1) +{ + InitializeStaticEncoders(); + Deflator::IsolatedInitialize(parameters); +} + +void Deflator::InitializeStaticEncoders() +{ + unsigned int codeLengths[288]; + std::fill(codeLengths + 0, codeLengths + 144, 8); + std::fill(codeLengths + 144, codeLengths + 256, 9); + std::fill(codeLengths + 256, codeLengths + 280, 7); + std::fill(codeLengths + 280, codeLengths + 288, 8); + m_staticLiteralEncoder.Initialize(codeLengths, 288); + std::fill(codeLengths + 0, codeLengths + 32, 5); + m_staticDistanceEncoder.Initialize(codeLengths, 32); +} + +void Deflator::IsolatedInitialize(const NameValuePairs ¶meters) +{ + int log2WindowSize = parameters.GetIntValueWithDefault("Log2WindowSize", DEFAULT_LOG2_WINDOW_SIZE); + if (!(MIN_LOG2_WINDOW_SIZE <= log2WindowSize && log2WindowSize <= MAX_LOG2_WINDOW_SIZE)) + throw InvalidArgument("Deflator: " + IntToString(log2WindowSize) + " is an invalid window size"); + + m_log2WindowSize = log2WindowSize; + DSIZE = 1 << m_log2WindowSize; + DMASK = DSIZE - 1; + HSIZE = 1 << m_log2WindowSize; + HMASK = HSIZE - 1; + m_byteBuffer.New(2*DSIZE); + m_head.New(HSIZE); + m_prev.New(DSIZE); + m_matchBuffer.New(DSIZE/2); + Reset(true); + + const int deflateLevel = parameters.GetIntValueWithDefault("DeflateLevel", DEFAULT_DEFLATE_LEVEL); + CRYPTOPP_ASSERT(deflateLevel >= MIN_DEFLATE_LEVEL /*0*/ && deflateLevel <= MAX_DEFLATE_LEVEL /*9*/); + SetDeflateLevel(deflateLevel); + bool detectUncompressible = parameters.GetValueWithDefault("DetectUncompressible", true); + m_compressibleDeflateLevel = detectUncompressible ? m_deflateLevel : 0; +} + +void Deflator::Reset(bool forceReset) +{ + if (forceReset) + ClearBitBuffer(); + else + CRYPTOPP_ASSERT(m_bitsBuffered == 0); + + m_headerWritten = false; + m_matchAvailable = false; + m_dictionaryEnd = 0; + m_stringStart = 0; + m_lookahead = 0; + m_minLookahead = MAX_MATCH; + m_matchBufferEnd = 0; + m_blockStart = 0; + m_blockLength = 0; + + m_detectCount = 1; + m_detectSkip = 0; + + // m_prev will be initialized automatically in InsertString + std::fill(m_head.begin(), m_head.end(), byte(0)); + + std::fill(m_literalCounts.begin(), m_literalCounts.end(), byte(0)); + std::fill(m_distanceCounts.begin(), m_distanceCounts.end(), byte(0)); +} + +void Deflator::SetDeflateLevel(int deflateLevel) +{ + if (!(MIN_DEFLATE_LEVEL <= deflateLevel && deflateLevel <= MAX_DEFLATE_LEVEL)) + throw InvalidArgument("Deflator: " + IntToString(deflateLevel) + " is an invalid deflate level"); + + if (deflateLevel == m_deflateLevel) + return; + + EndBlock(false); + + static const unsigned int configurationTable[10][4] = { + /* good lazy nice chain */ + /* 0 */ {0, 0, 0, 0}, /* store only */ + /* 1 */ {4, 3, 8, 4}, /* maximum speed, no lazy matches */ + /* 2 */ {4, 3, 16, 8}, + /* 3 */ {4, 3, 32, 32}, + /* 4 */ {4, 4, 16, 16}, /* lazy matches */ + /* 5 */ {8, 16, 32, 32}, + /* 6 */ {8, 16, 128, 128}, + /* 7 */ {8, 32, 128, 256}, + /* 8 */ {32, 128, 258, 1024}, + /* 9 */ {32, 258, 258, 4096}}; /* maximum compression */ + + GOOD_MATCH = configurationTable[deflateLevel][0]; + MAX_LAZYLENGTH = configurationTable[deflateLevel][1]; + MAX_CHAIN_LENGTH = configurationTable[deflateLevel][3]; + + m_deflateLevel = deflateLevel; +} + +unsigned int Deflator::FillWindow(const byte *str, size_t length) +{ + unsigned int maxBlockSize = (unsigned int)STDMIN(2UL*DSIZE, 0xffffUL); + + if (m_stringStart >= maxBlockSize - MAX_MATCH) + { + if (m_blockStart < DSIZE) + EndBlock(false); + + memcpy(m_byteBuffer, m_byteBuffer + DSIZE, DSIZE); + + m_dictionaryEnd = m_dictionaryEnd < DSIZE ? 0 : m_dictionaryEnd-DSIZE; + CRYPTOPP_ASSERT(m_stringStart >= DSIZE); + m_stringStart -= DSIZE; + CRYPTOPP_ASSERT(!m_matchAvailable || m_previousMatch >= DSIZE); + m_previousMatch -= DSIZE; + CRYPTOPP_ASSERT(m_blockStart >= DSIZE); + m_blockStart -= DSIZE; + + // These are set to the same value in IsolatedInitialize(). If they + // are the same, then we can clear a Coverity false alarm. + CRYPTOPP_ASSERT(DSIZE == HSIZE); + + unsigned int i; + for (i=0; i m_stringStart+m_lookahead); + unsigned int accepted = UnsignedMin(maxBlockSize-(m_stringStart+m_lookahead), length); + CRYPTOPP_ASSERT(accepted > 0); + memcpy(m_byteBuffer + m_stringStart + m_lookahead, str, accepted); + m_lookahead += accepted; + return accepted; +} + +inline unsigned int Deflator::ComputeHash(const byte *str) const +{ + CRYPTOPP_ASSERT(str+3 <= m_byteBuffer + m_stringStart + m_lookahead); + return ((str[0] << 10) ^ (str[1] << 5) ^ str[2]) & HMASK; +} + +unsigned int Deflator::LongestMatch(unsigned int &bestMatch) const +{ + CRYPTOPP_ASSERT(m_previousLength < MAX_MATCH); + + bestMatch = 0; + unsigned int bestLength = STDMAX(m_previousLength, (unsigned int)MIN_MATCH-1); + if (m_lookahead <= bestLength) + return 0; + + const byte *scan = m_byteBuffer + m_stringStart, *scanEnd = scan + STDMIN((unsigned int)MAX_MATCH, m_lookahead); + unsigned int limit = m_stringStart > (DSIZE-MAX_MATCH) ? m_stringStart - (DSIZE-MAX_MATCH) : 0; + unsigned int current = m_head[ComputeHash(scan)]; + + unsigned int chainLength = MAX_CHAIN_LENGTH; + if (m_previousLength >= GOOD_MATCH) + chainLength >>= 2; + + while (current > limit && --chainLength > 0) + { + const byte *match = m_byteBuffer + current; + CRYPTOPP_ASSERT(scan + bestLength < m_byteBuffer + m_stringStart + m_lookahead); + if (scan[bestLength-1] == match[bestLength-1] && scan[bestLength] == match[bestLength] && scan[0] == match[0] && scan[1] == match[1]) + { + CRYPTOPP_ASSERT(scan[2] == match[2]); + unsigned int len = (unsigned int)( +#if defined(_STDEXT_BEGIN) && !(defined(_MSC_VER) && (_MSC_VER < 1400 || _MSC_VER >= 1600)) && !defined(_STLPORT_VERSION) + stdext::unchecked_mismatch +#else + std::mismatch +#endif +#if _MSC_VER >= 1600 + (stdext::make_unchecked_array_iterator(scan)+3, stdext::make_unchecked_array_iterator(scanEnd), stdext::make_unchecked_array_iterator(match)+3).first - stdext::make_unchecked_array_iterator(scan)); +#else + (scan+3, scanEnd, match+3).first - scan); +#endif + CRYPTOPP_ASSERT(len != bestLength); + if (len > bestLength) + { + bestLength = len; + bestMatch = current; + + CRYPTOPP_ASSERT(scanEnd >= scan); + if (len == (unsigned int)(scanEnd - scan)) + break; + } + } + current = m_prev[current & DMASK]; + } + return (bestMatch > 0) ? bestLength : 0; +} + +inline void Deflator::InsertString(unsigned int start) +{ + CRYPTOPP_ASSERT(start <= 0xffff); + unsigned int hash = ComputeHash(m_byteBuffer + start); + m_prev[start & DMASK] = m_head[hash]; + m_head[hash] = word16(start); +} + +void Deflator::ProcessBuffer() +{ + if (!m_headerWritten) + { + WritePrestreamHeader(); + m_headerWritten = true; + } + + if (m_deflateLevel == 0) + { + m_stringStart += m_lookahead; + m_lookahead = 0; + m_blockLength = m_stringStart - m_blockStart; + m_matchAvailable = false; + return; + } + + while (m_lookahead > m_minLookahead) + { + while (m_dictionaryEnd < m_stringStart && m_dictionaryEnd+3 <= m_stringStart+m_lookahead) + InsertString(m_dictionaryEnd++); + + if (m_matchAvailable) + { + unsigned int matchPosition = 0, matchLength = 0; + bool usePreviousMatch; + if (m_previousLength >= MAX_LAZYLENGTH) + usePreviousMatch = true; + else + { + matchLength = LongestMatch(matchPosition); + usePreviousMatch = (matchLength == 0); + } + if (usePreviousMatch) + { + MatchFound(m_stringStart-1-m_previousMatch, m_previousLength); + m_stringStart += m_previousLength-1; + m_lookahead -= m_previousLength-1; + m_matchAvailable = false; + } + else + { + m_previousLength = matchLength; + m_previousMatch = matchPosition; + LiteralByte(m_byteBuffer[m_stringStart-1]); + m_stringStart++; + m_lookahead--; + } + } + else + { + m_previousLength = 0; + m_previousLength = LongestMatch(m_previousMatch); + if (m_previousLength) + m_matchAvailable = true; + else + LiteralByte(m_byteBuffer[m_stringStart]); + m_stringStart++; + m_lookahead--; + } + + CRYPTOPP_ASSERT(m_stringStart - (m_blockStart+m_blockLength) == (unsigned int)m_matchAvailable); + } + + if (m_minLookahead == 0 && m_matchAvailable) + { + LiteralByte(m_byteBuffer[m_stringStart-1]); + m_matchAvailable = false; + } +} + +size_t Deflator::Put2(const byte *str, size_t length, int messageEnd, bool blocking) +{ + if (!blocking) + throw BlockingInputOnly("Deflator"); + + size_t accepted = 0; + while (accepted < length) + { + unsigned int newAccepted = FillWindow(str+accepted, length-accepted); + ProcessBuffer(); + // call ProcessUncompressedData() after WritePrestreamHeader() + ProcessUncompressedData(str+accepted, newAccepted); + accepted += newAccepted; + } + CRYPTOPP_ASSERT(accepted == length); + + if (messageEnd) + { + m_minLookahead = 0; + ProcessBuffer(); + EndBlock(true); + FlushBitBuffer(); + WritePoststreamTail(); + Reset(); + } + + Output(0, NULLPTR, 0, messageEnd, blocking); + return 0; +} + +bool Deflator::IsolatedFlush(bool hardFlush, bool blocking) +{ + if (!blocking) + throw BlockingInputOnly("Deflator"); + + m_minLookahead = 0; + ProcessBuffer(); + m_minLookahead = MAX_MATCH; + EndBlock(false); + if (hardFlush) + EncodeBlock(false, STORED); + return false; +} + +void Deflator::LiteralByte(byte b) +{ + if (m_matchBufferEnd == m_matchBuffer.size()) + EndBlock(false); + + m_matchBuffer[m_matchBufferEnd++].literalCode = b; + m_literalCounts[b]++; + m_blockLength++; +} + +void Deflator::MatchFound(unsigned int distance, unsigned int length) +{ + if (m_matchBufferEnd == m_matchBuffer.size()) + EndBlock(false); + + static const unsigned int lengthCodes[] = { + 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, + 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, + 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, + 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285}; + static const unsigned int lengthBases[] = + {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195, + 227,258}; + static const unsigned int distanceBases[30] = + {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073, + 4097,6145,8193,12289,16385,24577}; + + CRYPTOPP_ASSERT(m_matchBufferEnd < m_matchBuffer.size()); + EncodedMatch &m = m_matchBuffer[m_matchBufferEnd++]; + CRYPTOPP_ASSERT((length >= 3) && (length-3 < COUNTOF(lengthCodes))); + unsigned int lengthCode = lengthCodes[length-3]; + m.literalCode = lengthCode; + m.literalExtra = length - lengthBases[lengthCode-257]; + unsigned int distanceCode = (unsigned int)(std::upper_bound(distanceBases, distanceBases+30, distance) - distanceBases - 1); + m.distanceCode = distanceCode; + m.distanceExtra = distance - distanceBases[distanceCode]; + + m_literalCounts[lengthCode]++; + m_distanceCounts[distanceCode]++; + m_blockLength += length; +} + +inline unsigned int CodeLengthEncode(const unsigned int *begin, + const unsigned int *end, + const unsigned int *& p, + unsigned int &extraBits, + unsigned int &extraBitsLength) +{ + unsigned int v = *p; + if ((end-p) >= 3) + { + const unsigned int *oldp = p; + if (v==0 && p[1]==0 && p[2]==0) + { + for (p=p+3; p!=end && *p==0 && p!=oldp+138; p++) {} + unsigned int repeat = (unsigned int)(p - oldp); + if (repeat <= 10) + { + extraBits = repeat-3; + extraBitsLength = 3; + return 17; + } + else + { + extraBits = repeat-11; + extraBitsLength = 7; + return 18; + } + } + else if (p!=begin && v==p[-1] && v==p[1] && v==p[2]) + { + for (p=p+3; p!=end && *p==v && p!=oldp+6; p++) {} + unsigned int repeat = (unsigned int)(p - oldp); + extraBits = repeat-3; + extraBitsLength = 2; + return 16; + } + } + p++; + extraBits = 0; + extraBitsLength = 0; + return v; +} + +void Deflator::EncodeBlock(bool eof, unsigned int blockType) +{ + PutBits(eof, 1); + PutBits(blockType, 2); + + if (blockType == STORED) + { + CRYPTOPP_ASSERT(m_blockStart + m_blockLength <= m_byteBuffer.size()); + CRYPTOPP_ASSERT(m_blockLength <= 0xffff); + FlushBitBuffer(); + AttachedTransformation()->PutWord16(word16(m_blockLength), LITTLE_ENDIAN_ORDER); + AttachedTransformation()->PutWord16(word16(~m_blockLength), LITTLE_ENDIAN_ORDER); + AttachedTransformation()->Put(m_byteBuffer + m_blockStart, m_blockLength); + } + else + { + if (blockType == DYNAMIC) + { + FixedSizeSecBlock literalCodeLengths; + FixedSizeSecBlock distanceCodeLengths; + + m_literalCounts[256] = 1; + HuffmanEncoder::GenerateCodeLengths(literalCodeLengths, 15, m_literalCounts, 286); + m_dynamicLiteralEncoder.Initialize(literalCodeLengths, 286); + unsigned int hlit = (unsigned int)(FindIfNot(RevIt(literalCodeLengths.end()), RevIt(literalCodeLengths.begin()+257), 0).base() - (literalCodeLengths.begin()+257)); + + HuffmanEncoder::GenerateCodeLengths(distanceCodeLengths, 15, m_distanceCounts, 30); + m_dynamicDistanceEncoder.Initialize(distanceCodeLengths, 30); + unsigned int hdist = (unsigned int)(FindIfNot(RevIt(distanceCodeLengths.end()), RevIt(distanceCodeLengths.begin()+1), 0).base() - (distanceCodeLengths.begin()+1)); + + SecBlockWithHint combinedLengths(hlit+257+hdist+1); + memcpy(combinedLengths, literalCodeLengths, (hlit+257)*sizeof(unsigned int)); + memcpy(combinedLengths+hlit+257, distanceCodeLengths, (hdist+1)*sizeof(unsigned int)); + + FixedSizeSecBlock codeLengthCodeCounts, codeLengthCodeLengths; + std::fill(codeLengthCodeCounts.begin(), codeLengthCodeCounts.end(), 0); + const unsigned int *p = combinedLengths.begin(), *begin = combinedLengths.begin(), *end = combinedLengths.end(); + while (p != end) + { + unsigned int code=0, extraBits=0, extraBitsLength=0; + code = CodeLengthEncode(begin, end, p, extraBits, extraBitsLength); + codeLengthCodeCounts[code]++; + } + HuffmanEncoder::GenerateCodeLengths(codeLengthCodeLengths, 7, codeLengthCodeCounts, 19); + HuffmanEncoder codeLengthEncoder(codeLengthCodeLengths, 19); + static const unsigned int border[] = { // Order of the bit length code lengths + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + unsigned int hclen = 19; + while (hclen > 4 && codeLengthCodeLengths[border[hclen-1]] == 0) + hclen--; + hclen -= 4; + + PutBits(hlit, 5); + PutBits(hdist, 5); + PutBits(hclen, 4); + + for (unsigned int i=0; i= 257) + { + CRYPTOPP_ASSERT(literalCode <= 285); + PutBits(m_matchBuffer[i].literalExtra, lengthExtraBits[literalCode-257]); + unsigned int distanceCode = m_matchBuffer[i].distanceCode; + distanceEncoder.Encode(*this, distanceCode); + PutBits(m_matchBuffer[i].distanceExtra, distanceExtraBits[distanceCode]); + } + } + literalEncoder.Encode(*this, 256); // end of block + } +} + +void Deflator::EndBlock(bool eof) +{ + if (m_blockLength == 0 && !eof) + return; + + if (m_deflateLevel == 0) + { + EncodeBlock(eof, STORED); + + if (m_compressibleDeflateLevel > 0 && ++m_detectCount == m_detectSkip) + { + m_deflateLevel = m_compressibleDeflateLevel; + m_detectCount = 1; + } + } + else + { + unsigned long storedLen = 8*((unsigned long)m_blockLength+4) + RoundUpToMultipleOf(m_bitsBuffered+3, 8U)-m_bitsBuffered; + + StartCounting(); + EncodeBlock(eof, STATIC); + unsigned long staticLen = FinishCounting(); + + unsigned long dynamicLen; + if (m_blockLength < 128 && m_deflateLevel < 8) + dynamicLen = ULONG_MAX; + else + { + StartCounting(); + EncodeBlock(eof, DYNAMIC); + dynamicLen = FinishCounting(); + } + + if (storedLen <= staticLen && storedLen <= dynamicLen) + { + EncodeBlock(eof, STORED); + + if (m_compressibleDeflateLevel > 0) + { + if (m_detectSkip) + m_deflateLevel = 0; + m_detectSkip = m_detectSkip ? STDMIN(2*m_detectSkip, 128U) : 1; + } + } + else + { + if (staticLen <= dynamicLen) + EncodeBlock(eof, STATIC); + else + EncodeBlock(eof, DYNAMIC); + + if (m_compressibleDeflateLevel > 0) + m_detectSkip = 0; + } + } + + m_matchBufferEnd = 0; + m_blockStart += m_blockLength; + m_blockLength = 0; + std::fill(m_literalCounts.begin(), m_literalCounts.end(), 0); + std::fill(m_distanceCounts.begin(), m_distanceCounts.end(), 0); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/zdeflate.h b/external/ours/library/crypto/src/shared/original/zdeflate.h new file mode 100755 index 000000000..b72f5416d --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/zinflate.cpp b/external/ours/library/crypto/src/shared/original/zinflate.cpp new file mode 100755 index 000000000..859912647 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/zinflate.cpp @@ -0,0 +1,662 @@ +// zinflate.cpp - originally written and placed in the public domain by Wei Dai + +// This is a complete reimplementation of the DEFLATE decompression algorithm. +// It should not be affected by any security vulnerabilities in the zlib +// compression library. In particular it is not affected by the double free bug +// (http://www.kb.cert.org/vuls/id/368819). + +#include "pch.h" + +#include "zinflate.h" +#include "secblock.h" +#include "smartptr.h" + +NAMESPACE_BEGIN(CryptoPP) + +struct CodeLessThan +{ + inline bool operator()(CryptoPP::HuffmanDecoder::code_t lhs, const CryptoPP::HuffmanDecoder::CodeInfo &rhs) + {return lhs < rhs.code;} + // needed for MSVC .NET 2005 + inline bool operator()(const CryptoPP::HuffmanDecoder::CodeInfo &lhs, const CryptoPP::HuffmanDecoder::CodeInfo &rhs) + {return lhs.code < rhs.code;} +}; + +inline bool LowFirstBitReader::FillBuffer(unsigned int length) +{ + while (m_bitsBuffered < length) + { + byte b; + if (!m_store.Get(b)) + return false; + m_buffer |= (unsigned long)b << m_bitsBuffered; + m_bitsBuffered += 8; + } + CRYPTOPP_ASSERT(m_bitsBuffered <= sizeof(unsigned long)*8); + return true; +} + +inline unsigned long LowFirstBitReader::PeekBits(unsigned int length) +{ + bool result = FillBuffer(length); + CRYPTOPP_UNUSED(result); CRYPTOPP_ASSERT(result); + return m_buffer & (((unsigned long)1 << length) - 1); +} + +inline void LowFirstBitReader::SkipBits(unsigned int length) +{ + CRYPTOPP_ASSERT(m_bitsBuffered >= length); + m_buffer >>= length; + m_bitsBuffered -= length; +} + +inline unsigned long LowFirstBitReader::GetBits(unsigned int length) +{ + unsigned long result = PeekBits(length); + SkipBits(length); + return result; +} + +inline HuffmanDecoder::code_t HuffmanDecoder::NormalizeCode(HuffmanDecoder::code_t code, unsigned int codeBits) +{ + return code << (MAX_CODE_BITS - codeBits); +} + +void HuffmanDecoder::Initialize(const unsigned int *codeBits, unsigned int nCodes) +{ + // the Huffman codes are represented in 3 ways in this code: + // + // 1. most significant code bit (i.e. top of code tree) in the least significant bit position + // 2. most significant code bit (i.e. top of code tree) in the most significant bit position + // 3. most significant code bit (i.e. top of code tree) in n-th least significant bit position, + // where n is the maximum code length for this code tree + // + // (1) is the way the codes come in from the deflate stream + // (2) is used to sort codes so they can be binary searched + // (3) is used in this function to compute codes from code lengths + // + // a code in representation (2) is called "normalized" here + // The BitReverse() function is used to convert between (1) and (2) + // The NormalizeCode() function is used to convert from (3) to (2) + + if (nCodes == 0) + throw Err("null code"); + + m_maxCodeBits = *std::max_element(codeBits, codeBits+nCodes); + + if (m_maxCodeBits > MAX_CODE_BITS) + throw Err("code length exceeds maximum"); + + if (m_maxCodeBits == 0) + throw Err("null code"); + + // count number of codes of each length + SecBlockWithHint blCount(m_maxCodeBits+1); + std::fill(blCount.begin(), blCount.end(), 0); + unsigned int i; + for (i=0; i nextCode(m_maxCodeBits+1); + nextCode[1] = 0; + for (i=2; i<=m_maxCodeBits; i++) + { + // compute this while checking for overflow: code = (code + blCount[i-1]) << 1 + if (code > code + blCount[i-1]) + throw Err("codes oversubscribed"); + code += blCount[i-1]; + if (code > (code << 1)) + throw Err("codes oversubscribed"); + code <<= 1; + nextCode[i] = code; + } + + // MAX_CODE_BITS is 32, m_maxCodeBits may be smaller. + const word64 shiftedMaxCode = ((word64)1 << m_maxCodeBits); + if (code > shiftedMaxCode - blCount[m_maxCodeBits]) + throw Err("codes oversubscribed"); + else if (m_maxCodeBits != 1 && code < shiftedMaxCode - blCount[m_maxCodeBits]) + throw Err("codes incomplete"); + + // compute a vector of triples sorted by code + m_codeToValue.resize(nCodes - blCount[0]); + unsigned int j=0; + for (i=0; ilen) + { + entry.type = 2; + entry.len = codeInfo.len; + } + else + { + entry.type = 3; + entry.end = last+1; + } + } +} + +inline unsigned int HuffmanDecoder::Decode(code_t code, /* out */ value_t &value) const +{ + CRYPTOPP_ASSERT(((int)(code & m_cacheMask)) < (int)m_cache.size()); + LookupEntry &entry = m_cache[code & m_cacheMask]; + + code_t normalizedCode = 0; + if (entry.type != 1) + normalizedCode = BitReverse(code); + + if (entry.type == 0) + FillCacheEntry(entry, normalizedCode); + + if (entry.type == 1) + { + value = entry.value; + return entry.len; + } + else + { + const CodeInfo &codeInfo = (entry.type == 2) + ? entry.begin[(normalizedCode << m_cacheBits) >> (MAX_CODE_BITS - (entry.len - m_cacheBits))] + : *(std::upper_bound(entry.begin, entry.end, normalizedCode, CodeLessThan())-1); + value = codeInfo.value; + return codeInfo.len; + } +} + +bool HuffmanDecoder::Decode(LowFirstBitReader &reader, value_t &value) const +{ + bool result = reader.FillBuffer(m_maxCodeBits); + CRYPTOPP_UNUSED(result); // CRYPTOPP_ASSERT(result); + + unsigned int codeBits = Decode(reader.PeekBuffer(), value); + if (codeBits > reader.BitsBuffered()) + return false; + reader.SkipBits(codeBits); + return true; +} + +// ************************************************************* + +Inflator::Inflator(BufferedTransformation *attachment, bool repeat, int propagation) + : AutoSignaling(propagation) + , m_state(PRE_STREAM), m_repeat(repeat), m_eof(0), m_wrappedAround(0) + , m_blockType(0xff), m_storedLen(0xffff), m_nextDecode(), m_literal(0) + , m_distance(0), m_reader(m_inQueue), m_current(0), m_lastFlush(0) +{ + Detach(attachment); +} + +void Inflator::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_state = PRE_STREAM; + parameters.GetValue("Repeat", m_repeat); + m_inQueue.Clear(); + m_reader.SkipBits(m_reader.BitsBuffered()); +} + +void Inflator::OutputByte(byte b) +{ + m_window[m_current++] = b; + if (m_current == m_window.size()) + { + ProcessDecompressedData(m_window + m_lastFlush, m_window.size() - m_lastFlush); + m_lastFlush = 0; + m_current = 0; + m_wrappedAround = true; + } +} + +void Inflator::OutputString(const byte *string, size_t length) +{ + while (length) + { + size_t len = UnsignedMin(length, m_window.size() - m_current); + memcpy(m_window + m_current, string, len); + m_current += len; + if (m_current == m_window.size()) + { + ProcessDecompressedData(m_window + m_lastFlush, m_window.size() - m_lastFlush); + m_lastFlush = 0; + m_current = 0; + m_wrappedAround = true; + } + string += len; + length -= len; + } +} + +void Inflator::OutputPast(unsigned int length, unsigned int distance) +{ + size_t start; + if (distance <= m_current) + start = m_current - distance; + else if (m_wrappedAround && distance <= m_window.size()) + start = m_current + m_window.size() - distance; + else + throw BadBlockErr(); + + if (start + length > m_window.size()) + { + for (; start < m_window.size(); start++, length--) + OutputByte(m_window[start]); + start = 0; + } + + if (start + length > m_current || m_current + length >= m_window.size()) + { + while (length--) + OutputByte(m_window[start++]); + } + else + { + memcpy(m_window + m_current, m_window + start, length); + m_current += length; + } +} + +size_t Inflator::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) +{ + if (!blocking) + throw BlockingInputOnly("Inflator"); + + LazyPutter lp(m_inQueue, inString, length); + ProcessInput(messageEnd != 0); + + if (messageEnd) + if (!(m_state == PRE_STREAM || m_state == AFTER_END)) + throw UnexpectedEndErr(); + + Output(0, NULLPTR, 0, messageEnd, blocking); + return 0; +} + +bool Inflator::IsolatedFlush(bool hardFlush, bool blocking) +{ + if (!blocking) + throw BlockingInputOnly("Inflator"); + + if (hardFlush) + ProcessInput(true); + FlushOutput(); + + return false; +} + +void Inflator::ProcessInput(bool flush) +{ + while (true) + { + switch (m_state) + { + case PRE_STREAM: + if (!flush && m_inQueue.CurrentSize() < MaxPrestreamHeaderSize()) + return; + ProcessPrestreamHeader(); + m_state = WAIT_HEADER; + m_wrappedAround = false; + m_current = 0; + m_lastFlush = 0; + m_window.New(((size_t) 1) << GetLog2WindowSize()); + break; + case WAIT_HEADER: + { + // maximum number of bytes before actual compressed data starts + const size_t MAX_HEADER_SIZE = BitsToBytes(3+5+5+4+19*7+286*15+19*15); + if (m_inQueue.CurrentSize() < (flush ? 1 : MAX_HEADER_SIZE)) + return; + DecodeHeader(); + break; + } + case DECODING_BODY: + if (!DecodeBody()) + return; + break; + case POST_STREAM: + if (!flush && m_inQueue.CurrentSize() < MaxPoststreamTailSize()) + return; + ProcessPoststreamTail(); + m_state = m_repeat ? PRE_STREAM : AFTER_END; + Output(0, NULLPTR, 0, GetAutoSignalPropagation(), true); // TODO: non-blocking + if (m_inQueue.IsEmpty()) + return; + break; + case AFTER_END: + m_inQueue.TransferTo(*AttachedTransformation()); + return; + } + } +} + +void Inflator::DecodeHeader() +{ + if (!m_reader.FillBuffer(3)) + throw UnexpectedEndErr(); + m_eof = m_reader.GetBits(1) != 0; + m_blockType = (byte)m_reader.GetBits(2); + + switch (m_blockType) + { + case 0: // stored + { + m_reader.SkipBits(m_reader.BitsBuffered() % 8); + if (!m_reader.FillBuffer(32)) + throw UnexpectedEndErr(); + m_storedLen = (word16)m_reader.GetBits(16); + word16 nlen = (word16)m_reader.GetBits(16); + if (nlen != (word16)~m_storedLen) + throw BadBlockErr(); + break; + } + case 1: // fixed codes + m_nextDecode = LITERAL; + break; + case 2: // dynamic codes + { + if (!m_reader.FillBuffer(5+5+4)) + throw UnexpectedEndErr(); + unsigned int hlit = m_reader.GetBits(5); + unsigned int hdist = m_reader.GetBits(5); + unsigned int hclen = m_reader.GetBits(4); + unsigned int i = 0; + + FixedSizeSecBlock codeLengths; + static const unsigned int border[] = { // Order of the bit length code lengths + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + std::fill(codeLengths.begin(), codeLengths+19, 0); + for (i=0; i hlit+257+hdist+1) + throw BadBlockErr(); + std::fill(codeLengths + i, codeLengths + i + count, repeater); + i += count; + } + m_dynamicLiteralDecoder.Initialize(codeLengths, hlit+257); + if (hdist == 0 && codeLengths[hlit+257] == 0) + { + if (hlit != 0) // a single zero distance code length means all literals + throw BadBlockErr(); + } + else + m_dynamicDistanceDecoder.Initialize(codeLengths+hlit+257, hdist+1); + m_nextDecode = LITERAL; + } + catch (HuffmanDecoder::Err &) + { + throw BadBlockErr(); + } + break; + } + default: + throw BadBlockErr(); // reserved block type + } + m_state = DECODING_BODY; +} + +bool Inflator::DecodeBody() +{ + bool blockEnd = false; + switch (m_blockType) + { + case 0: // stored + CRYPTOPP_ASSERT(m_reader.BitsBuffered() == 0); + while (!m_inQueue.IsEmpty() && !blockEnd) + { + size_t size; + const byte *block = m_inQueue.Spy(size); + size = UnsignedMin(m_storedLen, size); + CRYPTOPP_ASSERT(size <= 0xffff); + + OutputString(block, size); + m_inQueue.Skip(size); + m_storedLen = m_storedLen - (word16)size; + if (m_storedLen == 0) + blockEnd = true; + } + break; + case 1: // fixed codes + case 2: // dynamic codes + static const unsigned int lengthStarts[] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; + static const unsigned int lengthExtraBits[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; + static const unsigned int distanceStarts[] = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; + static const unsigned int distanceExtraBits[] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + const HuffmanDecoder& literalDecoder = GetLiteralDecoder(); + const HuffmanDecoder& distanceDecoder = GetDistanceDecoder(); + + switch (m_nextDecode) + { + case LITERAL: + while (true) + { + if (!literalDecoder.Decode(m_reader, m_literal)) + { + m_nextDecode = LITERAL; + break; + } + if (m_literal < 256) + OutputByte((byte)m_literal); + else if (m_literal == 256) // end of block + { + blockEnd = true; + break; + } + else + { + if (m_literal > 285) + throw BadBlockErr(); + unsigned int bits; + case LENGTH_BITS: + CRYPTOPP_ASSERT(m_literal-257 < COUNTOF(lengthExtraBits)); + bits = lengthExtraBits[m_literal-257]; + if (!m_reader.FillBuffer(bits)) + { + m_nextDecode = LENGTH_BITS; + break; + } + CRYPTOPP_ASSERT(m_literal-257 < COUNTOF(lengthStarts)); + m_literal = m_reader.GetBits(bits) + lengthStarts[m_literal-257]; + case DISTANCE: + if (!distanceDecoder.Decode(m_reader, m_distance)) + { + m_nextDecode = DISTANCE; + break; + } + case DISTANCE_BITS: + CRYPTOPP_ASSERT(m_distance < COUNTOF(distanceExtraBits)); + if (m_distance >= COUNTOF(distanceExtraBits)) + throw BadDistanceErr(); + bits = distanceExtraBits[m_distance]; + if (!m_reader.FillBuffer(bits)) + { + m_nextDecode = DISTANCE_BITS; + break; + } + CRYPTOPP_ASSERT(m_distance < COUNTOF(distanceStarts)); + if (m_distance >= COUNTOF(distanceStarts)) + throw BadDistanceErr(); + m_distance = m_reader.GetBits(bits) + distanceStarts[m_distance]; + OutputPast(m_literal, m_distance); + } + } + break; + default: + CRYPTOPP_ASSERT(0); + } + } + if (blockEnd) + { + if (m_eof) + { + FlushOutput(); + m_reader.SkipBits(m_reader.BitsBuffered()%8); + if (m_reader.BitsBuffered()) + { + // undo too much lookahead + SecBlockWithHint buffer(m_reader.BitsBuffered() / 8); + for (unsigned int i=0; i= m_lastFlush); + ProcessDecompressedData(m_window + m_lastFlush, m_current - m_lastFlush); + m_lastFlush = m_current; + } +} + +void Inflator::CreateFixedLiteralDecoder() +{ + unsigned int codeLengths[288]; + std::fill(codeLengths + 0, codeLengths + 144, 8); + std::fill(codeLengths + 144, codeLengths + 256, 9); + std::fill(codeLengths + 256, codeLengths + 280, 7); + std::fill(codeLengths + 280, codeLengths + 288, 8); + m_fixedLiteralDecoder.reset(new HuffmanDecoder); + m_fixedLiteralDecoder->Initialize(codeLengths, 288); +} + +void Inflator::CreateFixedDistanceDecoder() +{ + unsigned int codeLengths[32]; + std::fill(codeLengths + 0, codeLengths + 32, 5); + m_fixedDistanceDecoder.reset(new HuffmanDecoder); + m_fixedDistanceDecoder->Initialize(codeLengths, 32); +} + +const HuffmanDecoder& Inflator::GetLiteralDecoder() +{ + if (m_blockType == 1) + { + if (m_fixedLiteralDecoder.get() == NULLPTR) + CreateFixedLiteralDecoder(); + return *m_fixedLiteralDecoder; + } + else + { + return m_dynamicLiteralDecoder; + } +} + +const HuffmanDecoder& Inflator::GetDistanceDecoder() +{ + if (m_blockType == 1) + { + if (m_fixedDistanceDecoder.get() == NULLPTR) + CreateFixedDistanceDecoder(); + return *m_fixedDistanceDecoder; + } + else + { + return m_dynamicDistanceDecoder; + } +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/zinflate.h b/external/ours/library/crypto/src/shared/original/zinflate.h new file mode 100755 index 000000000..bebc0fdf6 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/original/zlib.cpp b/external/ours/library/crypto/src/shared/original/zlib.cpp new file mode 100755 index 000000000..58dd8bc2b --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/zlib.cpp @@ -0,0 +1,93 @@ +// zlib.cpp - originally written and placed in the public domain by Wei Dai + +// "zlib" is the name of a well known C language compression library +// (http://www.zlib.org) and also the name of a compression format +// (RFC 1950) that the library implements. This file is part of a +// complete reimplementation of the zlib compression format. + +#include "pch.h" +#include "zlib.h" +#include "zdeflate.h" +#include "zinflate.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +static const byte DEFLATE_METHOD = 8; +static const byte FDICT_FLAG = (1 << 5); + +// ************************************************************* + +void ZlibCompressor::WritePrestreamHeader() +{ + m_adler32.Restart(); + CRYPTOPP_ASSERT(((GetLog2WindowSize()-8) << 4) <= 255); + byte cmf = byte(DEFLATE_METHOD | ((GetLog2WindowSize()-8) << 4)); + CRYPTOPP_ASSERT((GetCompressionLevel() << 6) <= 255); + byte flags = byte(GetCompressionLevel() << 6); + AttachedTransformation()->PutWord16(RoundUpToMultipleOf(word16(cmf*256+flags), word16(31))); +} + +void ZlibCompressor::ProcessUncompressedData(const byte *inString, size_t length) +{ + m_adler32.Update(inString, length); +} + +void ZlibCompressor::WritePoststreamTail() +{ + FixedSizeSecBlock adler32; + m_adler32.Final(adler32); + AttachedTransformation()->Put(adler32, 4); +} + +unsigned int ZlibCompressor::GetCompressionLevel() const +{ + static const unsigned int deflateToCompressionLevel[] = {0, 1, 1, 1, 2, 2, 2, 2, 2, 3}; + return deflateToCompressionLevel[GetDeflateLevel()]; +} + +// ************************************************************* + +ZlibDecompressor::ZlibDecompressor(BufferedTransformation *attachment, bool repeat, int propagation) + : Inflator(attachment, repeat, propagation), m_log2WindowSize(0) +{ +} + +void ZlibDecompressor::ProcessPrestreamHeader() +{ + m_adler32.Restart(); + + byte cmf; + byte flags; + + if (!m_inQueue.Get(cmf) || !m_inQueue.Get(flags)) + throw HeaderErr(); + + if ((cmf*256+flags) % 31 != 0) + throw HeaderErr(); // if you hit this exception, you're probably trying to decompress invalid data + + if ((cmf & 0xf) != DEFLATE_METHOD) + throw UnsupportedAlgorithm(); + + if (flags & FDICT_FLAG) + throw UnsupportedPresetDictionary(); + + m_log2WindowSize = 8 + (cmf >> 4); +} + +void ZlibDecompressor::ProcessDecompressedData(const byte *inString, size_t length) +{ + AttachedTransformation()->Put(inString, length); + m_adler32.Update(inString, length); +} + +void ZlibDecompressor::ProcessPoststreamTail() +{ + FixedSizeSecBlock adler32; + if (m_inQueue.Get(adler32, 4) != 4) + throw Adler32Err(); + if (!m_adler32.Verify(adler32)) + throw Adler32Err(); +} + +NAMESPACE_END diff --git a/external/ours/library/crypto/src/shared/original/zlib.h b/external/ours/library/crypto/src/shared/original/zlib.h new file mode 100755 index 000000000..a330eeb88 --- /dev/null +++ b/external/ours/library/crypto/src/shared/original/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/external/ours/library/crypto/src/shared/wrapper/MD5Hash.h b/external/ours/library/crypto/src/shared/wrapper/MD5Hash.h index 97595d653..14abc12ac 100755 --- a/external/ours/library/crypto/src/shared/wrapper/MD5Hash.h +++ b/external/ours/library/crypto/src/shared/wrapper/MD5Hash.h @@ -11,7 +11,9 @@ namespace CryptoPP { - class MD5; + namespace Weak1 { + class MD5; + } } namespace Crypto { @@ -35,7 +37,7 @@ class MD5Hash MD5Hash(const MD5Hash & source); private: - CryptoPP::MD5 * md5; + CryptoPP::Weak1::MD5 * md5; }; //----------------------------------------------------------------------- diff --git a/external/ours/library/crypto/src/shared/wrapper/TwofishCrypt.cpp b/external/ours/library/crypto/src/shared/wrapper/TwofishCrypt.cpp deleted file mode 100755 index 9a272ae38..000000000 --- a/external/ours/library/crypto/src/shared/wrapper/TwofishCrypt.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// TwofishCrypt.cpp -// copyright 2001 Verant Interactive -// Author: Justin Randall - -//----------------------------------------------------------------------- - -#include "FirstCrypto.h" -#include "twofish.h" -#include "TwofishCrypt.h" - -namespace Crypto { - -//----------------------------------------------------------------------- -/** - @brief default ctor -*/ -TwofishCrypt::TwofishCrypt() : -cipher(0) -{ -} - -//----------------------------------------------------------------------- - -TwofishCrypt::TwofishCrypt(const TwofishCrypt &) -{ -} - -//----------------------------------------------------------------------- -/** - @brief dtor - - Deletes the instance of the Twofish cipher -*/ -TwofishCrypt::~TwofishCrypt() -{ - delete cipher; -} - -//----------------------------------------------------------------------- -/** - @brief disabled assignment operator -*/ -TwofishCrypt & TwofishCrypt::operator = (const TwofishCrypt &) -{ - return *this; -} - -//----------------------------------------------------------------------- -/** - @brief return the blocksize of the cipher -*/ -const unsigned int TwofishCrypt::getBlockSize() const -{ - return BLOCKSIZE; -} - -//----------------------------------------------------------------------- -/** - @brief perform a cipher operation - - The cipher operation is determined by the instance of the - TwofishCrypt object (which is actually either a TwofishEncryptor or - TwofishDecryptor) - - The input block size must be greater than or equal to the cipher block - size. -*/ -void TwofishCrypt::process(const unsigned char * const inputBuffer, unsigned char * outputBuffer, const unsigned int size) -{ - static unsigned char block[BLOCKSIZE]; - - if(cipher && size >= BLOCKSIZE) - { - const unsigned int r = size & 3; // optimization -- safe is % BLOCKSIZE - if(r == 0) - { - unsigned int i; - for(i = 0; i < size; i += BLOCKSIZE) - { - memcpy(block, &inputBuffer[i], BLOCKSIZE); - cipher->ProcessBlock(block); - memcpy(&outputBuffer[i], block, BLOCKSIZE); - } - } - assert( r == 0 ); // size must be a 16 byte block for Twofish to do it's job! - } - assert(cipher != nullptr); // can't process data without a twofish encryptor or decryptor! -} - -//----------------------------------------------------------------------- - -}//namespace Crypto - diff --git a/external/ours/library/crypto/src/shared/wrapper/TwofishCrypt.h b/external/ours/library/crypto/src/shared/wrapper/TwofishCrypt.h index bcec162b2..9ecd1f22f 100755 --- a/external/ours/library/crypto/src/shared/wrapper/TwofishCrypt.h +++ b/external/ours/library/crypto/src/shared/wrapper/TwofishCrypt.h @@ -7,6 +7,7 @@ //----------------------------------------------------------------------- +#include "assert.h" #include "CryptoBufferTransform.h" namespace CryptoPP @@ -20,23 +21,58 @@ namespace Crypto { /** @brief abstract base class for Twofish ciphers */ +template class TwofishCrypt { public: - TwofishCrypt(); - virtual ~TwofishCrypt() = 0; + TwofishCrypt() : cipher(0) + { + } - enum { BLOCKSIZE=16 }; - const unsigned int getBlockSize() const; - void process(const unsigned char * const inputBuffer, unsigned char * outputBuffer, const unsigned int size); + virtual ~TwofishCrypt() + { + delete cipher; + } + + enum + { + BLOCKSIZE = 16 + }; + + const unsigned int getBlockSize() const + { + return BLOCKSIZE; + } + + void process(const unsigned char *const inputBuffer, unsigned char *outputBuffer, const unsigned int size) + { + static unsigned char block[BLOCKSIZE]; + + if (cipher && size >= BLOCKSIZE) + { + const unsigned int r = size & 3; // optimization -- safe is % BLOCKSIZE + if (r == 0) + { + unsigned int i; + for (i = 0; i < size; i += BLOCKSIZE) + { + memcpy(block, &inputBuffer[i], BLOCKSIZE); + cipher->ProcessAndXorBlock(block, NULLPTR, block); + memcpy(&outputBuffer[i], block, BLOCKSIZE); + } + } + assert(r == 0); // size must be a 16 byte block for Twofish to do it's job! + } + assert(cipher != nullptr); // can't process data without a twofish encryptor or decryptor! + } private: - TwofishCrypt & operator = (const TwofishCrypt & rhs); - TwofishCrypt(const TwofishCrypt & source); + TwofishCrypt &operator=(const TwofishCrypt &rhs); + TwofishCrypt(const TwofishCrypt &source); protected: - /** @brief assigned by a TwofishEncryptor or TwofishDecryptor */ - CryptoPP::Twofish * cipher; + /** @brief assigned by a TwofishEncryptor or TwofishDecryptor */ + T *cipher; }; //----------------------------------------------------------------------- diff --git a/external/ours/library/crypto/src/shared/wrapper/TwofishDecryptor.h b/external/ours/library/crypto/src/shared/wrapper/TwofishDecryptor.h index 9c5f7576e..eb2099d20 100755 --- a/external/ours/library/crypto/src/shared/wrapper/TwofishDecryptor.h +++ b/external/ours/library/crypto/src/shared/wrapper/TwofishDecryptor.h @@ -7,13 +7,14 @@ //----------------------------------------------------------------------- +#include "twofish.h" #include "TwofishCrypt.h" namespace Crypto { //----------------------------------------------------------------------- - class TwofishDecryptor : public TwofishCrypt + class TwofishDecryptor : public TwofishCrypt { public: TwofishDecryptor(); diff --git a/external/ours/library/crypto/src/shared/wrapper/TwofishEncryptor.h b/external/ours/library/crypto/src/shared/wrapper/TwofishEncryptor.h index 437cb07c2..70aea9e58 100755 --- a/external/ours/library/crypto/src/shared/wrapper/TwofishEncryptor.h +++ b/external/ours/library/crypto/src/shared/wrapper/TwofishEncryptor.h @@ -7,18 +7,14 @@ //----------------------------------------------------------------------- +#include "twofish.h" #include "TwofishCrypt.h" -namespace CryptoPP -{ - class TwofishEncryption; -} - namespace Crypto { //----------------------------------------------------------------------- -class TwofishEncryptor : public TwofishCrypt +class TwofishEncryptor : public TwofishCrypt { public: TwofishEncryptor(); diff --git a/external/ours/library/localization/src/shared/LocalizedString.h b/external/ours/library/localization/src/shared/LocalizedString.h index bd3b8cb32..c897cd107 100755 --- a/external/ours/library/localization/src/shared/LocalizedString.h +++ b/external/ours/library/localization/src/shared/LocalizedString.h @@ -38,8 +38,8 @@ class LocalizedString // TODO: make these typedefs platform dependent - typedef unsigned long id_type; - typedef unsigned long crc_type; + typedef uint32_t id_type; + typedef uint32_t crc_type; LocalizedString(id_type id, crc_type sourceCrc, Unicode::String const & str); LocalizedString(id_type id, Unicode::String const & str); // GENERATE Crc FROM UNICODE. diff --git a/external/ours/library/localization/src/shared/LocalizedStringTable.h b/external/ours/library/localization/src/shared/LocalizedStringTable.h index cea6635e4..36ad1aabd 100755 --- a/external/ours/library/localization/src/shared/LocalizedStringTable.h +++ b/external/ours/library/localization/src/shared/LocalizedStringTable.h @@ -46,7 +46,7 @@ class LocalizedStringTable typedef std::map NameMap_t; // TODO: make this typedef platform dependent - typedef long magic_type; + typedef int32_t magic_type; static const magic_type ms_MAGIC; explicit LocalizedStringTable (const std::string & filename); diff --git a/external/ours/library/localization/src/shared/StringId.cpp b/external/ours/library/localization/src/shared/StringId.cpp index cb1492e41..3e8c28ba0 100755 --- a/external/ours/library/localization/src/shared/StringId.cpp +++ b/external/ours/library/localization/src/shared/StringId.cpp @@ -39,7 +39,7 @@ m_textIndex (0) //---------------------------------------------------------------------- -StringId::StringId (const std::string & table, unsigned long textIndex) : +StringId::StringId (const std::string & table, uint32_t textIndex) : m_table (table), m_text (), m_textIndex (textIndex) @@ -238,7 +238,7 @@ void StringId::setText (const std::string & text) //---------------------------------------------------------------------- -void StringId::setTextIndex (unsigned long textIndex) const +void StringId::setTextIndex (uint32_t textIndex) const { m_textIndex = textIndex; } diff --git a/external/ours/library/localization/src/shared/StringId.h b/external/ours/library/localization/src/shared/StringId.h index 4b4572df1..752a2cebe 100755 --- a/external/ours/library/localization/src/shared/StringId.h +++ b/external/ours/library/localization/src/shared/StringId.h @@ -39,12 +39,12 @@ class StringId StringId (); StringId (const std::string & table, const std::string & text); - StringId (const std::string & table, unsigned long textIndex); + StringId (const std::string & table, uint32_t textIndex); explicit StringId (const std::string & canonicalRepresentation); const std::string & getTable () const; const std::string & getText () const; - unsigned long getTextIndex () const; + uint32_t getTextIndex () const; bool isInvalid () const; bool isValid () const; @@ -60,7 +60,7 @@ class StringId //-- text index is a mutable property of the StringId //-- it is set the first time a StringId is localized, to speed up future lookups - void setTextIndex (unsigned long textIndex) const; + void setTextIndex (uint32_t textIndex) const; bool localize (LocUnicodeString & result, bool forceEnglish = false) const; LocUnicodeString localize (bool forceEnglish = false) const; @@ -79,7 +79,7 @@ class StringId std::string m_table; std::string m_text; - mutable unsigned long m_textIndex; //if this number is nonzero, assume it is valid + mutable uint32_t m_textIndex; //if this number is nonzero, assume it is valid }; //---------------------------------------------------------------------- @@ -98,7 +98,7 @@ inline const std::string & StringId::getText() const //---------------------------------------------------------------------- -inline unsigned long StringId::getTextIndex() const +inline uint32_t StringId::getTextIndex() const { return m_textIndex; } diff --git a/external/ours/library/localizationArchive/src/shared/StringIdArchive.cpp b/external/ours/library/localizationArchive/src/shared/StringIdArchive.cpp index b4054a253..889167c57 100755 --- a/external/ours/library/localizationArchive/src/shared/StringIdArchive.cpp +++ b/external/ours/library/localizationArchive/src/shared/StringIdArchive.cpp @@ -23,7 +23,7 @@ namespace Archive */ void get(ReadIterator & source, StringId & target) { - unsigned long index = 0; + uint32_t index = 0; std::string table; std::string name; diff --git a/game/server/application/SwgDatabaseServer/src/shared/buffers/IndexedNetworkTableBuffer.h b/game/server/application/SwgDatabaseServer/src/shared/buffers/IndexedNetworkTableBuffer.h index 43595df7a..1ccd6deee 100755 --- a/game/server/application/SwgDatabaseServer/src/shared/buffers/IndexedNetworkTableBuffer.h +++ b/game/server/application/SwgDatabaseServer/src/shared/buffers/IndexedNetworkTableBuffer.h @@ -17,6 +17,7 @@ #include #include #include +#include // ====================================================================== diff --git a/game/server/application/SwgDatabaseServer/src/shared/cleanup/TaskObjectTemplateListUpdater.cpp b/game/server/application/SwgDatabaseServer/src/shared/cleanup/TaskObjectTemplateListUpdater.cpp index f4653cd98..97c648f7b 100755 --- a/game/server/application/SwgDatabaseServer/src/shared/cleanup/TaskObjectTemplateListUpdater.cpp +++ b/game/server/application/SwgDatabaseServer/src/shared/cleanup/TaskObjectTemplateListUpdater.cpp @@ -32,7 +32,7 @@ bool TaskObjectTemplateListUpdater::process(DB::Session *session) int i_lines = 0; while(1) { - int i_id; + int32 i_id; char s_name[4096]; int i_retval = 0; diff --git a/game/server/application/SwgDatabaseServer/src/shared/core/SwgSnapshot.cpp b/game/server/application/SwgDatabaseServer/src/shared/core/SwgSnapshot.cpp index a111e70ca..dc9f96fac 100755 --- a/game/server/application/SwgDatabaseServer/src/shared/core/SwgSnapshot.cpp +++ b/game/server/application/SwgDatabaseServer/src/shared/core/SwgSnapshot.cpp @@ -331,21 +331,21 @@ void SwgSnapshot::encodeScriptObject(const NetworkId &objectId, Archive::ByteStr void SwgSnapshot::decodeAttributes(const NetworkId &objectId, Archive::ReadIterator &data, bool isBaseline, int offset) { if (isBaseline) { - size_t size, baselineCommandCount; + int32_t size, baselineCommandCount; Archive::get(data, size); Archive::get(data, baselineCommandCount); Attributes::Value temp; - for (size_t i = 0; i < size; ++i) { + for (int32_t i = 0; i < size; ++i) { Archive::get(data, temp); m_creatureObjectBuffer.setAttribute(objectId, i + offset, temp); } } else { typedef Archive::AutoDeltaVector VectorType; - size_t numCommands, baselineCommandCount; + int32_t numCommands, baselineCommandCount; Archive::get(data, numCommands); Archive::get(data, baselineCommandCount); - for (size_t count = 0; count < numCommands; ++count) { + for (int32_t count = 0; count < numCommands; ++count) { unsigned char cmd;// datatype? uint16 index; @@ -386,8 +386,8 @@ void SwgSnapshot::encodeAttributes(const NetworkId &objectId, Archive::ByteStrea std::vector values; m_creatureObjectBuffer.getAttributesForObject(objectId, values, offset, Attributes::NumberOfAttributes); - Archive::put(data, Attributes::NumberOfAttributes); - Archive::put(data, static_cast(0)); // baselineCommandCount + Archive::put(data, static_cast (Attributes::NumberOfAttributes)); + Archive::put(data, static_cast(0)); // baselineCommandCount if (values.size() < static_cast(Attributes::NumberOfAttributes)) { DEBUG_REPORT_LOG(true, ("Object %s did not have valid attribute data in the database. Missing attributes will be set to 100.\n", objectId.getValueString().c_str())); values.resize(Attributes::NumberOfAttributes, 100); @@ -754,21 +754,21 @@ void SwgSnapshot::ignorePersistedFlag(const NetworkId &objectId, Archive::ReadIt void SwgSnapshot::decodeLocationDataList(const NetworkId &objectId, size_t listId, Archive::ReadIterator &data, bool isBaseline) { if (isBaseline) { - size_t size, baselineCommandCount; + int32_t size, baselineCommandCount; Archive::get(data, size); Archive::get(data, baselineCommandCount); LocationData temp; - for (size_t i = 0; i < size; ++i) { + for (int32_t i = 0; i < size; ++i) { Archive::get(data, temp); m_locationBuffer.set(objectId, listId, i, temp); } } else { typedef Archive::AutoDeltaVector VectorType; - size_t numCommands, baselineCommandCount; + int32_t numCommands, baselineCommandCount; Archive::get(data, numCommands); Archive::get(data, baselineCommandCount); - for (size_t count = 0; count < numCommands; ++count) { + for (int32_t count = 0; count < numCommands; ++count) { unsigned char cmd; uint16 index; @@ -813,8 +813,8 @@ void SwgSnapshot::encodeLocationDataList(const NetworkId &objectId, size_t listI std::vector values; m_locationBuffer.getLocationList(objectId, listId, values); - Archive::put(data, values.size()); - Archive::put(data, static_cast(0)); + Archive::put(data, static_cast (values.size())); + Archive::put(data, static_cast(0)); for (std::vector::iterator i = values.begin(); i != values.end(); ++i) { Archive::put(data, *i); } @@ -855,8 +855,8 @@ void SwgSnapshot::encodeExperience(const NetworkId &objectId, Archive::ByteStrea ValuesType values; m_experienceBuffer.getExperienceForObject(objectId, values); - Archive::put(data, values.size()); - Archive::put(data, static_cast(0)); // baselineCommandCount + Archive::put(data, static_cast (values.size())); + Archive::put(data, static_cast (0)); // baselineCommandCount for (ValuesType::const_iterator i = values.begin(); i != values.end(); ++i) { const unsigned char command = 0; //ADD Archive::put(data, command); @@ -901,8 +901,8 @@ void SwgSnapshot::encodeBattlefieldParticipants(const NetworkId &objectId, Archi ValuesType values; m_battlefieldParticipantBuffer.getParticipantsForRegion(objectId, values); - Archive::put(data, values.size()); - Archive::put(data, static_cast(0)); // baselineCommandCount + Archive::put(data, static_cast (values.size())); + Archive::put(data, static_cast (0)); // baselineCommandCount for (ValuesType::const_iterator i = values.begin(); i != values.end(); ++i) { const unsigned char command = 0; //ADD Archive::put(data, command); @@ -945,8 +945,8 @@ void SwgSnapshot::encodeManufactureSchematicAttributes(const NetworkId &objectId ValuesType values; m_manufactureSchematicAttributeBuffer.getDataForObject(objectId, values); - Archive::put(data, values.size()); - Archive::put(data, static_cast(0)); // baselineCommandCount + Archive::put(data, static_cast (values.size())); + Archive::put(data, static_cast (0)); // baselineCommandCount for (ValuesType::const_iterator i = values.begin(); i != values.end(); ++i) { const unsigned char command = 0; //ADD Archive::put(data, command); @@ -1087,8 +1087,8 @@ void SwgSnapshot::encodeWaypoints(const NetworkId &objectId, Archive::ByteStream ValuesType values; m_waypointBuffer.getWaypointsForObject(objectId, values); - Archive::put(data, values.size()); - Archive::put(data, static_cast(0)); // baselineCommandCount + Archive::put(data, static_cast (values.size())); + Archive::put(data, static_cast (0)); // baselineCommandCount for (ValuesType::const_iterator i = values.begin(); i != values.end(); ++i) { const unsigned char command = 0; //ADD Archive::put(data, command); diff --git a/game/server/application/SwgDatabaseServer/src/shared/generated/Schema_h.template b/game/server/application/SwgDatabaseServer/src/shared/generated/Schema_h.template index 7297cfd7a..9589c757b 100644 --- a/game/server/application/SwgDatabaseServer/src/shared/generated/Schema_h.template +++ b/game/server/application/SwgDatabaseServer/src/shared/generated/Schema_h.template @@ -92,7 +92,7 @@ struct PlayerObjectBufferRow : public DB::Row DB::BindableLong born_date; DB::BindableLong played_time; DB::BindableDouble force_regen_rate; - DB::BindableLong force_power; + DB::BindableLong force_power; DB::BindableLong max_force_power; DB::BindableBitArray<2047> active_quests; DB::BindableBitArray<2047> completed_quests; diff --git a/game/server/application/SwgDatabaseServer/src/shared/queries/CommoditiesQuery.cpp b/game/server/application/SwgDatabaseServer/src/shared/queries/CommoditiesQuery.cpp index f5ae1da4e..c4ce5f64f 100755 --- a/game/server/application/SwgDatabaseServer/src/shared/queries/CommoditiesQuery.cpp +++ b/game/server/application/SwgDatabaseServer/src/shared/queries/CommoditiesQuery.cpp @@ -97,28 +97,28 @@ bool AuctionLocationsQuery::addData(const DB::Row *_data) if (!m_location_ids.push_back(myData->location_id.getValueASCII())) return false; if (!m_location_names.push_back(myData->location_name.getValueASCII())) return false; if (!m_owner_ids.push_back(myData->owner_id.isNull(), myData->owner_id.getValueASCII())) return false; - if (!m_sales_taxes.push_back(myData->sales_tax.isNull(), myData->sales_tax.getValue())) return false; + if (!m_sales_taxes.push_back(myData->sales_tax.isNull(), static_cast(myData->sales_tax.getValue()))) return false; if (!m_sales_tax_bank_ids.push_back(myData->sales_tax_bank_id.isNull(), myData->sales_tax_bank_id.getValue())) return false; - if (!m_empty_date.push_back(myData->empty_date.isNull(), myData->empty_date.getValue())) return false; - if (!m_last_access_date.push_back(myData->last_access_date.isNull(), myData->last_access_date.getValue())) return false; - if (!m_inactive_date.push_back(myData->inactive_date.isNull(), myData->inactive_date.getValue())) return false; - if (!m_status.push_back(myData->status.isNull(), myData->status.getValue())) return false; + if (!m_empty_date.push_back(myData->empty_date.isNull(), static_cast(myData->empty_date.getValue()))) return false; + if (!m_last_access_date.push_back(myData->last_access_date.isNull(), static_cast(myData->last_access_date.getValue()))) return false; + if (!m_inactive_date.push_back(myData->inactive_date.isNull(), static_cast(myData->inactive_date.getValue()))) return false; + if (!m_status.push_back(myData->status.isNull(), static_cast(myData->status.getValue()))) return false; if (!m_search_enabled.push_back(myData->search_enabled.isNull(), myData->search_enabled.getValue())) return false; - if (!m_entrance_charge.push_back(myData->entrance_charge.isNull(), myData->entrance_charge.getValue())) return false; + if (!m_entrance_charge.push_back(myData->entrance_charge.isNull(), static_cast(myData->entrance_charge.getValue()))) return false; break; case mode_INSERT: if (!m_location_ids.push_back(myData->location_id.getValueASCII())) return false; if (!m_location_names.push_back(myData->location_name.getValueASCII())) return false; if (!m_owner_ids.push_back(myData->owner_id.isNull(), myData->owner_id.getValueASCII())) return false; - if (!m_sales_taxes.push_back(myData->sales_tax.isNull(), myData->sales_tax.getValue())) return false; + if (!m_sales_taxes.push_back(myData->sales_tax.isNull(), static_cast(myData->sales_tax.getValue()))) return false; if (!m_sales_tax_bank_ids.push_back(myData->sales_tax_bank_id.isNull(), myData->sales_tax_bank_id.getValue())) return false; - if (!m_empty_date.push_back(myData->empty_date.isNull(), myData->empty_date.getValue())) return false; - if (!m_last_access_date.push_back(myData->last_access_date.isNull(), myData->last_access_date.getValue())) return false; - if (!m_inactive_date.push_back(myData->inactive_date.isNull(), myData->inactive_date.getValue())) return false; - if (!m_status.push_back(myData->status.isNull(), myData->status.getValue())) return false; + if (!m_empty_date.push_back(myData->empty_date.isNull(), static_cast(myData->empty_date.getValue()))) return false; + if (!m_last_access_date.push_back(myData->last_access_date.isNull(), static_cast(myData->last_access_date.getValue()))) return false; + if (!m_inactive_date.push_back(myData->inactive_date.isNull(), static_cast(myData->inactive_date.getValue()))) return false; + if (!m_status.push_back(myData->status.isNull(), static_cast(myData->status.getValue()))) return false; if (!m_search_enabled.push_back(myData->search_enabled.isNull(), myData->search_enabled.getValue())) return false; - if (!m_entrance_charge.push_back(myData->entrance_charge.isNull(), myData->entrance_charge.getValue())) return false; + if (!m_entrance_charge.push_back(myData->entrance_charge.isNull(), static_cast(myData->entrance_charge.getValue()))) return false; break; case mode_SELECT: @@ -417,7 +417,7 @@ bool MarketAuctionsQuery::addData(const DB::Row *_data) if (!m_item_ids.push_back(myData->item_id.getValueASCII())) return false; if (!m_owner_ids.push_back(myData->owner_id.getValueASCII())) return false; - if (!m_actives.push_back(myData->active.isNull(), myData->active.getValue())) return false; + if (!m_actives.push_back(myData->active.isNull(), static_cast(myData->active.getValue()))) return false; break; } @@ -430,17 +430,17 @@ bool MarketAuctionsQuery::addData(const DB::Row *_data) if (!m_owner_ids.push_back(myData->owner_id.getValueASCII())) return false; if (!m_creator_ids.push_back(myData->creator_id.isNull(), myData->creator_id.getValueASCII())) return false; if (!m_location_ids.push_back(myData->location_id.getValueASCII())) return false; - if (!m_min_bids.push_back(myData->min_bid.isNull(), myData->min_bid.getValue())) return false; - if (!m_buy_now_prices.push_back(myData->buy_now_price.isNull(), myData->buy_now_price.getValue())) return false; - if (!m_auction_timers.push_back(myData->auction_timer.isNull(), myData->auction_timer.getValue())) return false; + if (!m_min_bids.push_back(myData->min_bid.isNull(), static_cast(myData->min_bid.getValue()))) return false; + if (!m_buy_now_prices.push_back(myData->buy_now_price.isNull(), static_cast(myData->buy_now_price.getValue()))) return false; + if (!m_auction_timers.push_back(myData->auction_timer.isNull(), static_cast(myData->auction_timer.getValue()))) return false; if (!m_oobs.push_back(myData->oob.isNull(), myData->oob.getValueASCII())) return false; if (!m_user_descriptions.push_back(myData->user_description.isNull(), myData->user_description.getValue())) return false; - if (!m_categories.push_back(myData->category.isNull(), myData->category.getValue())) return false; + if (!m_categories.push_back(myData->category.isNull(), static_cast(myData->category.getValue()))) return false; if (!m_item_names.push_back(myData->item_name.isNull(), myData->item_name.getValue())) return false; - if (!m_item_timers.push_back(myData->item_timer.isNull(), myData->item_timer.getValue())) return false; - if (!m_actives.push_back(myData->active.isNull(), myData->active.getValue())) return false; - if (!m_item_sizes.push_back(myData->item_size.isNull(), myData->item_size.getValue())) return false; - if (!m_object_template_ids.push_back(myData->object_template_id.isNull(), myData->object_template_id.getValue())) return false; + if (!m_item_timers.push_back(myData->item_timer.isNull(), static_cast(myData->item_timer.getValue()))) return false; + if (!m_actives.push_back(myData->active.isNull(), static_cast(myData->active.getValue()))) return false; + if (!m_item_sizes.push_back(myData->item_size.isNull(), static_cast(myData->item_size.getValue()))) return false; + if (!m_object_template_ids.push_back(myData->object_template_id.isNull(), static_cast(myData->object_template_id.getValue()))) return false; break; } @@ -724,8 +724,8 @@ bool MarketAuctionBidsQuery::addData(const DB::Row *_data) case mode_INSERT: if (!m_item_ids.push_back(myData->item_id.getValueASCII())) return false; if (!m_bidder_ids.push_back(myData->bidder_id.getValueASCII())) return false; - if (!m_bids.push_back(myData->bid.getValue())) return false; - if (!m_max_proxy_bids.push_back(myData->max_proxy_bid.isNull(), myData->max_proxy_bid.getValue())) return false; + if (!m_bids.push_back(static_cast(myData->bid.getValue()))) return false; + if (!m_max_proxy_bids.push_back(myData->max_proxy_bid.isNull(), static_cast(myData->max_proxy_bid.getValue()))) return false; break; case mode_SELECT: diff --git a/game/server/application/SwgDatabaseServer/src/shared/queries/ObjectsTableQuery.cpp b/game/server/application/SwgDatabaseServer/src/shared/queries/ObjectsTableQuery.cpp index 11624d221..3d41f50f5 100755 --- a/game/server/application/SwgDatabaseServer/src/shared/queries/ObjectsTableQuery.cpp +++ b/game/server/application/SwgDatabaseServer/src/shared/queries/ObjectsTableQuery.cpp @@ -160,89 +160,89 @@ bool ObjectsTableQuery::addData(const DB::Row *_data) if (!m_quaternion_xs.push_back(myData->quaternion_x.isNull(), myData->quaternion_x.getValue())) return false; if (!m_quaternion_ys.push_back(myData->quaternion_y.isNull(), myData->quaternion_y.getValue())) return false; if (!m_quaternion_zs.push_back(myData->quaternion_z.isNull(), myData->quaternion_z.getValue())) return false; - if (!m_node_xs.push_back(myData->node_x.isNull(), myData->node_x.getValue())) return false; - if (!m_node_ys.push_back(myData->node_y.isNull(), myData->node_y.getValue())) return false; - if (!m_node_zs.push_back(myData->node_z.isNull(), myData->node_z.getValue())) return false; - if (!m_type_ids.push_back(myData->type_id.isNull(), myData->type_id.getValue())) return false; + if (!m_node_xs.push_back(myData->node_x.isNull(), static_cast(myData->node_x.getValue()))) return false; + if (!m_node_ys.push_back(myData->node_y.isNull(), static_cast(myData->node_y.getValue()))) return false; + if (!m_node_zs.push_back(myData->node_z.isNull(), static_cast(myData->node_z.getValue()))) return false; + if (!m_type_ids.push_back(myData->type_id.isNull(), static_cast(myData->type_id.getValue()))) return false; if (!m_scene_ids.push_back(myData->scene_id.getValueASCII())) return false; - if (!m_controller_types.push_back(myData->controller_type.isNull(), myData->controller_type.getValue())) return false; - if (!m_deleteds.push_back(myData->deleted.isNull(), myData->deleted.getValue())) return false; + if (!m_controller_types.push_back(myData->controller_type.isNull(), static_cast(myData->controller_type.getValue()))) return false; + if (!m_deleteds.push_back(myData->deleted.isNull(), static_cast(myData->deleted.getValue()))) return false; if (!m_object_names.push_back(myData->object_name.getValueASCII())) return false; - if (!m_volumes.push_back(myData->volume.isNull(), myData->volume.getValue())) return false; + if (!m_volumes.push_back(myData->volume.isNull(), static_cast(myData->volume.getValue()))) return false; if (!m_contained_bys.push_back(myData->contained_by.getValueASCII())) return false; - if (!m_slot_arrangements.push_back(myData->slot_arrangement.isNull(), myData->slot_arrangement.getValue())) return false; + if (!m_slot_arrangements.push_back(myData->slot_arrangement.isNull(), static_cast(myData->slot_arrangement.getValue()))) return false; if (!m_player_controlleds.push_back(myData->player_controlled.getValueASCII())) return false; - if (!m_cache_versions.push_back(myData->cache_version.isNull(), myData->cache_version.getValue())) return false; + if (!m_cache_versions.push_back(myData->cache_version.isNull(), static_cast(myData->cache_version.getValue()))) return false; if (!m_load_contentss.push_back(myData->load_contents.getValueASCII())) return false; - if (!m_cash_balances.push_back(myData->cash_balance.isNull(), myData->cash_balance.getValue())) return false; - if (!m_bank_balances.push_back(myData->bank_balance.isNull(), myData->bank_balance.getValue())) return false; + if (!m_cash_balances.push_back(myData->cash_balance.isNull(), static_cast(myData->cash_balance.getValue()))) return false; + if (!m_bank_balances.push_back(myData->bank_balance.isNull(), static_cast(myData->bank_balance.getValue()))) return false; if (!m_complexitys.push_back(myData->complexity.isNull(), myData->complexity.getValue())) return false; if (!m_name_string_tables.push_back(myData->name_string_table.getValueASCII())) return false; if (!m_name_string_texts.push_back(myData->name_string_text.getValueASCII())) return false; if (!m_static_item_names.push_back(myData->static_item_name.getValueASCII())) return false; - if (!m_static_item_versions.push_back(myData->static_item_version.isNull(), myData->static_item_version.getValue())) return false; - if (!m_conversion_ids.push_back(myData->conversion_id.isNull(), myData->conversion_id.getValue())) return false; - if (!m_object_template_ids.push_back(myData->object_template_id.isNull(), myData->object_template_id.getValue())) return false; + if (!m_static_item_versions.push_back(myData->static_item_version.isNull(), static_cast(myData->static_item_version.getValue()))) return false; + if (!m_conversion_ids.push_back(myData->conversion_id.isNull(), static_cast(myData->conversion_id.getValue()))) return false; + if (!m_object_template_ids.push_back(myData->object_template_id.isNull(), static_cast(myData->object_template_id.getValue()))) return false; if (!m_load_withs.push_back(myData->load_with.getValueASCII())) return false; if (!m_objvar_0_names.push_back(myData->objvar_0_name.getValueASCII())) return false; - if (!m_objvar_0_types.push_back(myData->objvar_0_type.isNull(), myData->objvar_0_type.getValue())) return false; + if (!m_objvar_0_types.push_back(myData->objvar_0_type.isNull(), static_cast(myData->objvar_0_type.getValue()))) return false; if (!m_objvar_0_values.push_back(myData->objvar_0_value.getValueASCII())) return false; if (!m_objvar_1_names.push_back(myData->objvar_1_name.getValueASCII())) return false; - if (!m_objvar_1_types.push_back(myData->objvar_1_type.isNull(), myData->objvar_1_type.getValue())) return false; + if (!m_objvar_1_types.push_back(myData->objvar_1_type.isNull(), static_cast(myData->objvar_1_type.getValue()))) return false; if (!m_objvar_1_values.push_back(myData->objvar_1_value.getValueASCII())) return false; if (!m_objvar_2_names.push_back(myData->objvar_2_name.getValueASCII())) return false; - if (!m_objvar_2_types.push_back(myData->objvar_2_type.isNull(), myData->objvar_2_type.getValue())) return false; + if (!m_objvar_2_types.push_back(myData->objvar_2_type.isNull(), static_cast(myData->objvar_2_type.getValue()))) return false; if (!m_objvar_2_values.push_back(myData->objvar_2_value.getValueASCII())) return false; if (!m_objvar_3_names.push_back(myData->objvar_3_name.getValueASCII())) return false; - if (!m_objvar_3_types.push_back(myData->objvar_3_type.isNull(), myData->objvar_3_type.getValue())) return false; + if (!m_objvar_3_types.push_back(myData->objvar_3_type.isNull(), static_cast(myData->objvar_3_type.getValue()))) return false; if (!m_objvar_3_values.push_back(myData->objvar_3_value.getValueASCII())) return false; if (!m_objvar_4_names.push_back(myData->objvar_4_name.getValueASCII())) return false; - if (!m_objvar_4_types.push_back(myData->objvar_4_type.isNull(), myData->objvar_4_type.getValue())) return false; + if (!m_objvar_4_types.push_back(myData->objvar_4_type.isNull(), static_cast(myData->objvar_4_type.getValue()))) return false; if (!m_objvar_4_values.push_back(myData->objvar_4_value.getValueASCII())) return false; if (!m_objvar_5_names.push_back(myData->objvar_5_name.getValueASCII())) return false; - if (!m_objvar_5_types.push_back(myData->objvar_5_type.isNull(), myData->objvar_5_type.getValue())) return false; + if (!m_objvar_5_types.push_back(myData->objvar_5_type.isNull(), static_cast(myData->objvar_5_type.getValue()))) return false; if (!m_objvar_5_values.push_back(myData->objvar_5_value.getValueASCII())) return false; if (!m_objvar_6_names.push_back(myData->objvar_6_name.getValueASCII())) return false; - if (!m_objvar_6_types.push_back(myData->objvar_6_type.isNull(), myData->objvar_6_type.getValue())) return false; + if (!m_objvar_6_types.push_back(myData->objvar_6_type.isNull(), static_cast(myData->objvar_6_type.getValue()))) return false; if (!m_objvar_6_values.push_back(myData->objvar_6_value.getValueASCII())) return false; if (!m_objvar_7_names.push_back(myData->objvar_7_name.getValueASCII())) return false; - if (!m_objvar_7_types.push_back(myData->objvar_7_type.isNull(), myData->objvar_7_type.getValue())) return false; + if (!m_objvar_7_types.push_back(myData->objvar_7_type.isNull(), static_cast(myData->objvar_7_type.getValue()))) return false; if (!m_objvar_7_values.push_back(myData->objvar_7_value.getValueASCII())) return false; if (!m_objvar_8_names.push_back(myData->objvar_8_name.getValueASCII())) return false; - if (!m_objvar_8_types.push_back(myData->objvar_8_type.isNull(), myData->objvar_8_type.getValue())) return false; + if (!m_objvar_8_types.push_back(myData->objvar_8_type.isNull(), static_cast(myData->objvar_8_type.getValue()))) return false; if (!m_objvar_8_values.push_back(myData->objvar_8_value.getValueASCII())) return false; if (!m_objvar_9_names.push_back(myData->objvar_9_name.getValueASCII())) return false; - if (!m_objvar_9_types.push_back(myData->objvar_9_type.isNull(), myData->objvar_9_type.getValue())) return false; + if (!m_objvar_9_types.push_back(myData->objvar_9_type.isNull(), static_cast(myData->objvar_9_type.getValue()))) return false; if (!m_objvar_9_values.push_back(myData->objvar_9_value.getValueASCII())) return false; if (!m_objvar_10_names.push_back(myData->objvar_10_name.getValueASCII())) return false; - if (!m_objvar_10_types.push_back(myData->objvar_10_type.isNull(), myData->objvar_10_type.getValue())) return false; + if (!m_objvar_10_types.push_back(myData->objvar_10_type.isNull(), static_cast(myData->objvar_10_type.getValue()))) return false; if (!m_objvar_10_values.push_back(myData->objvar_10_value.getValueASCII())) return false; if (!m_objvar_11_names.push_back(myData->objvar_11_name.getValueASCII())) return false; - if (!m_objvar_11_types.push_back(myData->objvar_11_type.isNull(), myData->objvar_11_type.getValue())) return false; + if (!m_objvar_11_types.push_back(myData->objvar_11_type.isNull(), static_cast(myData->objvar_11_type.getValue()))) return false; if (!m_objvar_11_values.push_back(myData->objvar_11_value.getValueASCII())) return false; if (!m_objvar_12_names.push_back(myData->objvar_12_name.getValueASCII())) return false; - if (!m_objvar_12_types.push_back(myData->objvar_12_type.isNull(), myData->objvar_12_type.getValue())) return false; + if (!m_objvar_12_types.push_back(myData->objvar_12_type.isNull(), static_cast(myData->objvar_12_type.getValue()))) return false; if (!m_objvar_12_values.push_back(myData->objvar_12_value.getValueASCII())) return false; if (!m_objvar_13_names.push_back(myData->objvar_13_name.getValueASCII())) return false; - if (!m_objvar_13_types.push_back(myData->objvar_13_type.isNull(), myData->objvar_13_type.getValue())) return false; + if (!m_objvar_13_types.push_back(myData->objvar_13_type.isNull(), static_cast(myData->objvar_13_type.getValue()))) return false; if (!m_objvar_13_values.push_back(myData->objvar_13_value.getValueASCII())) return false; if (!m_objvar_14_names.push_back(myData->objvar_14_name.getValueASCII())) return false; - if (!m_objvar_14_types.push_back(myData->objvar_14_type.isNull(), myData->objvar_14_type.getValue())) return false; + if (!m_objvar_14_types.push_back(myData->objvar_14_type.isNull(), static_cast(myData->objvar_14_type.getValue()))) return false; if (!m_objvar_14_values.push_back(myData->objvar_14_value.getValueASCII())) return false; if (!m_objvar_15_names.push_back(myData->objvar_15_name.getValueASCII())) return false; - if (!m_objvar_15_types.push_back(myData->objvar_15_type.isNull(), myData->objvar_15_type.getValue())) return false; + if (!m_objvar_15_types.push_back(myData->objvar_15_type.isNull(), static_cast(myData->objvar_15_type.getValue()))) return false; if (!m_objvar_15_values.push_back(myData->objvar_15_value.getValueASCII())) return false; if (!m_objvar_16_names.push_back(myData->objvar_16_name.getValueASCII())) return false; - if (!m_objvar_16_types.push_back(myData->objvar_16_type.isNull(), myData->objvar_16_type.getValue())) return false; + if (!m_objvar_16_types.push_back(myData->objvar_16_type.isNull(), static_cast(myData->objvar_16_type.getValue()))) return false; if (!m_objvar_16_values.push_back(myData->objvar_16_value.getValueASCII())) return false; if (!m_objvar_17_names.push_back(myData->objvar_17_name.getValueASCII())) return false; - if (!m_objvar_17_types.push_back(myData->objvar_17_type.isNull(), myData->objvar_17_type.getValue())) return false; + if (!m_objvar_17_types.push_back(myData->objvar_17_type.isNull(), static_cast(myData->objvar_17_type.getValue()))) return false; if (!m_objvar_17_values.push_back(myData->objvar_17_value.getValueASCII())) return false; if (!m_objvar_18_names.push_back(myData->objvar_18_name.getValueASCII())) return false; - if (!m_objvar_18_types.push_back(myData->objvar_18_type.isNull(), myData->objvar_18_type.getValue())) return false; + if (!m_objvar_18_types.push_back(myData->objvar_18_type.isNull(), static_cast(myData->objvar_18_type.getValue()))) return false; if (!m_objvar_18_values.push_back(myData->objvar_18_value.getValueASCII())) return false; if (!m_objvar_19_names.push_back(myData->objvar_19_name.getValueASCII())) return false; - if (!m_objvar_19_types.push_back(myData->objvar_19_type.isNull(), myData->objvar_19_type.getValue())) return false; + if (!m_objvar_19_types.push_back(myData->objvar_19_type.isNull(),static_cast( myData->objvar_19_type.getValue()))) return false; if (!m_objvar_19_values.push_back(myData->objvar_19_value.getValueASCII())) return false; if (!m_script_lists.push_back(myData->script_list.getValueASCII())) return false; break; diff --git a/game/server/application/SwgDatabaseServer/src/shared/queries/ResourceTypeQuery.cpp b/game/server/application/SwgDatabaseServer/src/shared/queries/ResourceTypeQuery.cpp index dfc8a70ce..43caa07d0 100755 --- a/game/server/application/SwgDatabaseServer/src/shared/queries/ResourceTypeQuery.cpp +++ b/game/server/application/SwgDatabaseServer/src/shared/queries/ResourceTypeQuery.cpp @@ -50,7 +50,7 @@ bool ResourceTypeQuery::addData(DBSchema::ResourceTypeRow const & data) if (!m_resource_classes.push_back(data.resource_class.getValueASCII())) return false; if (!m_attributes.push_back(data.attributes.getValueASCII())) return false; if (!m_fractal_seeds.push_back(data.fractal_seeds.getValueASCII())) return false; - if (!m_depleted_timestamps.push_back(data.depleted_timestamp.isNull(), data.depleted_timestamp.getValue())) return false; + if (!m_depleted_timestamps.push_back(data.depleted_timestamp.isNull(), static_cast(data.depleted_timestamp.getValue()))) return false; m_numItems=m_numItems.getValue() + 1; return true; diff --git a/game/server/library/swgServerNetworkMessages/src/shared/core/SetupSwgServerNetworkMessages.cpp b/game/server/library/swgServerNetworkMessages/src/shared/core/SetupSwgServerNetworkMessages.cpp index 864e26450..8621f0b1a 100755 --- a/game/server/library/swgServerNetworkMessages/src/shared/core/SetupSwgServerNetworkMessages.cpp +++ b/game/server/library/swgServerNetworkMessages/src/shared/core/SetupSwgServerNetworkMessages.cpp @@ -198,20 +198,20 @@ namespace SetupSwgServerNetworkMessagesNamespace return unpackGenericMessage > > >(source); } - void packUnsignedLong(const MessageQueue::Data * data, Archive::ByteStream & target) + void packUnsignedInt(const MessageQueue::Data * data, Archive::ByteStream & target) { - const MessageQueueGenericValueType * msg = safe_cast *>(data); + const MessageQueueGenericValueType * msg = safe_cast *>(data); if(msg) { Archive::put(target, msg->getValue()); } } - MessageQueue::Data * unpackUnsignedLong(Archive::ReadIterator & source) + MessageQueue::Data * unpackUnsignedInt(Archive::ReadIterator & source) { - unsigned long v; + uint32_t v; Archive::get(source, v); - return new MessageQueueGenericValueType(v); + return new MessageQueueGenericValueType(v); } void packUnicodeString(const MessageQueue::Data * data, Archive::ByteStream & target) @@ -594,20 +594,20 @@ namespace SetupSwgServerNetworkMessagesNamespace return new MessageQueueGenericValueType >(v); } - void packULongBool(const MessageQueue::Data * data, Archive::ByteStream & target) + void packUIntBool(const MessageQueue::Data * data, Archive::ByteStream & target) { - const MessageQueueGenericValueType > * msg = safe_cast > *>(data); + const MessageQueueGenericValueType > * msg = safe_cast > *>(data); if(msg) { Archive::put(target, msg->getValue()); } } - MessageQueue::Data * unpackULongBool(Archive::ReadIterator & source) + MessageQueue::Data * unpackUIntBool(Archive::ReadIterator & source) { - std::pair v; + std::pair v; Archive::get(source, v); - return new MessageQueueGenericValueType >(v); + return new MessageQueueGenericValueType >(v); } void packStringNetworkIdNetworkId(const MessageQueue::Data * data, Archive::ByteStream & target) diff --git a/game/shared/library/swgSharedNetworkMessages/src/shared/core/SetupSwgSharedNetworkMessages.cpp b/game/shared/library/swgSharedNetworkMessages/src/shared/core/SetupSwgSharedNetworkMessages.cpp index 399a513ca..88def1ca2 100755 --- a/game/shared/library/swgSharedNetworkMessages/src/shared/core/SetupSwgSharedNetworkMessages.cpp +++ b/game/shared/library/swgSharedNetworkMessages/src/shared/core/SetupSwgSharedNetworkMessages.cpp @@ -191,7 +191,7 @@ namespace SetupSwgSharedNetworkMessagesNamespace void packAddToPlayerSpawnQueueMessage(const MessageQueue::Data * data, Archive::ByteStream & target) { - const MessageQueueGenericValueType > * const msg = dynamic_cast > *>(data); + const MessageQueueGenericValueType > * const msg = dynamic_cast > *>(data); if(msg) { Archive::put(target, msg->getValue()); @@ -200,9 +200,9 @@ namespace SetupSwgSharedNetworkMessagesNamespace MessageQueue::Data* unpackAddToPlayerSpawnQueueMessage(Archive::ReadIterator & source) { - std::pair v; + std::pair v; Archive::get(source, v); - MessageQueueGenericValueType > * result = new MessageQueueGenericValueType >(v); + MessageQueueGenericValueType > * result = new MessageQueueGenericValueType >(v); return result; }