diff --git a/Pluto.vcxproj b/Pluto.vcxproj index b8bf16960..473d489f8 100644 --- a/Pluto.vcxproj +++ b/Pluto.vcxproj @@ -262,7 +262,7 @@ true true false - SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -283,7 +283,7 @@ true true false - LUA_BUILD_AS_DLL;SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + LUA_BUILD_AS_DLL;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -304,7 +304,7 @@ true true false - SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -325,7 +325,7 @@ true true false - SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -346,7 +346,7 @@ true true false - SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -367,7 +367,7 @@ true true false - SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -388,7 +388,7 @@ true true false - LUA_BUILD_AS_DLL;SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + LUA_BUILD_AS_DLL;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -409,7 +409,7 @@ true true false - LUA_BUILD_AS_DLL;SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + LUA_BUILD_AS_DLL;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -430,7 +430,7 @@ true true false - SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -451,7 +451,7 @@ true true false - SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -472,7 +472,7 @@ true true false - SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -493,7 +493,7 @@ true true false - SOUP_USE_INTRIN;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 true @@ -581,76 +581,6 @@ - - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - - - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - - - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - - - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - - - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - -maes -mavx -mavx2 -mpclmul -mrdrnd -mrdseed -msha -msse4.1 %(AdditionalOptions) - @@ -785,6 +715,7 @@ + @@ -817,6 +748,7 @@ + @@ -954,7 +886,9 @@ + + diff --git a/Pluto.vcxproj.filters b/Pluto.vcxproj.filters index e23bf2732..b0e3d3079 100644 --- a/Pluto.vcxproj.filters +++ b/Pluto.vcxproj.filters @@ -105,9 +105,6 @@ vendor\Soup\soup - - vendor\Soup\Intrin - vendor\Soup\soup @@ -265,9 +262,6 @@ vendor\Soup\soup - - vendor\Soup\Intrin - vendor\Soup\soup @@ -283,18 +277,9 @@ vendor\Soup\soup - - vendor\Soup\Intrin - vendor\Soup\soup - - vendor\Soup\Intrin - - - vendor\Soup\Intrin - vendor\Soup\soup @@ -349,6 +334,9 @@ vendor\Soup\soup + + vendor\Soup\soup + vendor\Soup\soup @@ -1087,6 +1075,24 @@ vendor\Soup\soup + + vendor\Soup\soup + + + vendor\Soup\soup + + + vendor\Soup\soup + + + vendor\Soup\soup + + + vendor\Soup\soup + + + vendor\Soup\soup + vendor\Soup\soup @@ -1104,8 +1110,5 @@ {713ac335-27c4-4677-9da1-08c37c023a77} - - {f0adda43-f311-40e5-b4ec-284f248bad46} - - \ No newline at end of file + diff --git a/src/Makefile b/src/Makefile index bfd497703..0f1176291 100644 --- a/src/Makefile +++ b/src/Makefile @@ -27,7 +27,7 @@ SYSLIBS= MYCFLAGS= MYLDFLAGS= -MYLIBS=-Lvendor/Soup/soup -lsoup -Lvendor/Soup/Intrin -lsoupintrin +MYLIBS=-Lvendor/Soup/soup -lsoup MYOBJS= # Special flags for compiler modules; -Os reduces code size. @@ -63,9 +63,8 @@ o: $(ALL_O) a: $(ALL_A) $(LUA_A): $(BASE_O) - cd vendor/Soup/Intrin && $(MAKE) && cd ../.. cd vendor/Soup/soup && $(MAKE) && cd ../.. - $(AR) $@ $(BASE_O) vendor/Soup/Intrin/*.o vendor/Soup/soup/*.o + $(AR) $@ $(BASE_O) vendor/Soup/soup/*.o $(RANLIB) $@ $(LUA_SO): $(BASE_O) $(LUA_A) @@ -81,7 +80,6 @@ test: ./$(LUA_T) -v clean: - cd vendor/Soup/Intrin && $(MAKE) clean && cd ../.. cd vendor/Soup/soup && $(MAKE) clean && cd ../.. $(RM) $(ALL_T) $(ALL_O) diff --git a/src/vendor/Soup/Intrin/.sun b/src/vendor/Soup/Intrin/.sun deleted file mode 100644 index ae9f49ad7..000000000 --- a/src/vendor/Soup/Intrin/.sun +++ /dev/null @@ -1,15 +0,0 @@ -+*.cpp -static - -arg -O3 - -arg -maes -arg -mpclmul -arg -mrdrnd -arg -mrdseed -arg -msha -arg -msse4.1 - -if not windows - arg -fPIC -endif diff --git a/src/vendor/Soup/Intrin/Makefile b/src/vendor/Soup/Intrin/Makefile deleted file mode 100644 index dea4f5035..000000000 --- a/src/vendor/Soup/Intrin/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -CXX=g++ -std=c++17 -O3 -flto -fvisibility=hidden -fPIC -CFLAGS=-c -Wall - -ifeq ($(shell uname -m),x86_64) - CFLAGS+= -maes -mpclmul -mrdrnd -mrdseed -msha -msse4.1 -endif - -ifeq ($(shell uname -m),aarch64) - CFLAGS+= -march=armv8-a+crypto+crc -endif -# For people who think different -ifeq ($(shell uname -m),arm64) - CFLAGS+= -march=armv8-a+crypto+crc -endif - -LIBNAME=libsoupintrin.a -OBJS=aes_helper.o crc32_intrin.o hardware_rng.o sha1_transform.o sha256_transform.o - -all: $(LIBNAME) - -$(LIBNAME): $(OBJS) - ar rcs $(LIBNAME) $^ - -%.o: %.cpp - $(CXX) $(CFLAGS) -c $< -o $@ - -clean: - $(RM) ${OBJS} $(LIBNAME) diff --git a/src/vendor/Soup/Intrin/hardware_rng.cpp b/src/vendor/Soup/Intrin/hardware_rng.cpp deleted file mode 100644 index fc8dd8a7c..000000000 --- a/src/vendor/Soup/Intrin/hardware_rng.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "../soup/base.hpp" -#if SOUP_X86 - -#include - -#include - -NAMESPACE_SOUP -{ - namespace intrin - { - uint16_t hardware_rng_generate16() noexcept - { - uint16_t res; - while (_rdseed16_step(&res) == 0); - return res; - } - - uint32_t hardware_rng_generate32() noexcept - { - uint32_t res; - while (_rdseed32_step(&res) == 0); - return res; - } - -#if SOUP_BITS == 64 - uint64_t hardware_rng_generate64() noexcept - { - unsigned long long res; - while (_rdseed64_step(&res) == 0); - return res; - } - static_assert(sizeof(uint64_t) == sizeof(unsigned long long)); -#endif - } -} - -#endif diff --git a/src/vendor/Soup/build_common.php b/src/vendor/Soup/build_common.php index e154e29e3..9dd499793 100644 --- a/src/vendor/Soup/build_common.php +++ b/src/vendor/Soup/build_common.php @@ -1,7 +1,7 @@ x_over_y) + while (this->divide(y, x_over_y, remainder), y > x_over_y) { y = (x_over_y + y) / two; } diff --git a/src/vendor/Soup/soup/Bigint.hpp b/src/vendor/Soup/soup/Bigint.hpp index 07893bb54..24b9dd022 100644 --- a/src/vendor/Soup/soup/Bigint.hpp +++ b/src/vendor/Soup/soup/Bigint.hpp @@ -172,9 +172,9 @@ NAMESPACE_SOUP void operator/=(const Bigint& divisor) SOUP_EXCAL; void operator%=(const Bigint& divisor) SOUP_EXCAL; [[nodiscard]] std::pair divide(const Bigint& divisor) const SOUP_EXCAL; // (Quotient, Remainder) - void divide(const Bigint& divisor, Bigint& outQuotient, Bigint& outRemainder) const SOUP_EXCAL; + void divide(const Bigint& divisor, Bigint& SOUP_UNIQADDR outQuotient, Bigint& SOUP_UNIQADDR outRemainder) const SOUP_EXCAL; [[nodiscard]] std::pair divideUnsigned(const Bigint& divisor) const SOUP_EXCAL; // (Quotient, Remainder) - void divideUnsigned(const Bigint& divisor, Bigint& remainder) SOUP_EXCAL; + void divideUnsigned(const Bigint& divisor, Bigint& SOUP_UNIQADDR remainder) SOUP_EXCAL; [[nodiscard]] chunk_t divideUnsignedSmall(chunk_t divisor) noexcept; [[nodiscard]] Bigint mod(const Bigint& m) const SOUP_EXCAL; [[nodiscard]] Bigint modUnsigned(const Bigint& m) const SOUP_EXCAL; diff --git a/src/vendor/Soup/soup/Buffer.hpp b/src/vendor/Soup/soup/Buffer.hpp index 07eabbadc..30a9fac9a 100644 --- a/src/vendor/Soup/soup/Buffer.hpp +++ b/src/vendor/Soup/soup/Buffer.hpp @@ -50,6 +50,12 @@ NAMESPACE_SOUP append(b); } + Buffer(const std::string& b) SOUP_EXCAL + : Buffer(b.size()) + { + append(b); + } + Buffer(Buffer&& b) noexcept : m_data(b.m_data), m_size(b.m_size), m_capacity(b.m_capacity) { @@ -224,6 +230,11 @@ NAMESPACE_SOUP append(src.m_data, src.m_size); } + void append(const std::string& src) SOUP_EXCAL + { + append(src.data(), src.size()); + } + void erase(size_t pos, size_t len) SOUP_EXCAL { memmove(&m_data[pos], &m_data[pos + len], m_size - len); diff --git a/src/vendor/Soup/soup/BufferRefWriter.hpp b/src/vendor/Soup/soup/BufferRefWriter.hpp index d465f12a0..036fe08bf 100644 --- a/src/vendor/Soup/soup/BufferRefWriter.hpp +++ b/src/vendor/Soup/soup/BufferRefWriter.hpp @@ -11,7 +11,12 @@ NAMESPACE_SOUP public: Buffer& buf; - BufferRefWriter(Buffer& buf, Endian endian = ENDIAN_LITTLE) + BufferRefWriter(Buffer& buf) + : Writer(ENDIAN_LITTLE), buf(buf) + { + } + + [[deprecated]] BufferRefWriter(Buffer& buf, Endian endian) : Writer(endian), buf(buf) { } @@ -30,5 +35,10 @@ NAMESPACE_SOUP } return true; } + + [[nodiscard]] size_t getPosition() final + { + return buf.size(); + } }; } diff --git a/src/vendor/Soup/soup/BufferWriter.hpp b/src/vendor/Soup/soup/BufferWriter.hpp index c2c389981..9ff81b7d5 100644 --- a/src/vendor/Soup/soup/BufferWriter.hpp +++ b/src/vendor/Soup/soup/BufferWriter.hpp @@ -11,12 +11,17 @@ NAMESPACE_SOUP public: Buffer buf{}; - BufferWriter(Endian endian = ENDIAN_LITTLE) + BufferWriter() + : Writer(ENDIAN_LITTLE) + { + } + + [[deprecated]] BufferWriter(Endian endian) : Writer(endian) { } - BufferWriter(bool little_endian) + [[deprecated]] BufferWriter(bool little_endian) : Writer(little_endian) { } @@ -35,5 +40,10 @@ NAMESPACE_SOUP } return true; } + + [[nodiscard]] size_t getPosition() final + { + return buf.size(); + } }; } diff --git a/src/vendor/Soup/soup/Canvas.cpp b/src/vendor/Soup/soup/Canvas.cpp index 08b3d15ff..65abc1a0f 100644 --- a/src/vendor/Soup/soup/Canvas.cpp +++ b/src/vendor/Soup/soup/Canvas.cpp @@ -497,23 +497,23 @@ NAMESPACE_SOUP Canvas c; uint16_t sig; - SOUP_IF_LIKELY (r.u16(sig) && sig == 0x4D42) + SOUP_IF_LIKELY (r.u16le(sig) && sig == 0x4D42) { uint32_t data_start, header_size, palette_size; int32_t width, height; int16_t bits_per_pixel; - SOUP_IF_LIKELY ((r.seek(0x0A), r.u32(data_start)) - && r.u32(header_size) + SOUP_IF_LIKELY ((r.seek(0x0A), r.u32le(data_start)) + && r.u32le(header_size) && header_size == 40 // BITMAPINFOHEADER - && r.i32(width) - && r.i32(height) + && r.i32le(width) + && r.i32le(height) && r.skip(2) // planes - && r.i16(bits_per_pixel) + && r.i16le(bits_per_pixel) && r.skip(4) // compression method && r.skip(4) // image size && r.skip(4) // horizontal resolution && r.skip(4) // vertical resolution - && r.u32(palette_size) + && r.u32le(palette_size) && r.skip(4) // important colours ) { @@ -547,7 +547,7 @@ NAMESPACE_SOUP for (size_t i = 0; i != c.pixels.size(); ) { uint32_t dw; - SOUP_IF_UNLIKELY (!r.u32(dw)) + SOUP_IF_UNLIKELY (!r.u32le(dw)) { break; } @@ -672,17 +672,17 @@ NAMESPACE_SOUP { uint16_t s; uint32_t i; - SOUP_IF_UNLIKELY (!(s = 0x4D42, w.u16(s)) - || !(i = static_cast(40 + (3 * pixels.size())), w.u32(i)) + SOUP_IF_UNLIKELY (!(s = 0x4D42, w.u16le(s)) + || !(i = static_cast(40 + (3 * pixels.size())), w.u32le(i)) || !w.skip(4) - || !(i = (14 + 40), w.u32(i)) - || !(i = 40, w.u32(i)) - || !(i = width, w.u32(i)) - || !(i = height * -1, w.u32(i)) - || !(s = 1, w.u16(s)) - || !(s = 24, w.u16(s)) - || !(i = 0, w.u32(i)) - || !(i = static_cast(3 * pixels.size()), w.u32(i)) + || !(i = (14 + 40), w.u32le(i)) + || !(i = 40, w.u32le(i)) + || !(i = width, w.u32le(i)) + || !(i = height * -1, w.u32le(i)) + || !(s = 1, w.u16le(s)) + || !(s = 24, w.u16le(s)) + || !(i = 0, w.u32le(i)) + || !(i = static_cast(3 * pixels.size()), w.u32le(i)) || !w.skip(4 + 4 + 4 + 4) ) { diff --git a/src/vendor/Soup/soup/CpuInfo.cpp b/src/vendor/Soup/soup/CpuInfo.cpp index c65731a99..605313df0 100644 --- a/src/vendor/Soup/soup/CpuInfo.cpp +++ b/src/vendor/Soup/soup/CpuInfo.cpp @@ -47,8 +47,15 @@ NAMESPACE_SOUP if (cpuid_max_eax >= 0x07) { invokeCpuid(arr, 0x07, 0); + extended_features_max_ecx = EAX; extended_features_0_ebx = EBX; + if (extended_features_max_ecx >= 1) + { + invokeCpuid(arr, 0x07, 1); + extended_features_1_eax = EAX; + } + if (cpuid_max_eax >= 0x16) { invokeCpuid(arr, 0x16); @@ -65,7 +72,7 @@ NAMESPACE_SOUP if (cpuid_extended_max_eax >= 0x80000001) { invokeCpuid(arr, 0x80000001); - extended_features_1_ecx = ECX; + extended_flags_1_ecx = ECX; } #undef EAX @@ -114,30 +121,43 @@ NAMESPACE_SOUP str.append("\nStepping ID: ").append(std::to_string(stepping_id)); str.append("\nModel: ").append(std::to_string(model)); str.append("\nFamily: ").append(std::to_string(family)); - str.append("\nFeature Flags 1: ").append(string::hex(feature_flags_ecx)); - str.append("\nFeature Flags 2: ").append(string::hex(feature_flags_edx)); - if (cpuid_max_eax >= 0x07) + if (base_frequency || max_frequency || bus_frequency) { - str.append("\nFeature Flags 3: ").append(string::hex(extended_features_0_ebx)); - - if (cpuid_max_eax >= 0x16) - { - str.append("\nBase Frequency: ").append(std::to_string(base_frequency)).append( - " MHz\n" - "Max. Frequency: " - ).append(std::to_string(max_frequency)).append( - " MHz\n" - "Bus (Reference) Frequency: " - ).append(std::to_string(bus_frequency)).append(" MHz"); - } + str.append("\nBase Frequency: ").append(std::to_string(base_frequency)).append( + " MHz\n" + "Max. Frequency: " + ).append(std::to_string(max_frequency)).append( + " MHz\n" + "Bus (Reference) Frequency: " + ).append(std::to_string(bus_frequency)).append(" MHz"); } } - if (cpuid_extended_max_eax >= 0x80000001) - { - str.append("\nExtended Feature Flags: ").append(string::hex(extended_features_1_ecx)); - } + str.append("\nSSE Support: "); + if (supportsSSE4_2()) { str.append("SSE4.2"); } + else if (supportsSSE4_1()) { str.append("SSE4.1"); } + else if (supportsSSSE3()) { str.append("SSSE3"); } + else if (supportsSSE3()) { str.append("SSE3"); } + else if (supportsSSE2()) { str.append("SSE2"); } + else if (supportsSSE()) { str.append("SSE"); } + else { str.append("None"); } + + str.append("\nAVX Support: "); + if (supportsAVX512F()) { str.append("AVX512F"); } + else if (supportsAVX2()) { str.append("AVX2"); } + else if (supportsAVX()) { str.append("AVX"); } + else { str.append("None"); } + + std::string misc_features{}; + if (supportsPCLMULQDQ()) { string::listAppend(misc_features, "PCLMULQDQ"); } + if (supportsAESNI()) { string::listAppend(misc_features, "AESNI"); } + if (supportsRDRAND()) { string::listAppend(misc_features, "RDRAND"); } + if (supportsRDSEED()) { string::listAppend(misc_features, "RDSEED"); } + if (supportsSHA()) { string::listAppend(misc_features, "SHA"); } + if (supportsSHA512()) { string::listAppend(misc_features, "SHA512"); } + if (supportsXOP()) { string::listAppend(misc_features, "supportsXOP"); } + str.append("\nOther Known Features: ").append(misc_features); return str; #elif SOUP_ARM @@ -163,12 +183,11 @@ NAMESPACE_SOUP void CpuInfo::invokeCpuid(void* out, uint32_t eax, uint32_t ecx) noexcept { - #if defined(__GNUC__) - ((uint32_t*)out)[3] = ecx; - __get_cpuid(eax, &((uint32_t*)out)[0], &((uint32_t*)out)[1], &((uint32_t*)out)[3], &((uint32_t*)out)[2]); - #else + #if defined(_MSC_VER) && !defined(__clang__) __cpuidex(((int*)out), eax, ecx); std::swap(((int*)out)[2], ((int*)out)[3]); + #else + __cpuid_count(eax, ecx, ((int*)out)[0], ((int*)out)[1], ((int*)out)[3], ((int*)out)[2]); #endif } #endif diff --git a/src/vendor/Soup/soup/CpuInfo.hpp b/src/vendor/Soup/soup/CpuInfo.hpp index 6b05a889f..7ba4bee31 100644 --- a/src/vendor/Soup/soup/CpuInfo.hpp +++ b/src/vendor/Soup/soup/CpuInfo.hpp @@ -28,24 +28,30 @@ NAMESPACE_SOUP #if SOUP_X86 uint32_t cpuid_max_eax; - uint64_t cpuid_extended_max_eax; + uint32_t cpuid_extended_max_eax; ShortString<16> vendor_id; - uint8_t stepping_id; - uint8_t model; - uint8_t family; - uint32_t feature_flags_ecx; - uint32_t feature_flags_edx; + // EAX=1 + uint8_t stepping_id = 0; + uint8_t model = 0; + uint8_t family = 0; + uint32_t feature_flags_ecx = 0; + uint32_t feature_flags_edx = 0; // EAX=7, ECX=0 - uint32_t extended_features_0_ebx; + uint32_t extended_features_max_ecx = 0; + uint32_t extended_features_0_ebx = 0; - // EAX=80000001h - uint64_t extended_features_1_ecx; + // EAX=7, ECX=1 + uint32_t extended_features_1_eax = 0; + + // EAX=16h + uint16_t base_frequency = 0; + uint16_t max_frequency = 0; + uint16_t bus_frequency = 0; - uint16_t base_frequency; - uint16_t max_frequency; - uint16_t bus_frequency; + // EAX=80000001h + uint32_t extended_flags_1_ecx = 0; [[nodiscard]] bool supportsSSE() const noexcept { @@ -87,6 +93,11 @@ NAMESPACE_SOUP return (feature_flags_ecx >> 25) & 1; } + [[nodiscard]] bool supportsAVX() const noexcept + { + return (feature_flags_ecx >> 28) & 1; + } + [[nodiscard]] bool supportsRDRAND() const noexcept { return (feature_flags_ecx >> 30) & 1; @@ -112,9 +123,14 @@ NAMESPACE_SOUP return (extended_features_0_ebx >> 29) & 1; } + [[nodiscard]] bool supportsSHA512() const noexcept + { + return (extended_features_1_eax >> 0) & 1; + } + [[nodiscard]] bool supportsXOP() const noexcept { - return (extended_features_1_ecx >> 11) & 1; + return (extended_flags_1_ecx >> 11) & 1; } static void invokeCpuid(void* out, uint32_t eax) noexcept; diff --git a/src/vendor/Soup/soup/Endian.hpp b/src/vendor/Soup/soup/Endian.hpp index d07a17540..952ce62c9 100644 --- a/src/vendor/Soup/soup/Endian.hpp +++ b/src/vendor/Soup/soup/Endian.hpp @@ -1,5 +1,10 @@ #pragma once +#if defined(_MSC_VER) && !defined(__clang__) +#include // _byteswap_* +#include // is_constant_evaluated +#endif + #include "base.hpp" #include "IntStruct.hpp" @@ -10,7 +15,7 @@ NAMESPACE_SOUP { ENDIAN_LITTLE = true, ENDIAN_BIG = false, -#ifdef SOUP_LITTLE_ENDIAN +#if 'ABCD' == 0x41424344ul ENDIAN_NATIVE = ENDIAN_LITTLE, #else ENDIAN_NATIVE = ENDIAN_BIG, @@ -18,6 +23,10 @@ NAMESPACE_SOUP ENDIAN_NETWORK = ENDIAN_BIG, }; +#if 'ABCD' != 0x41424344ul // Native endian is not little endian? + static_assert('ABCD' == 0x44434241ul); // Then it should be big endian. +#endif + SOUP_INT_STRUCT(native_u16_t, uint16_t); SOUP_INT_STRUCT(native_u32_t, uint32_t); SOUP_INT_STRUCT(native_u64_t, uint64_t); @@ -31,35 +40,54 @@ NAMESPACE_SOUP { #if SOUP_CPP23 return std::byteswap(val); +#elif defined(_MSC_VER) && !defined(__clang__) + #if SOUP_CPP20 + if (!std::is_constant_evaluated()) + { + return _byteswap_ushort(val); + } + #endif #elif defined(__GNUC__) || defined(__clang__) return __builtin_bswap16(val); -#else - return (val << 8) | (val >> 8); #endif + return (val << 8) | (val >> 8); } [[nodiscard]] static constexpr uint32_t invert(uint32_t val) noexcept { #if SOUP_CPP23 return std::byteswap(val); +#elif defined(_MSC_VER) && !defined(__clang__) + #if SOUP_CPP20 + if (!std::is_constant_evaluated()) + { + return _byteswap_ulong(val); + } + #endif #elif defined(__GNUC__) || defined(__clang__) return __builtin_bswap32(val); -#else +#endif return val << (32 - 8) | ((val >> 8) & 0xFF) << (32 - 16) | ((val >> 16) & 0xFF) << (32 - 24) | ((val >> 24) & 0xFF) ; -#endif } [[nodiscard]] static constexpr uint64_t invert(uint64_t val) noexcept { #if SOUP_CPP23 return std::byteswap(val); +#elif defined(_MSC_VER) && !defined(__clang__) + #if SOUP_CPP20 + if (!std::is_constant_evaluated()) + { + return _byteswap_uint64(val); + } + #endif #elif defined(__GNUC__) || defined(__clang__) return __builtin_bswap64(val); -#else +#endif return val << (64 - 8) | ((val >> 8) & 0xFF) << (64 - 16) | ((val >> 16) & 0xFF) << (64 - 24) @@ -69,7 +97,6 @@ NAMESPACE_SOUP | ((val >> 48) & 0xFF) << (64 - 56) | ((val >> 56) & 0xFF) ; -#endif } [[nodiscard]] static constexpr network_u16_t toNetwork(uint16_t val) noexcept diff --git a/src/vendor/Soup/soup/HardwareRng.cpp b/src/vendor/Soup/soup/HardwareRng.cpp index 25a5963e9..c92ea9b94 100644 --- a/src/vendor/Soup/soup/HardwareRng.cpp +++ b/src/vendor/Soup/soup/HardwareRng.cpp @@ -13,53 +13,63 @@ #include // read, close #endif -NAMESPACE_SOUP -{ -#if SOUP_X86 && defined(SOUP_USE_INTRIN) - namespace intrin - { - extern uint16_t hardware_rng_generate16() noexcept; - extern uint32_t hardware_rng_generate32() noexcept; - extern uint64_t hardware_rng_generate64() noexcept; - } +#if SOUP_X86 +#include #endif +NAMESPACE_SOUP +{ // HardwareRng bool HardwareRng::isAvailable() noexcept { -#if SOUP_X86 && defined(SOUP_USE_INTRIN) +#if SOUP_X86 return CpuInfo::get().supportsRDSEED(); #else return false; #endif } + #if SOUP_X86 && (defined(__GNUC__) || defined(__clang__)) + __attribute__((target("rdseed"))) + #endif uint16_t HardwareRng::generate16() noexcept { -#if SOUP_X86 && defined(SOUP_USE_INTRIN) - return intrin::hardware_rng_generate16(); +#if SOUP_X86 + uint16_t res; + while (_rdseed16_step(&res) == 0); + return res; #else SOUP_ASSERT_UNREACHABLE; #endif } + #if SOUP_X86 && (defined(__GNUC__) || defined(__clang__)) + __attribute__((target("rdseed"))) + #endif uint32_t HardwareRng::generate32() noexcept { -#if SOUP_X86 && defined(SOUP_USE_INTRIN) - return intrin::hardware_rng_generate32(); +#if SOUP_X86 + uint32_t res; + while (_rdseed32_step(&res) == 0); + return res; #else SOUP_ASSERT_UNREACHABLE; #endif } + #if SOUP_X86 && SOUP_BITS >= 64 && (defined(__GNUC__) || defined(__clang__)) + __attribute__((target("rdseed"))) + #endif uint64_t HardwareRng::generate64() noexcept { -#if SOUP_X86 && defined(SOUP_USE_INTRIN) +#if SOUP_X86 #if SOUP_BITS >= 64 - return intrin::hardware_rng_generate64(); + unsigned long long res; + while (_rdseed64_step(&res) == 0); + return res; #else - return (static_cast(intrin::hardware_rng_generate32()) << 32) | intrin::hardware_rng_generate32(); + return (static_cast(generate32()) << 32) | generate32(); #endif #else SOUP_ASSERT_UNREACHABLE; diff --git a/src/vendor/Soup/soup/IntVector.hpp b/src/vendor/Soup/soup/IntVector.hpp index 11f6f542a..214472cf9 100644 --- a/src/vendor/Soup/soup/IntVector.hpp +++ b/src/vendor/Soup/soup/IntVector.hpp @@ -49,7 +49,7 @@ NAMESPACE_SOUP { free(); m_capacity = b.m_size; - m_data = (T*)malloc(m_capacity * sizeof(T)); + m_data = (T*)soup::malloc(m_capacity * sizeof(T)); } m_size = b.m_size; @@ -123,7 +123,7 @@ NAMESPACE_SOUP SOUP_IF_UNLIKELY (m_size + elms > m_capacity) { m_capacity = m_size + elms; - auto data = reinterpret_cast(malloc(m_capacity * sizeof(T))); + auto data = reinterpret_cast(soup::malloc(m_capacity * sizeof(T))); memcpy(&data[elms], &m_data[0], m_size * sizeof(T)); memset(&data[0], 0, elms * sizeof(T)); m_data = data; diff --git a/src/vendor/Soup/soup/IpGroups.hpp b/src/vendor/Soup/soup/IpGroups.hpp index eb7f34739..c666002ac 100644 --- a/src/vendor/Soup/soup/IpGroups.hpp +++ b/src/vendor/Soup/soup/IpGroups.hpp @@ -15,6 +15,7 @@ NAMESPACE_SOUP static constexpr CidrSupernet v4_private_network = { std::array { CidrSubnet4(SOUP_IPV4(192, 168, 0, 0), 16), + CidrSubnet4(SOUP_IPV4(172, 16, 0, 0), 12), CidrSubnet4(SOUP_IPV4(10, 0, 0, 0), 8), } }; diff --git a/src/vendor/Soup/soup/IstreamReader.hpp b/src/vendor/Soup/soup/IstreamReader.hpp index acf7abaf9..2bfcd1290 100644 --- a/src/vendor/Soup/soup/IstreamReader.hpp +++ b/src/vendor/Soup/soup/IstreamReader.hpp @@ -11,7 +11,12 @@ NAMESPACE_SOUP public: std::istream& is; - IstreamReader(std::istream& is, Endian endian = ENDIAN_LITTLE) + IstreamReader(std::istream& is) + : Reader(ENDIAN_LITTLE), is(is) + { + } + + [[deprecated]] IstreamReader(std::istream& is, Endian endian) : Reader(endian), is(is) { } diff --git a/src/vendor/Soup/soup/JsonFloat.cpp b/src/vendor/Soup/soup/JsonFloat.cpp index 04ea3cf84..11d76c126 100644 --- a/src/vendor/Soup/soup/JsonFloat.cpp +++ b/src/vendor/Soup/soup/JsonFloat.cpp @@ -21,7 +21,7 @@ NAMESPACE_SOUP uint64_t val; *reinterpret_cast(&val) = value; return w.u8(b) - && w.u64(val) + && w.u64le(val) ; } } diff --git a/src/vendor/Soup/soup/Makefile b/src/vendor/Soup/soup/Makefile index aaab2bfbe..b847bc280 100644 --- a/src/vendor/Soup/soup/Makefile +++ b/src/vendor/Soup/soup/Makefile @@ -1,5 +1,5 @@ CXX=g++ -std=c++17 -O3 -flto -fvisibility=hidden -fPIC -CFLAGS=-c -Wall -DSOUP_USE_INTRIN +CFLAGS=-c -Wall LIBNAME=libsoup.a # echo $(ls *.cpp | sed 's/.cpp/.o/g') diff --git a/src/vendor/Soup/soup/MemoryRefReader.hpp b/src/vendor/Soup/soup/MemoryRefReader.hpp index 3c6030b86..139dd6748 100644 --- a/src/vendor/Soup/soup/MemoryRefReader.hpp +++ b/src/vendor/Soup/soup/MemoryRefReader.hpp @@ -15,14 +15,25 @@ NAMESPACE_SOUP size_t size; size_t offset = 0; - MemoryRefReader(const void* _data, size_t size, bool little_endian = true) + MemoryRefReader(const void* _data, size_t size) + : Reader(true), data(reinterpret_cast(_data)), size(size) + { + } + + [[deprecated]] MemoryRefReader(const void* _data, size_t size, bool little_endian) : Reader(little_endian), data(reinterpret_cast(_data)), size(size) { } template )> - MemoryRefReader(const T& t, bool little_endian = true) - : MemoryRefReader(t.data(), t.size(), little_endian) + MemoryRefReader(const T& t) + : MemoryRefReader(t.data(), t.size()) + { + } + + template )> + [[deprecated]] MemoryRefReader(const T& t, bool little_endian) + : Reader(little_endian), data(reinterpret_cast(t.data())), size(t.size()) { } diff --git a/src/vendor/Soup/soup/Oid.cpp b/src/vendor/Soup/soup/Oid.cpp index f11a08a88..bdfebf79e 100644 --- a/src/vendor/Soup/soup/Oid.cpp +++ b/src/vendor/Soup/soup/Oid.cpp @@ -8,20 +8,20 @@ NAMESPACE_SOUP { - Oid Oid::COMMON_NAME = { 2, 5, 4, 3 }; - Oid Oid::RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 1 }; - Oid Oid::SHA1_WITH_RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 5 }; - Oid Oid::SHA256_WITH_RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 11 }; - Oid Oid::SHA384_WITH_RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 12 }; - Oid Oid::SHA512_WITH_RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 13 }; - Oid Oid::ECDSA_WITH_SHA256 = { 1, 2, 840, 10045, 4, 3, 2 }; - Oid Oid::ECDSA_WITH_SHA384 = { 1, 2, 840, 10045, 4, 3, 3 }; - Oid Oid::CE_KEYUSAGE = { 2, 5, 29, 15 }; - Oid Oid::CE_SUBJECTALTNAME = { 2, 5, 29, 17 }; - Oid Oid::CE_BASICCONSTRAINTS = { 2, 5, 29, 19 }; - Oid Oid::EC_PUBLIC_KEY = { 1, 2, 840, 10045, 2, 1 }; - Oid Oid::PRIME256V1 = { 1, 2, 840, 10045, 3, 1, 7 }; - Oid Oid::ANSIP384R1 = { 1, 3, 132, 0, 34 }; + const Oid Oid::COMMON_NAME = { 2, 5, 4, 3 }; + const Oid Oid::RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 1 }; + const Oid Oid::SHA1_WITH_RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 5 }; + const Oid Oid::SHA256_WITH_RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 11 }; + const Oid Oid::SHA384_WITH_RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 12 }; + const Oid Oid::SHA512_WITH_RSA_ENCRYPTION = { 1, 2, 840, 113549, 1, 1, 13 }; + const Oid Oid::ECDSA_WITH_SHA256 = { 1, 2, 840, 10045, 4, 3, 2 }; + const Oid Oid::ECDSA_WITH_SHA384 = { 1, 2, 840, 10045, 4, 3, 3 }; + const Oid Oid::CE_KEYUSAGE = { 2, 5, 29, 15 }; + const Oid Oid::CE_SUBJECTALTNAME = { 2, 5, 29, 17 }; + const Oid Oid::CE_BASICCONSTRAINTS = { 2, 5, 29, 19 }; + const Oid Oid::EC_PUBLIC_KEY = { 1, 2, 840, 10045, 2, 1 }; + const Oid Oid::PRIME256V1 = { 1, 2, 840, 10045, 3, 1, 7 }; + const Oid Oid::ANSIP384R1 = { 1, 3, 132, 0, 34 }; Oid Oid::fromBinary(const std::string& str) { diff --git a/src/vendor/Soup/soup/Oid.hpp b/src/vendor/Soup/soup/Oid.hpp index 5f4d60925..f2384baa3 100644 --- a/src/vendor/Soup/soup/Oid.hpp +++ b/src/vendor/Soup/soup/Oid.hpp @@ -11,20 +11,20 @@ NAMESPACE_SOUP { std::vector path{}; - static Oid COMMON_NAME; - static Oid RSA_ENCRYPTION; - static Oid SHA1_WITH_RSA_ENCRYPTION; - static Oid SHA256_WITH_RSA_ENCRYPTION; - static Oid SHA384_WITH_RSA_ENCRYPTION; - static Oid SHA512_WITH_RSA_ENCRYPTION; - static Oid ECDSA_WITH_SHA256; - static Oid ECDSA_WITH_SHA384; - static Oid CE_KEYUSAGE; - static Oid CE_SUBJECTALTNAME; - static Oid CE_BASICCONSTRAINTS; - static Oid EC_PUBLIC_KEY; - static Oid PRIME256V1; // aka. secp256r1 - static Oid ANSIP384R1; // aka. secp384r1 + static const Oid COMMON_NAME; + static const Oid RSA_ENCRYPTION; + static const Oid SHA1_WITH_RSA_ENCRYPTION; + static const Oid SHA256_WITH_RSA_ENCRYPTION; + static const Oid SHA384_WITH_RSA_ENCRYPTION; + static const Oid SHA512_WITH_RSA_ENCRYPTION; + static const Oid ECDSA_WITH_SHA256; + static const Oid ECDSA_WITH_SHA384; + static const Oid CE_KEYUSAGE; + static const Oid CE_SUBJECTALTNAME; + static const Oid CE_BASICCONSTRAINTS; + static const Oid EC_PUBLIC_KEY; + static const Oid PRIME256V1; // aka. secp256r1 + static const Oid ANSIP384R1; // aka. secp384r1 constexpr Oid() = default; diff --git a/src/vendor/Soup/soup/OstreamWriter.hpp b/src/vendor/Soup/soup/OstreamWriter.hpp index 800143b3f..1bd2be9d6 100644 --- a/src/vendor/Soup/soup/OstreamWriter.hpp +++ b/src/vendor/Soup/soup/OstreamWriter.hpp @@ -9,7 +9,12 @@ NAMESPACE_SOUP public: std::ostream& os; - OstreamWriter(std::ostream& os, Endian endian = ENDIAN_LITTLE) + OstreamWriter(std::ostream& os) + : Writer(ENDIAN_LITTLE), os(os) + { + } + + [[deprecated]] OstreamWriter(std::ostream& os, Endian endian) : Writer(endian), os(os) { } @@ -28,5 +33,10 @@ NAMESPACE_SOUP } return true; } + + [[nodiscard]] size_t getPosition() final + { + return os.tellp(); + } }; } diff --git a/src/vendor/Soup/soup/Packet.hpp b/src/vendor/Soup/soup/Packet.hpp index c3cc46c08..a1f48b85b 100644 --- a/src/vendor/Soup/soup/Packet.hpp +++ b/src/vendor/Soup/soup/Packet.hpp @@ -5,12 +5,8 @@ #define SOUP_IF_ISREAD if constexpr (T::isRead()) #define SOUP_ELSEIF_ISWRITE else -#include - #include "BufferWriter.hpp" -#include "IstreamReader.hpp" #include "MemoryRefReader.hpp" -#include "OstreamWriter.hpp" #include "StringReader.hpp" #include "StringWriter.hpp" #include "utility.hpp" // SOUP_MOVE_RETURN @@ -35,77 +31,38 @@ NAMESPACE_SOUP using u56 = u64; public: - bool fromBinary(std::string&& bin, Endian endian = ENDIAN_BIG) noexcept - { - StringReader r(std::move(bin), endian); - return read(r); - } - - bool fromBinary(const std::string& bin, Endian endian = ENDIAN_BIG) noexcept - { - MemoryRefReader r(bin, endian); - return read(r); - } - - bool fromBinaryLE(std::string&& bin) noexcept - { - StringReader r(std::move(bin), ENDIAN_LITTLE); - return read(r); - } - - bool fromBinaryLE(const std::string& bin) noexcept + bool fromBinary(std::string&& bin) noexcept { - MemoryRefReader r(bin, ENDIAN_LITTLE); + StringReader r(std::move(bin)); return read(r); } - bool read(std::istream& is, Endian endian = ENDIAN_BIG) + bool fromBinary(const std::string& bin) noexcept { - IstreamReader r(is, endian); + MemoryRefReader r(bin); return read(r); } - bool readLE(std::istream& is) - { - return read(is, ENDIAN_LITTLE); - } - template bool read(Reader& r) { return static_cast(this)->template io(r); } - [[nodiscard]] Buffer toBinary(Endian endian = ENDIAN_BIG) SOUP_EXCAL + [[nodiscard]] Buffer toBinary() SOUP_EXCAL { - BufferWriter w(endian); + BufferWriter w; write(w); SOUP_MOVE_RETURN(w.buf); } - [[nodiscard]] std::string toBinaryString(Endian endian = ENDIAN_BIG) SOUP_EXCAL + [[nodiscard]] std::string toBinaryString() SOUP_EXCAL { - StringWriter w(endian); + StringWriter w; write(w); SOUP_MOVE_RETURN(w.data); } - [[nodiscard]] std::string toBinaryStringLE() - { - return toBinaryString(ENDIAN_LITTLE); - } - - bool write(std::ostream& os, Endian endian = ENDIAN_BIG) - { - OstreamWriter w(os, endian); - return write(w); - } - - bool writeLE(std::ostream& os) - { - return write(os, ENDIAN_LITTLE); - } - template bool write(Writer& w) { diff --git a/src/vendor/Soup/soup/Reader.cpp b/src/vendor/Soup/soup/Reader.cpp index 8e36d107a..f2ef71526 100644 --- a/src/vendor/Soup/soup/Reader.cpp +++ b/src/vendor/Soup/soup/Reader.cpp @@ -49,4 +49,45 @@ NAMESPACE_SOUP } return true; } + + bool Reader::u64_dyn_v2(uint64_t& v) noexcept + { + uint8_t b; + SOUP_RETHROW_FALSE(u8(b)); + v = (b & 0x7f); + + uint8_t bits = 7; + bool has_next = (b >> 7); + while (has_next) + { + SOUP_RETHROW_FALSE(u8(b)); + has_next = false; + SOUP_IF_LIKELY (bits < 56) + { + has_next = (b >> 7); + b &= 0x7f; + } + v |= (((uint64_t)b + 1) << bits); + bits += 7; + } + + return true; + } + + bool Reader::i64_dyn_v2(int64_t& v) noexcept + { + uint64_t u; + SOUP_RETHROW_FALSE(u64_dyn_v2(u)); + const bool neg = (u >> 6) & 1; // check bit 6 + u = ((u >> 1) & ~0x3f) | (u & 0x3f); // remove bit 6 + if (neg) + { + v = (u * -1) - 1; + } + else + { + v = u; + } + return true; + } } diff --git a/src/vendor/Soup/soup/Reader.hpp b/src/vendor/Soup/soup/Reader.hpp index 85e50f6ea..48164c69e 100644 --- a/src/vendor/Soup/soup/Reader.hpp +++ b/src/vendor/Soup/soup/Reader.hpp @@ -12,7 +12,6 @@ NAMESPACE_SOUP using ioBase::ioBase; [[nodiscard]] virtual bool hasMore() noexcept = 0; - [[nodiscard]] virtual size_t getPosition() = 0; virtual void seek(size_t pos) = 0; void seekBegin() { seek(0); } virtual void seekEnd() = 0; @@ -39,6 +38,12 @@ NAMESPACE_SOUP // A signed 64-bit integer encoded in 1..9 bytes. (Specialisation of u64_dyn.) bool i64_dyn(int64_t& v) noexcept; + // An unsigned 64-bit integer encoded in 1..9 bytes. This is a slightly more efficient version of u64_dyn, e.g. 0x4000..0x407f are encoded in 2 bytes instead of 3. + bool u64_dyn_v2(uint64_t& v) noexcept; + + // A signed 64-bit integer encoded in 1..9 bytes. (Specialisation of u64_dyn_v2. This revision also simplifies how negative integers are handled.) + bool i64_dyn_v2(int64_t& v) noexcept; + // An integer where every byte's most significant bit is used to indicate if another byte follows, most significant byte first. template bool om(Int& v) noexcept @@ -113,7 +118,7 @@ NAMESPACE_SOUP if (first == 0xFC) { uint16_t val; - if (u16_le(val)) + if (u16le(val)) { v = val; return true; @@ -122,7 +127,7 @@ NAMESPACE_SOUP if (first == 0xFD) { uint32_t val; - if (u24_le(val)) + if (u24le(val)) { v = val; return true; @@ -131,7 +136,7 @@ NAMESPACE_SOUP if (first == 0xFE) { uint64_t val; - if (u64_le(val)) + if (u64le(val)) { v = val; return true; @@ -181,36 +186,6 @@ NAMESPACE_SOUP return mysql_lenenc(len) && str((size_t)len, v); } - // Length-prefixed string, using u8 for the length prefix. - [[deprecated]] bool str_lp_u8(std::string& v, const uint8_t max_len = 0xFF) SOUP_EXCAL - { - return str_lp(v, max_len); - } - - // Length-prefixed string, using u16 for the length prefix. - [[deprecated]] bool str_lp_u16(std::string& v, const uint16_t max_len = 0xFFFF) SOUP_EXCAL - { - return str_lp(v, max_len); - } - - // Length-prefixed string, using u24 for the length prefix. - [[deprecated]] bool str_lp_u24(std::string& v, const uint32_t max_len = 0xFFFFFF) SOUP_EXCAL - { - return str_lp(v, max_len); - } - - // Length-prefixed string, using u32 for the length prefix. - [[deprecated]] bool str_lp_u32(std::string& v, const uint32_t max_len = 0xFFFFFFFF) SOUP_EXCAL - { - return str_lp(v, max_len); - } - - // Length-prefixed string, using u64 for the length prefix. - [[deprecated]] bool str_lp_u64(std::string& v) SOUP_EXCAL - { - return str_lp(v); - } - // String with known length. bool str(size_t len, std::string& v) SOUP_EXCAL { @@ -237,36 +212,17 @@ NAMESPACE_SOUP return true; } - // std::vector with u16 size prefix. - bool vec_u16_u16(std::vector& v) SOUP_EXCAL - { - uint16_t len; - SOUP_RETHROW_FALSE(ioBase::u16(len)); - v.clear(); - v.reserve(len / 2); - while (len--) - { - uint16_t entry; - SOUP_IF_UNLIKELY (!ioBase::u16(entry)) - { - return false; - } - v.emplace_back(std::move(entry)); - } - return true; - } - - // std::vector with u16 byte length prefix. - bool vec_u16_bl_u16(std::vector& v) SOUP_EXCAL + // vector of u16be with u16be byte length prefix. + bool vec_u16be_bl_u16be(std::vector& v) SOUP_EXCAL { uint16_t len; - SOUP_RETHROW_FALSE(ioBase::u16(len)); + SOUP_RETHROW_FALSE(ioBase::u16be(len)); v.clear(); v.reserve(len / 2); for (; len >= sizeof(uint16_t); len -= sizeof(uint16_t)) { uint16_t entry; - SOUP_IF_UNLIKELY (!ioBase::u16(entry)) + SOUP_IF_UNLIKELY (!ioBase::u16be(entry)) { return false; } @@ -294,17 +250,17 @@ NAMESPACE_SOUP return true; } - // vector of str_lp with u24 byte length prefix. - bool vec_str_lp_u24_bl_u24(std::vector& v) SOUP_EXCAL + // vector of str_lp with u24be byte length prefix. + bool vec_str_lp_u24be_bl_u24be(std::vector& v) SOUP_EXCAL { uint32_t len; - SOUP_RETHROW_FALSE(ioBase::u24(len)); + SOUP_RETHROW_FALSE(ioBase::u24be(len)); v.clear(); v.reserve(len / 3); while (len >= 3) { std::string entry; - SOUP_IF_UNLIKELY (!str_lp(entry)) + SOUP_IF_UNLIKELY (!str_lp(entry)) { return false; } diff --git a/src/vendor/Soup/soup/Server.cpp b/src/vendor/Soup/soup/Server.cpp index c613c1c87..22fc0e7b4 100644 --- a/src/vendor/Soup/soup/Server.cpp +++ b/src/vendor/Soup/soup/Server.cpp @@ -15,7 +15,12 @@ NAMESPACE_SOUP Server* server; ServerService* service; - void processAccept(Socket&& sock) const SOUP_EXCAL + CaptureServerPort(Server* server, ServerService* service) + : server(server), service(service) + { + } + + void processAccept(Socket&& sock) const { if (sock.hasConnection()) { @@ -34,7 +39,12 @@ NAMESPACE_SOUP SharedPtr certstore; tls_server_on_client_hello_t on_client_hello; - void processAccept(Socket&& sock) const SOUP_EXCAL + CaptureServerPortCrypto(Server* server, ServerService* service, const SharedPtr& certstore, tls_server_on_client_hello_t on_client_hello) + : CaptureServerPort(server, service), certstore(certstore), on_client_hello(on_client_hello) + { + } + + void processAccept(Socket&& sock) const { if (sock.hasConnection()) { @@ -43,7 +53,7 @@ NAMESPACE_SOUP { service->on_connection_established(*s, *service, *server); } - s->enableCryptoServer(certstore, [](Socket& s, Capture&& _cap) SOUP_EXCAL + s->enableCryptoServer(certstore, [](Socket& s, Capture&& _cap) { CaptureServerPortCrypto& cap = *_cap.get(); cap.service->on_tunnel_established(s, *cap.service, *cap.server); @@ -52,6 +62,44 @@ NAMESPACE_SOUP } }; + struct CaptureServerPortOptCrypto : public CaptureServerPortCrypto + { + CaptureServerPortOptCrypto(Server* server, ServerService* service, const SharedPtr& certstore, tls_server_on_client_hello_t on_client_hello) + : CaptureServerPortCrypto(server, service, certstore, on_client_hello) + { + } + + void processAccept(Socket&& sock) const + { + if (sock.hasConnection()) + { + auto s = server->addSocket(std::move(sock)); + if (service->on_connection_established) + { + service->on_connection_established(*s, *service, *server); + } + s->transport_recv([](Socket& s, std::string&& data, Capture&& _cap) + { + s.transport_unrecv(data); + CaptureServerPortOptCrypto& cap = *_cap.get(); + if (data.size() > 2 && data.at(0) == 22 && data.at(1) == 3) // TLS? + { + s.enableCryptoServer(cap.certstore, [](Socket& s, Capture&& _cap) + { + CaptureServerPortOptCrypto& cap = *_cap.get(); + cap.service->on_tunnel_established(s, *cap.service, *cap.server); + }, &cap, cap.on_client_hello); + } + else + { + cap.service->on_tunnel_established(s, *cap.service, *cap.server); + } + }, this); + + } + } + }; + bool Server::bind(uint16_t port, ServerService* service) SOUP_EXCAL { Socket sock6{}; @@ -60,7 +108,7 @@ NAMESPACE_SOUP return false; } setDataAvailableHandler6(sock6); - sock6.holdup_callback.cap = CaptureServerPort{ this, service }; + sock6.holdup_callback.cap = CaptureServerPort(this, service); addSocket(std::move(sock6)); #if SOUP_WINDOWS @@ -70,7 +118,7 @@ NAMESPACE_SOUP return false; } setDataAvailableHandler4(sock4); - sock4.holdup_callback.cap = CaptureServerPort{ this, service }; + sock4.holdup_callback.cap = CaptureServerPort(this, service); addSocket(std::move(sock4)); #endif @@ -94,7 +142,7 @@ NAMESPACE_SOUP setDataAvailableHandler4(sock); } #endif - sock.holdup_callback.cap = CaptureServerPort{ this, service }; + sock.holdup_callback.cap = CaptureServerPort(this, service); addSocket(std::move(sock)); return true; } @@ -107,7 +155,7 @@ NAMESPACE_SOUP return false; } setDataAvailableHandlerCrypto6(sock6); - sock6.holdup_callback.cap = CaptureServerPortCrypto{ { this, service }, certstore, on_client_hello }; + sock6.holdup_callback.cap = CaptureServerPortCrypto(this, service, certstore, on_client_hello); addSocket(std::move(sock6)); #if SOUP_WINDOWS @@ -117,7 +165,32 @@ NAMESPACE_SOUP return false; } setDataAvailableHandlerCrypto4(sock4); - sock4.holdup_callback.cap = CaptureServerPortCrypto{ { this, service }, certstore, on_client_hello }; + sock4.holdup_callback.cap = CaptureServerPortCrypto(this, service, certstore, on_client_hello); + addSocket(std::move(sock4)); +#endif + + return true; + } + + bool Server::bindOptCrypto(uint16_t port, ServerService* service, SharedPtr certstore, tls_server_on_client_hello_t on_client_hello) SOUP_EXCAL + { + Socket sock6{}; + if (!sock6.bind6(port)) + { + return false; + } + setDataAvailableHandlerOptCrypto6(sock6); + sock6.holdup_callback.cap = CaptureServerPortOptCrypto(this, service, certstore, on_client_hello); + addSocket(std::move(sock6)); + +#if SOUP_WINDOWS + Socket sock4{}; + if (!sock4.bind4(port)) + { + return false; + } + setDataAvailableHandlerOptCrypto4(sock4); + sock4.holdup_callback.cap = CaptureServerPortOptCrypto(this, service, certstore, on_client_hello); addSocket(std::move(sock4)); #endif @@ -214,6 +287,16 @@ NAMESPACE_SOUP }; } + void Server::setDataAvailableHandlerOptCrypto6(Socket& s) noexcept + { + s.holdup_type = Worker::SOCKET; + s.holdup_callback.fp = [](Worker& w, Capture&& cap) SOUP_EXCAL + { + auto& s = static_cast(w); + cap.get().processAccept(s.accept6()); + }; + } + #if SOUP_WINDOWS void Server::setDataAvailableHandler4(Socket& s) noexcept { @@ -234,6 +317,16 @@ NAMESPACE_SOUP cap.get().processAccept(s.accept4()); }; } + + void Server::setDataAvailableHandlerOptCrypto4(Socket& s) noexcept + { + s.holdup_type = Worker::SOCKET; + s.holdup_callback.fp = [](Worker& w, Capture&& cap) SOUP_EXCAL + { + auto& s = static_cast(w); + cap.get().processAccept(s.accept4()); + }; + } #endif void Server::setDataAvailableHandlerUdp(Socket& s, udp_callback_t callback) noexcept diff --git a/src/vendor/Soup/soup/Server.hpp b/src/vendor/Soup/soup/Server.hpp index 89a934e0c..affa3f18a 100644 --- a/src/vendor/Soup/soup/Server.hpp +++ b/src/vendor/Soup/soup/Server.hpp @@ -16,6 +16,7 @@ NAMESPACE_SOUP bool bind(uint16_t port, ServerService* service) SOUP_EXCAL; bool bind(const IpAddr& ip, uint16_t port, ServerService* service) SOUP_EXCAL; bool bindCrypto(uint16_t port, ServerService* service, SharedPtr certstore, tls_server_on_client_hello_t on_client_hello = nullptr) SOUP_EXCAL; + bool bindOptCrypto(uint16_t port, ServerService* service, SharedPtr certstore, tls_server_on_client_hello_t on_client_hello = nullptr) SOUP_EXCAL; bool bindUdp(uint16_t port, udp_callback_t callback) SOUP_EXCAL; bool bindUdp(const IpAddr& addr, uint16_t port, udp_callback_t callback) SOUP_EXCAL; bool bindUdp(uint16_t port, ServerServiceUdp* service) SOUP_EXCAL; @@ -23,9 +24,11 @@ NAMESPACE_SOUP protected: static void setDataAvailableHandler6(Socket& s) noexcept; static void setDataAvailableHandlerCrypto6(Socket& s) noexcept; + static void setDataAvailableHandlerOptCrypto6(Socket& s) noexcept; #if SOUP_WINDOWS static void setDataAvailableHandler4(Socket& s) noexcept; static void setDataAvailableHandlerCrypto4(Socket& s) noexcept; + static void setDataAvailableHandlerOptCrypto4(Socket& s) noexcept; #endif static void setDataAvailableHandlerUdp(Socket& s, udp_callback_t callback) noexcept; static void setDataAvailableHandlerUdp(Socket& s, ServerServiceUdp* service) noexcept; diff --git a/src/vendor/Soup/soup/Socket.cpp b/src/vendor/Soup/soup/Socket.cpp index f1f37a168..71ba594ca 100644 --- a/src/vendor/Soup/soup/Socket.cpp +++ b/src/vendor/Soup/soup/Socket.cpp @@ -468,8 +468,8 @@ NAMESPACE_SOUP //TlsSignatureScheme::ecdsa_secp384r1_sha384, }; - StringWriter sw(ENDIAN_BIG); - sw.vec_u16_bl_u16(supported_signature_schemes); + StringWriter sw; + sw.vec_u16be_bl_u16be(supported_signature_schemes); hello.extensions.add(TlsExtensionType::signature_algorithms, std::move(sw.data)); } @@ -917,7 +917,7 @@ NAMESPACE_SOUP Bigint data; }; - void Socket::enableCryptoServer(SharedPtr certstore, void(*callback)(Socket&, Capture&&) SOUP_EXCAL, Capture&& cap, tls_server_on_client_hello_t on_client_hello) SOUP_EXCAL + void Socket::enableCryptoServer(SharedPtr certstore, void(*callback)(Socket&, Capture&&), Capture&& cap, tls_server_on_client_hello_t on_client_hello) { auto handshaker = make_unique( callback, @@ -925,7 +925,7 @@ NAMESPACE_SOUP ); handshaker->certstore = std::move(certstore); handshaker->on_client_hello = on_client_hello; - tls_recvHandshake(std::move(handshaker), [](Socket& s, UniquePtr&& handshaker, TlsHandshakeType_t handshake_type, std::string&& data) SOUP_EXCAL + tls_recvHandshake(std::move(handshaker), [](Socket& s, UniquePtr&& handshaker, TlsHandshakeType_t handshake_type, std::string&& data) { if (handshake_type != TlsHandshake::client_hello) { @@ -1021,7 +1021,7 @@ NAMESPACE_SOUP handshaker->private_key = &rsa_data->private_key; - s.tls_recvHandshake(std::move(handshaker), [](Socket& s, UniquePtr&& handshaker, TlsHandshakeType_t handshake_type, std::string&& data) SOUP_EXCAL + s.tls_recvHandshake(std::move(handshaker), [](Socket& s, UniquePtr&& handshaker, TlsHandshakeType_t handshake_type, std::string&& data) { if (handshake_type != TlsHandshake::client_key_exchange) { @@ -1045,7 +1045,7 @@ NAMESPACE_SOUP Bigint::fromBinary(data) }); - s.tls_recvRecord(TlsContentType::change_cipher_spec, [](Socket& s, std::string&& data, Capture&& cap) SOUP_EXCAL + s.tls_recvRecord(TlsContentType::change_cipher_spec, [](Socket& s, std::string&& data, Capture&& cap) { if (!s.tls_sendRecord(TlsContentType::change_cipher_spec, "\1")) { @@ -1055,7 +1055,7 @@ NAMESPACE_SOUP UniquePtr handshaker = std::move(cap.get>()); auto* p = &handshaker->promise; - s.awaitPromiseCompletion(p, [](Worker& w, Capture&& cap) SOUP_EXCAL + s.awaitPromiseCompletion(p, [](Worker& w, Capture&& cap) { w.holdup_type = Worker::NONE; @@ -1073,7 +1073,7 @@ NAMESPACE_SOUP handshaker->expected_finished_verify_data = handshaker->getClientFinishVerifyData(); - s.tls_recvHandshake(std::move(handshaker), [](Socket& s, UniquePtr&& handshaker, TlsHandshakeType_t handshake_type, std::string&& data) SOUP_EXCAL + s.tls_recvHandshake(std::move(handshaker), [](Socket& s, UniquePtr&& handshaker, TlsHandshakeType_t handshake_type, std::string&& data) { if (handshake_type != TlsHandshake::finished) { @@ -1202,7 +1202,7 @@ NAMESPACE_SOUP } else { - transport_recv(0x1000, callback, std::move(cap)); + transport_recv(callback, std::move(cap)); } } @@ -1296,7 +1296,7 @@ NAMESPACE_SOUP record.length = static_cast(body.size()); Buffer header(5); - BufferRefWriter bw(header, ENDIAN_BIG); + BufferRefWriter bw(header); record.write(bw); body.prepend(header.data(), header.size()); @@ -1306,11 +1306,11 @@ NAMESPACE_SOUP struct CaptureSocketTlsRecvHandshake { UniquePtr handshaker; - void(*callback)(Socket&, UniquePtr&&, TlsHandshakeType_t, std::string&&) SOUP_EXCAL; + void(*callback)(Socket&, UniquePtr&&, TlsHandshakeType_t, std::string&&); std::string pre; }; - void Socket::tls_recvHandshake(UniquePtr&& handshaker, void(*callback)(Socket&, UniquePtr&&, TlsHandshakeType_t, std::string&&) SOUP_EXCAL, std::string&& pre) SOUP_EXCAL + void Socket::tls_recvHandshake(UniquePtr&& handshaker, void(*callback)(Socket&, UniquePtr&&, TlsHandshakeType_t, std::string&&), std::string&& pre) // 'excal' if callback is { CaptureSocketTlsRecvHandshake cap{ std::move(handshaker), @@ -1318,7 +1318,7 @@ NAMESPACE_SOUP std::move(pre) }; - auto record_callback = [](Socket& s, TlsContentType_t content_type, std::string&& data, Capture&& _cap) SOUP_EXCAL + auto record_callback = [](Socket& s, TlsContentType_t content_type, std::string&& data, Capture&& _cap) // 'excal' if callback is { if (content_type != TlsContentType::handshake) { @@ -1665,6 +1665,11 @@ NAMESPACE_SOUP return {}; } + void Socket::transport_recv(transport_recv_callback_t callback, Capture&& cap) + { + return transport_recv(0x1000, callback, std::move(cap)); + } + struct CaptureSocketTransportRecv { int bytes; diff --git a/src/vendor/Soup/soup/Socket.hpp b/src/vendor/Soup/soup/Socket.hpp index 1946adab2..bb5e37c72 100644 --- a/src/vendor/Soup/soup/Socket.hpp +++ b/src/vendor/Soup/soup/Socket.hpp @@ -118,7 +118,7 @@ NAMESPACE_SOUP void enableCryptoClientProcessServerHelloDone(UniquePtr&& handshaker) SOUP_EXCAL; public: - void enableCryptoServer(SharedPtr certstore, void(*callback)(Socket&, Capture&&) SOUP_EXCAL, Capture&& cap = {}, tls_server_on_client_hello_t on_client_hello = nullptr) SOUP_EXCAL; + void enableCryptoServer(SharedPtr certstore, void(*callback)(Socket&, Capture&&), Capture&& cap = {}, tls_server_on_client_hello_t on_client_hello = nullptr); // Application Layer @@ -171,7 +171,7 @@ NAMESPACE_SOUP bool tls_sendRecordEncrypted(TlsContentType_t content_type, const std::string& content) SOUP_EXCAL; bool tls_sendRecordEncrypted(TlsContentType_t content_type, const void* data, size_t size) SOUP_EXCAL; - void tls_recvHandshake(UniquePtr&& handshaker, void(*callback)(Socket&, UniquePtr&&, TlsHandshakeType_t, std::string&&) SOUP_EXCAL, std::string&& pre = {}) SOUP_EXCAL; + void tls_recvHandshake(UniquePtr&& handshaker, void(*callback)(Socket&, UniquePtr&&, TlsHandshakeType_t, std::string&&), std::string&& pre = {}); void tls_recvRecord(TlsContentType_t expected_content_type, void(*callback)(Socket&, std::string&&, Capture&&), Capture&& cap = {}); // 'excal' as long as callback is void tls_recvRecord(void(*callback)(Socket&, TlsContentType_t, std::string&&, Capture&&), Capture&& cap = {}); // 'excal' as long as callback is @@ -192,6 +192,7 @@ NAMESPACE_SOUP protected: [[nodiscard]] std::string transport_recvCommon(int max_bytes) SOUP_EXCAL; public: + void transport_recv(transport_recv_callback_t callback, Capture&& cap = {}); // 'excal' as long as callback is void transport_recv(int max_bytes, transport_recv_callback_t callback, Capture&& cap = {}); // 'excal' as long as callback is void transport_recvExact(int bytes, transport_recv_callback_t callback, Capture&& cap = {}, std::string&& pre = {}); // 'excal' as long as callback is diff --git a/src/vendor/Soup/soup/SocketTlsHandshaker.cpp b/src/vendor/Soup/soup/SocketTlsHandshaker.cpp index e0a20f102..91d211c48 100644 --- a/src/vendor/Soup/soup/SocketTlsHandshaker.cpp +++ b/src/vendor/Soup/soup/SocketTlsHandshaker.cpp @@ -9,7 +9,7 @@ NAMESPACE_SOUP { - SocketTlsHandshaker::SocketTlsHandshaker(void(*callback)(Socket&, Capture&&) SOUP_EXCAL, Capture&& callback_capture) noexcept + SocketTlsHandshaker::SocketTlsHandshaker(void(*callback)(Socket&, Capture&&), Capture&& callback_capture) noexcept : callback(callback), callback_capture(std::move(callback_capture)) { layer_bytes.reserve(2800); // When we receive "finished" from Cloudflare, this is 2689~2696 bytes. diff --git a/src/vendor/Soup/soup/SocketTlsHandshaker.hpp b/src/vendor/Soup/soup/SocketTlsHandshaker.hpp index 783fc75b1..8ac104acb 100644 --- a/src/vendor/Soup/soup/SocketTlsHandshaker.hpp +++ b/src/vendor/Soup/soup/SocketTlsHandshaker.hpp @@ -19,7 +19,7 @@ NAMESPACE_SOUP class SocketTlsHandshaker { public: - void(*callback)(Socket&, Capture&&) SOUP_EXCAL; + void(*callback)(Socket&, Capture&&); Capture callback_capture; TlsCipherSuite_t cipher_suite = TLS_RSA_WITH_AES_128_CBC_SHA; @@ -45,7 +45,7 @@ NAMESPACE_SOUP void(*on_client_hello)(Socket&, TlsClientHello&&); const RsaPrivateKey* private_key{}; - explicit SocketTlsHandshaker(void(*callback)(Socket&, Capture&&) SOUP_EXCAL, Capture&& callback_capture) noexcept; + explicit SocketTlsHandshaker(void(*callback)(Socket&, Capture&&), Capture&& callback_capture) noexcept; [[nodiscard]] std::string pack(TlsHandshakeType_t handshake_type, const std::string& content) SOUP_EXCAL; diff --git a/src/vendor/Soup/soup/StringReader.hpp b/src/vendor/Soup/soup/StringReader.hpp index 187d9888f..62653de1c 100644 --- a/src/vendor/Soup/soup/StringReader.hpp +++ b/src/vendor/Soup/soup/StringReader.hpp @@ -12,17 +12,27 @@ NAMESPACE_SOUP std::string data; size_t offset = 0; - StringReader(Endian endian = ENDIAN_LITTLE) noexcept + StringReader() noexcept + : Reader(ENDIAN_LITTLE) + { + } + + [[deprecated]] StringReader(Endian endian) noexcept : Reader(endian) { } - StringReader(std::string&& data, Endian endian = ENDIAN_LITTLE) noexcept + StringReader(std::string&& data) noexcept + : Reader(ENDIAN_LITTLE), data(std::move(data)) + { + } + + [[deprecated]] StringReader(std::string&& data, Endian endian) noexcept : Reader(endian), data(std::move(data)) { } - StringReader(std::string&& data, bool little_endian) noexcept + [[deprecated]] StringReader(std::string&& data, bool little_endian) noexcept : Reader(little_endian), data(std::move(data)) { } diff --git a/src/vendor/Soup/soup/StringRefWriter.hpp b/src/vendor/Soup/soup/StringRefWriter.hpp index dada21e0f..12ef86b4c 100644 --- a/src/vendor/Soup/soup/StringRefWriter.hpp +++ b/src/vendor/Soup/soup/StringRefWriter.hpp @@ -9,7 +9,12 @@ NAMESPACE_SOUP public: std::string& str; - StringRefWriter(std::string& str, bool little_endian = true) + StringRefWriter(std::string& str) + : Writer(true), str(str) + { + } + + [[deprecated]] StringRefWriter(std::string& str, bool little_endian) : Writer(little_endian), str(str) { } @@ -28,5 +33,10 @@ NAMESPACE_SOUP } return true; } + + [[nodiscard]] size_t getPosition() final + { + return str.size(); + } }; } diff --git a/src/vendor/Soup/soup/StringWriter.hpp b/src/vendor/Soup/soup/StringWriter.hpp index 91d95d74e..0fb595ca0 100644 --- a/src/vendor/Soup/soup/StringWriter.hpp +++ b/src/vendor/Soup/soup/StringWriter.hpp @@ -9,12 +9,17 @@ NAMESPACE_SOUP public: std::string data{}; - StringWriter(Endian endian = ENDIAN_LITTLE) + StringWriter() + : Writer(ENDIAN_LITTLE) + { + } + + [[deprecated]] StringWriter(Endian endian) : Writer(endian) { } - StringWriter(bool little_endian) + [[deprecated]] StringWriter(bool little_endian) : Writer(little_endian) { } @@ -33,5 +38,10 @@ NAMESPACE_SOUP } return true; } + + [[nodiscard]] size_t getPosition() final + { + return data.size(); + } }; } diff --git a/src/vendor/Soup/soup/TlsCertificate.hpp b/src/vendor/Soup/soup/TlsCertificate.hpp index 83fed48ed..231cd41b2 100644 --- a/src/vendor/Soup/soup/TlsCertificate.hpp +++ b/src/vendor/Soup/soup/TlsCertificate.hpp @@ -10,7 +10,7 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { - return s.vec_str_lp_u24_bl_u24(asn1_certs); + return s.vec_str_lp_u24be_bl_u24be(asn1_certs); } }; } diff --git a/src/vendor/Soup/soup/TlsClientHello.hpp b/src/vendor/Soup/soup/TlsClientHello.hpp index 5910d2b5e..c4a2f71c5 100644 --- a/src/vendor/Soup/soup/TlsClientHello.hpp +++ b/src/vendor/Soup/soup/TlsClientHello.hpp @@ -24,7 +24,7 @@ NAMESPACE_SOUP return version.io(s) && random.io(s) && s.template str_lp(session_id, 32) - && s.vec_u16_bl_u16(cipher_suites) + && s.vec_u16be_bl_u16be(cipher_suites) && s.vec_u8_u8(compression_methods) && extensions.io(s) ; diff --git a/src/vendor/Soup/soup/TlsClientHelloExtEllipticCurves.hpp b/src/vendor/Soup/soup/TlsClientHelloExtEllipticCurves.hpp index 8bb68aca8..ffbbb69e6 100644 --- a/src/vendor/Soup/soup/TlsClientHelloExtEllipticCurves.hpp +++ b/src/vendor/Soup/soup/TlsClientHelloExtEllipticCurves.hpp @@ -10,7 +10,7 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { - return s.vec_u16_bl_u16(named_curves); + return s.vec_u16be_bl_u16be(named_curves); } }; } diff --git a/src/vendor/Soup/soup/TlsClientHelloExtServerName.hpp b/src/vendor/Soup/soup/TlsClientHelloExtServerName.hpp index d95a9d093..c92339d6d 100644 --- a/src/vendor/Soup/soup/TlsClientHelloExtServerName.hpp +++ b/src/vendor/Soup/soup/TlsClientHelloExtServerName.hpp @@ -13,25 +13,25 @@ NAMESPACE_SOUP if (s.isRead()) { uint16_t len = 0; - if (s.u16(len) && len > 3) + if (s.u16be(len) && len > 3) { uint8_t num_people_who_asked; if (s.u8(num_people_who_asked) && num_people_who_asked == 0 ) { - return s.template str_lp(host_name); + return s.template str_lp(host_name); } } } else if (s.isWrite()) { uint16_t len = static_cast(host_name.length() + 3); - if (s.u16(len)) + if (s.u16be(len)) { uint8_t num_people_who_asked = 0; return s.u8(num_people_who_asked) - && s.template str_lp(host_name) + && s.template str_lp(host_name) ; } } diff --git a/src/vendor/Soup/soup/TlsEncryptedPreMasterSecret.hpp b/src/vendor/Soup/soup/TlsEncryptedPreMasterSecret.hpp index 049d6f916..eadc06b36 100644 --- a/src/vendor/Soup/soup/TlsEncryptedPreMasterSecret.hpp +++ b/src/vendor/Soup/soup/TlsEncryptedPreMasterSecret.hpp @@ -10,7 +10,7 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { - return s.template str_lp(data); + return s.template str_lp(data); } }; } diff --git a/src/vendor/Soup/soup/TlsHandshake.hpp b/src/vendor/Soup/soup/TlsHandshake.hpp index 5f4786078..487dd904a 100644 --- a/src/vendor/Soup/soup/TlsHandshake.hpp +++ b/src/vendor/Soup/soup/TlsHandshake.hpp @@ -27,7 +27,7 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { return s.u8(handshake_type) - && s.u24(length) + && s.u24be(length) ; } }; diff --git a/src/vendor/Soup/soup/TlsHelloExtensions.hpp b/src/vendor/Soup/soup/TlsHelloExtensions.hpp index 23eb44819..c53d4ca7a 100644 --- a/src/vendor/Soup/soup/TlsHelloExtensions.hpp +++ b/src/vendor/Soup/soup/TlsHelloExtensions.hpp @@ -11,8 +11,8 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { - return s.u16_be(id) - && s.template str_lp(data) + return s.u16be(id) + && s.template str_lp(data) ; } }; @@ -29,7 +29,7 @@ NAMESPACE_SOUP if (s.hasMore()) { uint16_t extension_bytes; - if (!s.u16(extension_bytes)) + if (!s.u16be(extension_bytes)) { return false; } @@ -54,7 +54,7 @@ NAMESPACE_SOUP { ext_data.append(ext.toBinaryString()); } - s.template str_lp(ext_data); + s.template str_lp(ext_data); } } return true; diff --git a/src/vendor/Soup/soup/TlsMac.hpp b/src/vendor/Soup/soup/TlsMac.hpp index 08844fff5..fe30b0d2d 100644 --- a/src/vendor/Soup/soup/TlsMac.hpp +++ b/src/vendor/Soup/soup/TlsMac.hpp @@ -11,7 +11,7 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { - return s.u64_be(seq_num) + return s.u64be(seq_num) && record.io(s) ; } diff --git a/src/vendor/Soup/soup/TlsRandom.hpp b/src/vendor/Soup/soup/TlsRandom.hpp index c87d91c05..059f5741d 100644 --- a/src/vendor/Soup/soup/TlsRandom.hpp +++ b/src/vendor/Soup/soup/TlsRandom.hpp @@ -11,7 +11,7 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { - if (!s.u32_be(time)) + if (!s.u32be(time)) { return false; } diff --git a/src/vendor/Soup/soup/TlsRecord.hpp b/src/vendor/Soup/soup/TlsRecord.hpp index 062b46250..99ca0f725 100644 --- a/src/vendor/Soup/soup/TlsRecord.hpp +++ b/src/vendor/Soup/soup/TlsRecord.hpp @@ -17,7 +17,7 @@ NAMESPACE_SOUP { return s.u8(content_type) && version.io(s) - && s.u16(length) + && s.u16be(length) ; } }; diff --git a/src/vendor/Soup/soup/TlsServerHello.hpp b/src/vendor/Soup/soup/TlsServerHello.hpp index 6f9ccf8d0..712dd2e6c 100644 --- a/src/vendor/Soup/soup/TlsServerHello.hpp +++ b/src/vendor/Soup/soup/TlsServerHello.hpp @@ -24,7 +24,7 @@ NAMESPACE_SOUP return version.io(s) && random.io(s) && s.template str_lp(session_id, 32) - && s.u16(cipher_suite) + && s.u16be(cipher_suite) && s.u8(compression_method) && extensions.io(s) ; diff --git a/src/vendor/Soup/soup/TlsServerKeyExchange.hpp b/src/vendor/Soup/soup/TlsServerKeyExchange.hpp index 193689c8f..74c692ce2 100644 --- a/src/vendor/Soup/soup/TlsServerKeyExchange.hpp +++ b/src/vendor/Soup/soup/TlsServerKeyExchange.hpp @@ -14,7 +14,7 @@ NAMESPACE_SOUP { return s.u8(curve_type) && curve_type == 3 - && s.u16_be(named_curve) + && s.u16be(named_curve) && s.template str_lp(point) ; } @@ -30,8 +30,8 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { return params.io(s) - && s.u16_be(signature_scheme) - && s.template str_lp(signature) + && s.u16be(signature_scheme) + && s.template str_lp(signature) ; } }; diff --git a/src/vendor/Soup/soup/TrustStore.cpp b/src/vendor/Soup/soup/TrustStore.cpp index 43a6c2c30..c594eeeec 100644 --- a/src/vendor/Soup/soup/TrustStore.cpp +++ b/src/vendor/Soup/soup/TrustStore.cpp @@ -14,7 +14,7 @@ NAMESPACE_SOUP TrustStore TrustStore::fromMozillaImpl() SOUP_EXCAL { - // Generated by codegen/cacert.php based on the 2023-01-10 revision from https://curl.se/docs/caextract.html. + // Generated by codegen/cacert.php based on the 2024-11-26 revision from https://curl.se/docs/caextract.html. const char* cacerts[] = { "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", @@ -23,7 +23,6 @@ NAMESPACE_SOUP "MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLzRt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==", "MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u", "MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=", - "MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==", "MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxtqZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=", "MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQHmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/bvZ8=", "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJlxy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=", @@ -40,11 +39,9 @@ NAMESPACE_SOUP "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", @@ -66,7 +63,6 @@ NAMESPACE_SOUP "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", @@ -149,10 +145,29 @@ NAMESPACE_SOUP "MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxwGXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+", "MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8=", "MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR", - "MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQELBQAwgYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIFJTQSB2MzAeFw0yMDAzMTgwOTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBSU0EgdjMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J77gnJY9LTQ91ew6aEOErxjYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscxuj7X/iWpKo429NEvx7epXTPcMHD4QGxLsqYxYdE0PD0xesevxKenhOGXpOhL9hd87jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF/YP9f4RtNGx/ardLAQO/rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8qQedmCeFLl+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bGwzrwbMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4znKS4iicvObpCdg604nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBOM/J+JjKsBY04pOZ2PJ8QaQ5tndLBeSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiMbIedBi3x7+PmBvrFZhNb/FAHnnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbgh3cXTJ2w2AmoDVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSytK7mLfcm1ap1LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAImocn+M684uGMQQgC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN438o2Fi+CiJ+8EUdPdk3ILY7r3y18Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/qln0F7psTpURs+APQ3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3sSdPkvmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn99t2HVhjYsCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQmhty3QUBjYZgv6Rn7rWlDdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YAVSgU7NbHEqIbZULpkejLPoeJVF3Zr52XnGnnCv8PWniLYypMfUeUP95L6VPQMPHF9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFHIK+WEj5jlB0E5y67hscMmoi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiXYY60MGo8bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ", - "MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQzPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4WAie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3", "MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UEAxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20rhvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsENPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGmnpjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtYXLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPKp7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOfGAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0VcwCBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybSYpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHuTofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4OH3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASxYfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZXSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml+LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesnKwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg==", "MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k=", + "MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAzMTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3ZxRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZspDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O558dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgRat7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4TqnMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XKV0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZOz2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXnjSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3KliawLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u+2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkNSoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOoP2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRzznfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezyr/6zcCwupvI=", + "MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgyMVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBSb290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9BIgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK++kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJKsVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w==", + "MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccCWvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRaqCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw==", + "MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDaef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnzSDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xfiOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3XME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OASVYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgESJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu+Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+LHaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xtzwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9cmTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQYKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZAFv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjBJYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpXDhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFuiTdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAYQqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL", + "MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloXDTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTPL3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OYt6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0insS657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBOL9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77wdr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS+YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYSd66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoGAtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2fgTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0ZNbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlthEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsMQtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvfR4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJDPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeWP4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVylrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlqbLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2wAgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3qr5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sjiMho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA=", + "MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYmacCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFNSeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NWuCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeNb0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g==", + "MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBFQ0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/XtXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMDaAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtuCCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo9H1/IISpQuQo", + "MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBMMS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYvYe+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZkmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDsGY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUlnnkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzygeBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezBc6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lIpw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUdEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBDAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPso0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJqM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuywxfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgMrr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuYo7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcEoji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ==", + "MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEMBQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAeFw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEwMTlaMFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNST1QY4SxzlZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqKAtCWHwDNBSHvBm3dIZwZQ0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/VP68czH5GX6zfZBCK70bwkPAPLfSIC7Epqq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1AgdB4SQXMeJNnKziyhWTXAyB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm9WAPzJMshH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gXzhqcD0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAvkV34PmVACxmZySYgWmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msTf9FkPz2ccEblooV7WIQn3MSAPmeamseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jAuPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCFTIcQcf+eQxuulXUtgQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj7zjKsK5Xf/IhMBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4wM8zAQLpw6o1D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2XFNFV1pF1AWZLy4jVe5jaN/TG3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNjduMNhXJEIlU/HHzp/LgV6FL6qj6jITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstlcHboCoWASzY9M/eVVHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys+TIxxHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1onAX1daBli2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d7XB4tmBZrOFdRWOPyN9yaFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2NtjjgKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpoFGWsJwt0ivKH", + "MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0yMTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATxs8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbwLxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJijYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mDpm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiRUKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA==", + "MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNaFw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLxeP0CflfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJEhRGnSjot6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggqhkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liWpDVfG2XqYZpwI7UNo5uSUm9poIyNStDuiw7LR47QjRE=", + "MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRaFw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/MMDALj2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmUv4RDsNuESgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggqhkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/nich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs73u1Z/GtMMH9ZzkXpc2AVmkzw5l4lIhVtwodZ0LKOag==", + "MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQELBQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3QtMDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45FtnYSkYZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslhsuitQDy6uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0alDrJLpA6lfO741GIDuZNqihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3OjWiE260f6GBfZumbCk6SP/F2krfxQapWsvCQz0b2If4b19bJzKo98rwjyGpg/qYFlP8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/cZip8UlF1y5mO6D1cv547KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTifBSeolz7pUcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/kQO9lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JOHg9O5j9ZpSPcPYeoKFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkBEa801M/XrmLTBQe0MXXgDW1XT2mH+VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6UCBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm45P3luG0wDQYJKoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQnmhUQo8mUuJM3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+QgvfKNmwrZggvkN80V4aCRckjXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2vtrV0KnahP/t1MJ+UXjulYPPLXAziDslg+MkfFoom3ecnf+slpoq9uC02EJqxWE2aaE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/WNyVntHKLr4W96ioDj8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+o/E4Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0wlREQKC6/oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHnYfkUyq+Dj7+vsQpZXdxc1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVocicCMb3SgazNNtQEo/a2tiRc7ppqEvOuM6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw", + "MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQELBQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3QtMDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3VrCLENQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0kyI9p+Kx7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1CrWDaSWqVcN3SAOLMV2MCe5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxzhkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2WWy09X6GDRl224yW4fKcZgBzqZUPckXk2LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rpM9kzXzehxfCrPfp4sOcsn/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIfhs1w/tkuFT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5kQMreyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3wNemKfrb3vOTlycEVS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6vwQcQeKwRoi9C8DfF8rhW3Q5iLc4tVn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7GxcJXvYXowDQYJKoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqBKCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3+VGXu6TwYofF1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbymeAPnCKfWxkxlSaRosTKCL4BWaMS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3NyqpgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xdgSGn2rtO/+YHqP65DSdsu3BaVXoT6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2OHG1QAk8mGEPej1WFsQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+NmYWvtPjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2dlklyALKrdVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670v64fG9PiO/yzcnMcmyiQiRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17Org3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7", + "MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIwMB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIzNTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqGSM49AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/OtdKPD/M12kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDPf8iAC8GXs7s1J8nCG6NCMEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6fMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Diz6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn27iQ7t0l", + "MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAyMDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMyNzIzNTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9cUD/h3VCKSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHVcp6R+SPWcHu79ZvB7JPPGeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMAU6DksquDOFczJZSfvkgdmOGjup5czQRxUX11eKvzWarE4GC+j4NSuHUaQTXtvPM6Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWol8hHD/BeEIvnHRz+sTugBTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9FIS3R/qy8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73Jco4vzLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg8qKrBC7m8kwOFjQgrIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8rFEz0ciD0cmfHdRHNCk+y7AO+oMLKFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7SWWO/gLCMk3PLNaaZlSJhZQNg+y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtqeXgj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQpGv7qHBFfLp+sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm9S3ul0A8Yute1hTWjOKWi0FpkzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErwM807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy/SKE8YXJN3nptT+/XOR0so8RYgDdGGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4mZqTuXNnQkYRIer+CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtzaL1txKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+w6jv/naaoqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aKL4x35bcF7DvB7L6Gs4a8wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+ljX273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4QntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgmdTdmQRCsu/WU48IxK63nI1bMNSWSs1A=", + "MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQswCQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENBIFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2WhcNNDcwMzMxMDkwMTM2WjBuMQswCQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENBIFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zfe9MEkVz6iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6CcyvHZpsKjECcfIr28jlgst7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FDY1w8ndYn81LsF7Kpryz3dvgwHQYDVR0OBBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFwhVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dGXSaQpYXFuXqUPoeovQA=", + "MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1sTs6P40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxFavcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684iJkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfuj3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupfXtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDAS9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDAoS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzCkHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAdBgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIBAGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0ttGlTITVX1olNc79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn68xDiBaiA9a5F/gZbG0jAn/xX9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNnTKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7tRCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq/p1hvIbZv97Tujqxf36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0RFxbIQh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzXxeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X", + "MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mtp7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zdJ1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gurFzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOCAQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==", + "MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEMBQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgwNzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh1oq/FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOgvlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9JkdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXiby8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac18izju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIABSMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVLApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0ErX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ibed87hwriZLoAymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopTzfFP7ELyk+OZpDc8h7hi2/DsHzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHSDCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPGFrojutzdfhrGe0K22VoF3Jpf1d+42kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6qnsb58Nn4DSEC5MUoFlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/OfVyK4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtlLor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39cJRNItX+S", + "MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMyNTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5GdCx4wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSRZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6bkU6iYAZezKYVWOr62Nuk22rGwlgMU4=", }; TrustStore ts; ts.data.reserve(COUNT(cacerts)); diff --git a/src/vendor/Soup/soup/Writer.cpp b/src/vendor/Soup/soup/Writer.cpp index 1dcaeca12..8bd54e81e 100644 --- a/src/vendor/Soup/soup/Writer.cpp +++ b/src/vendor/Soup/soup/Writer.cpp @@ -4,6 +4,7 @@ NAMESPACE_SOUP { bool Writer::u64_dyn(const uint64_t& v) noexcept { + bool ret = true; uint64_t in = v; for (uint8_t i = 0; i != 8; ++i) { @@ -12,19 +13,20 @@ NAMESPACE_SOUP if (in != 0) { cur |= 0x80; - u8(cur); + ret &= u8(cur); } else { - return u8(cur); + ret &= u8(cur); + return ret; } } if (in != 0) { auto byte = (uint8_t)in; - return u8(byte); + ret &= u8(byte); } - return true; + return ret; } bool Writer::i64_dyn(const int64_t& v) noexcept @@ -42,6 +44,50 @@ NAMESPACE_SOUP return u64_dyn(((uint64_t)neg << 6) | ((u & ~0x3f) << 1) | (u & 0x3f)); } + bool Writer::u64_dyn_v2(const uint64_t& v) noexcept + { + bool ret = true; + uint64_t in = v; + uint8_t cur; + for (uint8_t i = 0; i != 8; ++i) + { + cur = (in & 0x7f); + in >>= 7; + if (in != 0) + { + cur |= 0x80; + ret &= u8(cur); + in -= 1; // v2 + } + else + { + ret &= u8(cur); + return ret; + } + } + if (cur >> 7) // Last byte indicated another one would follow? + { + cur = (uint8_t)in; + ret &= u8(cur); + } + return ret; + } + + bool Writer::i64_dyn_v2(const int64_t& v) noexcept + { + uint64_t u; + bool neg = (v < 0); + if (neg) + { + u = (v * -1) - 1; + } + else + { + u = v; + } + return u64_dyn_v2(((uint64_t)neg << 6) | ((u & ~0x3f) << 1) | (u & 0x3f)); + } + bool Writer::mysql_lenenc(const uint64_t& v) noexcept { if (v < 0xFB) @@ -53,16 +99,16 @@ NAMESPACE_SOUP { uint8_t prefix = 0xFC; auto val = (uint16_t)v; - return u8(prefix) && u16_le(val); + return u8(prefix) && u16le(val); } else if (v <= 0xFFFFFF) { uint8_t prefix = 0xFD; auto val = (uint32_t)v; - return u8(prefix) && u24_le(val); + return u8(prefix) && u24le(val); } uint8_t prefix = 0xFE; auto val = v; - return u8(prefix) && u64_le(val); + return u8(prefix) && u64le(val); } } diff --git a/src/vendor/Soup/soup/Writer.hpp b/src/vendor/Soup/soup/Writer.hpp index 830e3a80f..06781f22c 100644 --- a/src/vendor/Soup/soup/Writer.hpp +++ b/src/vendor/Soup/soup/Writer.hpp @@ -28,6 +28,12 @@ NAMESPACE_SOUP // A signed 64-bit integer encoded in 1..9 bytes. (Specialisation of u64_dyn.) bool i64_dyn(const int64_t& v) noexcept; + // An unsigned 64-bit integer encoded in 1..9 bytes. This is a slightly more efficient version of u64_dyn, e.g. 0x4000..0x407f are encoded in 2 bytes instead of 3. + bool u64_dyn_v2(const uint64_t& v) noexcept; + + // A signed 64-bit integer encoded in 1..9 bytes. (Specialisation of u64_dyn_v2. This revision also simplifies how negative integers are handled.) + bool i64_dyn_v2(const int64_t& v) noexcept; + // An integer where every byte's most significant bit is used to indicate if another byte follows, most significant byte first. template bool om(const Int& v) noexcept @@ -149,36 +155,6 @@ NAMESPACE_SOUP return ret; } - // Length-prefixed string, using u8 for the length prefix. - [[deprecated]] bool str_lp_u8(const std::string& v, const uint8_t max_len = 0xFF) noexcept - { - return str_lp(v, max_len); - } - - // Length-prefixed string, using u16 for the length prefix. - [[deprecated]] bool str_lp_u16(const std::string& v, const uint16_t max_len = 0xFFFF) noexcept - { - return str_lp(v, max_len); - } - - // Length-prefixed string, using u24 for the length prefix. - [[deprecated]] bool str_lp_u24(const std::string& v, const uint32_t max_len = 0xFFFFFF) noexcept - { - return str_lp(v, max_len); - } - - // Length-prefixed string, using u32 for the length prefix. - [[deprecated]] bool str_lp_u32(const std::string& v, const uint32_t max_len = 0xFFFFFFFF) noexcept - { - return str_lp(v, max_len); - } - - // Length-prefixed string, using u64 for the length prefix. - [[deprecated]] bool str_lp_u64(const std::string& v) noexcept - { - return str_lp(v); - } - // String with known length. bool str(size_t len, const std::string& v) noexcept { @@ -211,25 +187,8 @@ NAMESPACE_SOUP return ret; } - // std::vector with u16 size prefix. - bool vec_u16_u16(std::vector& v) noexcept - { - SOUP_IF_UNLIKELY (v.size() > 0xFFFF) - { - return false; - } - bool ret = true; - auto len = (uint16_t)v.size(); - ret &= ioBase::u16(len); - for (auto& entry : v) - { - ret &= ioBase::u16(entry); - } - return ret; - } - - // std::vector with u16 byte length prefix. - bool vec_u16_bl_u16(std::vector& v) noexcept + // vector of u16be with u16be byte length prefix. + bool vec_u16be_bl_u16be(std::vector& v) noexcept { size_t bl = (v.size() * sizeof(uint16_t)); SOUP_IF_UNLIKELY (bl > 0xFFFF) @@ -238,10 +197,10 @@ NAMESPACE_SOUP } bool ret = true; auto bl_u16 = (uint16_t)bl; - ret &= ioBase::u16(bl_u16); + ret &= ioBase::u16be(bl_u16); for (auto& entry : v) { - ret &= ioBase::u16(entry); + ret &= ioBase::u16be(entry); } return ret; } @@ -259,8 +218,8 @@ NAMESPACE_SOUP return ret; } - // vector of str_lp with u24 byte length prefix. - bool vec_str_lp_u24_bl_u24(std::vector& v) noexcept + // vector of str_lp with u24be byte length prefix. + bool vec_str_lp_u24be_bl_u24be(std::vector& v) noexcept { size_t bl = (v.size() * 3); for (const auto& entry : v) @@ -273,10 +232,10 @@ NAMESPACE_SOUP } bool ret = true; auto bl_u32 = (uint32_t)bl; - ret &= ioBase::u24(bl_u32); + ret &= ioBase::u24be(bl_u32); for (auto& entry : v) { - ret &= str_lp(entry); + ret &= str_lp(entry); } return ret; } diff --git a/src/vendor/Soup/soup/aes.cpp b/src/vendor/Soup/soup/aes.cpp index 0f1b5d564..fed8fcf95 100644 --- a/src/vendor/Soup/soup/aes.cpp +++ b/src/vendor/Soup/soup/aes.cpp @@ -1,21 +1,22 @@ #include "aes.hpp" +#include // ceil #include // memcpy #include "base.hpp" -#if defined(SOUP_USE_INTRIN) && SOUP_BITS == 64 && (SOUP_X86 || SOUP_ARM) -#define AES_USE_INTRIN true +#if SOUP_BITS == 64 && (SOUP_X86 || SOUP_ARM) + #define AES_USE_INTRIN true #else -#define AES_USE_INTRIN false + #define AES_USE_INTRIN false #endif #if AES_USE_INTRIN -#include "CpuInfo.hpp" + #include "aes_intrin.hpp" + #include "CpuInfo.hpp" #endif #include "Endian.hpp" -#include "plusaes.hpp" /* Original source: https://github.com/SergeyBel/AES @@ -42,6 +43,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +// https://github.com/kkAyataka/plusaes was also used a reference for AES-GCM + #if SOUP_X86 #define IS_AES_INTRIN_AVAILBLE CpuInfo::get().supportsAESNI() #else @@ -50,24 +53,6 @@ SOFTWARE. NAMESPACE_SOUP { -#if AES_USE_INTRIN - namespace intrin - { - extern void aes_expand_key_128(uint8_t w[176], const uint8_t key[16]) noexcept; - extern void aes_expand_key_192(uint8_t w[208], const uint8_t key[24]) noexcept; - extern void aes_expand_key_256(uint8_t w[240], const uint8_t key[32]) noexcept; - extern void aes_encrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept; - extern void aes_encrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept; - extern void aes_encrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept; - extern void aes_prepare_decryption_128(uint8_t w[176]) noexcept; - extern void aes_prepare_decryption_192(uint8_t w[208]) noexcept; - extern void aes_prepare_decryption_256(uint8_t w[240]) noexcept; - extern void aes_decrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept; - extern void aes_decrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept; - extern void aes_decrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept; - } -#endif - static constexpr int Nb = 4; static constexpr unsigned int blockBytesLen = 4 * Nb * sizeof(uint8_t); @@ -451,7 +436,7 @@ NAMESPACE_SOUP } } - void aes::gcmEncrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, uint8_t tag[16]) SOUP_EXCAL + void aes::gcmEncrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, uint8_t tag[16]) noexcept { const auto Nr = getNrFromKeyLen(key_len); alignas(16) uint8_t roundKeys[240]; @@ -475,7 +460,7 @@ NAMESPACE_SOUP calcGcmTag(tag, data, data_len, aadata, aadata_len, roundKeys, Nr, h, j0); } - bool aes::gcmDecrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, const uint8_t tag[16]) SOUP_EXCAL + bool aes::gcmDecrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, const uint8_t tag[16]) noexcept { const auto Nr = getNrFromKeyLen(key_len); alignas(16) uint8_t roundKeys[240]; @@ -892,9 +877,15 @@ NAMESPACE_SOUP void aes::xorBlocks(uint8_t a[16], const uint8_t b[16]) noexcept { -#if SOUP_BITS == 64 +#if SOUP_BITS >= 64 + // Could use _mm_xor_si128 if target supports SSE2 reinterpret_cast(a)[0] ^= reinterpret_cast(b)[0]; reinterpret_cast(a)[1] ^= reinterpret_cast(b)[1]; +#elif SOUP_BITS >= 32 + reinterpret_cast(a)[0] ^= reinterpret_cast(b)[0]; + reinterpret_cast(a)[1] ^= reinterpret_cast(b)[1]; + reinterpret_cast(a)[2] ^= reinterpret_cast(b)[2]; + reinterpret_cast(a)[3] ^= reinterpret_cast(b)[3]; #else for (unsigned int i = 0; i != 16; ++i) { @@ -911,11 +902,34 @@ NAMESPACE_SOUP } } - void aes::ghash(uint8_t res[16], const uint8_t h[16], const std::vector& x) noexcept + void aes::rshiftBlock(uint8_t block[16]) noexcept + { + for (int i = 15; i > 0; --i) + { + block[i] = (block[i] >> 1) | (block[i - 1] << 7); + } + block[0] >>= 1; + } + + void aes::mulBlocks(uint8_t res[16], const uint8_t x[16], const uint8_t y[16]) noexcept { - plusaes::detail::gcm::Block bH(h, 16); - auto bRes = plusaes::detail::gcm::ghash(bH, x); - memcpy(res, bRes.data(), 16); + memset(res, 0, 16); + uint8_t v[16]; + memcpy(v, y, 16); + for (uint8_t i = 0; i != 128; ++i) + { + if ((x[i / 8] >> (7 - (i % 8))) & 1) + { + xorBlocks(res, v); + } + + const bool lsb_set = v[15] & 1; + rshiftBlock(v); + if (lsb_set) + { + v[0] ^= 0xe1; + } + } } void aes::calcH(uint8_t h[16], uint8_t roundKeys[240], const int Nr) noexcept @@ -924,7 +938,7 @@ NAMESPACE_SOUP aes::encryptBlock(h, h, roundKeys, Nr); } - void aes::calcJ0(uint8_t j0[16], const uint8_t h[16], const uint8_t* iv, size_t iv_len) SOUP_EXCAL + void aes::calcJ0(uint8_t j0[16], const uint8_t h[16], const uint8_t* iv, size_t iv_len) noexcept { if (iv_len == 12) { @@ -936,15 +950,21 @@ NAMESPACE_SOUP } else { - const auto len_iv = iv_len * 8; - const auto s = 128 * plusaes::detail::gcm::ceil(len_iv / 128.0) - len_iv; - std::vector ghash_in; - ghash_in.reserve(32); - plusaes::detail::gcm::push_back(ghash_in, iv, iv_len); - plusaes::detail::gcm::push_back_zero_bits(ghash_in, s + 64); - plusaes::detail::gcm::push_back(ghash_in, std::bitset<64>(len_iv)); + GhashState state(j0, h); + state.append(iv, iv_len); + + const uint64_t iv_bits = iv_len * 8; + auto padding = (128 * static_cast(std::ceil(iv_bits / 128.0) + 0.5) - iv_bits) / 8; + while (padding--) + { + state.appendByte(0); + } + + memset(state.buffer, 0, 16); + reinterpret_cast(state.buffer)[1] = Endianness::invert(iv_bits); static_assert(ENDIAN_NATIVE == ENDIAN_LITTLE); + state.transform(); - return ghash(j0, h, ghash_in); + SOUP_DEBUG_ASSERT(state.buffer_counter == 0); } } @@ -985,22 +1005,38 @@ NAMESPACE_SOUP } } - void aes::calcGcmTag(uint8_t tag[16], uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t roundKeys[16], const int Nr, const uint8_t h[16], const uint8_t j0[16]) SOUP_EXCAL + void aes::calcGcmTag(uint8_t tag[16], uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t roundKeys[16], const int Nr, const uint8_t h[16], const uint8_t j0[16]) noexcept { - const auto lenC = data_len * 8; - const auto lenA = aadata_len * 8; - const std::size_t u = 128 * plusaes::detail::gcm::ceil(lenC / 128.0) - lenC; - const std::size_t v = 128 * plusaes::detail::gcm::ceil(lenA / 128.0) - lenA; + const uint64_t lenC = data_len * 8; + const uint64_t lenA = aadata_len * 8; + auto u = (128 * static_cast(std::ceil(lenC / 128.0) + 0.5) - lenC) / 8; + auto v = (128 * static_cast(std::ceil(lenA / 128.0) + 0.5) - lenA) / 8; + uint8_t z[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + GhashState state(tag, h); + state.append(aadata, aadata_len); + while (v--) { state.appendByte(0); } + state.append(data, data_len); + while (u--) { state.appendByte(0); } + *reinterpret_cast(z) = Endianness::invert(lenA); state.append(z, 8); static_assert(ENDIAN_NATIVE == ENDIAN_LITTLE); + *reinterpret_cast(z) = Endianness::invert(lenC); state.append(z, 8); static_assert(ENDIAN_NATIVE == ENDIAN_LITTLE); + SOUP_DEBUG_ASSERT(state.buffer_counter == 0); - std::vector ghash_in; - ghash_in.reserve((aadata_len + v / 8) + (data_len + u / 8) + 8 + 8); - plusaes::detail::gcm::push_back(ghash_in, aadata, aadata_len); - plusaes::detail::gcm::push_back_zero_bits(ghash_in, v); - plusaes::detail::gcm::push_back(ghash_in, data, data_len); - plusaes::detail::gcm::push_back_zero_bits(ghash_in, u); - plusaes::detail::gcm::push_back(ghash_in, std::bitset<64>(lenA)); - plusaes::detail::gcm::push_back(ghash_in, std::bitset<64>(lenC)); - ghash(tag, h, ghash_in); gctr(tag, 16, roundKeys, Nr, j0); } + + aes::GhashState::GhashState(uint8_t res[16], const uint8_t h[16]) noexcept + : res(res), h(h), buffer_counter(0) + { + memset(res, 0, 16); + } + + void aes::GhashState::transform() noexcept + { + xorBlocks(res, buffer); + + uint8_t tmp[16]; + memcpy(tmp, res, 16); + mulBlocks(res, tmp, h); + } } diff --git a/src/vendor/Soup/soup/aes.hpp b/src/vendor/Soup/soup/aes.hpp index ef394a536..7f94e897a 100644 --- a/src/vendor/Soup/soup/aes.hpp +++ b/src/vendor/Soup/soup/aes.hpp @@ -2,15 +2,13 @@ #include #include -#include #include "base.hpp" // SOUP_EXCAL NAMESPACE_SOUP { - class aes + struct aes { - public: // Input size should be a multiple of 16 bytes. // GCM can deal with unaligned data, other methods will simply ignore the trailing bytes -> they will not be encrypted. // You may use a padding scheme such as PKCS#7 for padding. @@ -25,10 +23,10 @@ NAMESPACE_SOUP static void cfbDecrypt(uint8_t* data, size_t data_len, const uint8_t* key, size_t key_len, const uint8_t iv[16]) noexcept; static void ecbEncrypt(uint8_t* data, size_t data_len, const uint8_t* key, size_t key_len) noexcept; static void ecbDecrypt(uint8_t* data, size_t data_len, const uint8_t* key, size_t key_len) noexcept; - static void gcmEncrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, uint8_t tag[16]) SOUP_EXCAL; - static bool gcmDecrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, const uint8_t tag[16]) SOUP_EXCAL; + static void gcmEncrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, uint8_t tag[16]) noexcept; + static bool gcmDecrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, const uint8_t tag[16]) noexcept; + - private: static void expandKey(uint8_t w[240], const uint8_t* key, size_t key_len) noexcept; static void expandKeyForDecryption(uint8_t w[240], const uint8_t* key, size_t key_len) noexcept; [[nodiscard]] static int getNk(size_t key_len) noexcept; @@ -53,11 +51,42 @@ NAMESPACE_SOUP static SOUP_FORCEINLINE void xorBlocks(uint8_t a[16], const uint8_t b[16]) noexcept; static void xorBlocks(uint8_t a[], const uint8_t b[], unsigned int len) noexcept; - static void ghash(uint8_t res[16], const uint8_t h[16], const std::vector& x) noexcept; + static SOUP_FORCEINLINE void rshiftBlock(uint8_t block[16]) noexcept; + static void mulBlocks(uint8_t res[16], const uint8_t x[16], const uint8_t y[16]) noexcept; static void calcH(uint8_t h[16], uint8_t roundKeys[240], const int Nr) noexcept; - static void calcJ0(uint8_t j0[16], const uint8_t h[16], const uint8_t* iv, size_t iv_len) SOUP_EXCAL; + static void calcJ0(uint8_t j0[16], const uint8_t h[16], const uint8_t* iv, size_t iv_len) noexcept; static void inc32(uint8_t block[16]) noexcept; static void gctr(uint8_t* data, size_t data_len, const uint8_t roundKeys[240], const int Nr, const uint8_t icb[8]) noexcept; - static void calcGcmTag(uint8_t tag[16], uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t roundKeys[16], const int Nr, const uint8_t h[16], const uint8_t j0[16]) SOUP_EXCAL; + static void calcGcmTag(uint8_t tag[16], uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t roundKeys[16], const int Nr, const uint8_t h[16], const uint8_t j0[16]) noexcept; + + struct GhashState + { + uint8_t* const res; + const uint8_t* const h; + uint8_t buffer[16]; + uint8_t buffer_counter; + + GhashState(uint8_t res[16], const uint8_t h[16]) noexcept; + + void append(const uint8_t data[], size_t size) noexcept + { + for (size_t i = 0; i != size; ++i) + { + appendByte(data[i]); + } + } + + void appendByte(uint8_t byte) noexcept + { + buffer[buffer_counter] = byte; + if (++buffer_counter == 16) + { + buffer_counter = 0; + transform(); + } + } + + void transform() noexcept; + }; }; } diff --git a/src/vendor/Soup/Intrin/aes_helper.cpp b/src/vendor/Soup/soup/aes_intrin.hpp similarity index 91% rename from src/vendor/Soup/Intrin/aes_helper.cpp rename to src/vendor/Soup/soup/aes_intrin.hpp index 83973632e..5a381614f 100644 --- a/src/vendor/Soup/Intrin/aes_helper.cpp +++ b/src/vendor/Soup/soup/aes_intrin.hpp @@ -1,450 +1,519 @@ -#include "../soup/base.hpp" - -#include - -#if SOUP_X86 - #include -#elif SOUP_ARM - #include -#endif - -// x86: -// - https://gist.github.com/acapola/d5b940da024080dfaf5f -// - https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf -// ARM: -// - https://blog.michaelbrase.com/2018/06/04/optimizing-x86-aes-intrinsics-on-armv8-a/ - -NAMESPACE_SOUP -{ - namespace intrin - { -#if SOUP_X86 - [[nodiscard]] static __m128i aes_expand_key_step(__m128i key0, __m128i key1) noexcept - { - key0 = _mm_xor_si128(key0, _mm_slli_si128(key0, 4)); - key0 = _mm_xor_si128(key0, _mm_slli_si128(key0, 4)); - key0 = _mm_xor_si128(key0, _mm_slli_si128(key0, 4)); - return _mm_xor_si128(key0, _mm_shuffle_epi32(key1, 0xff)); - } - - [[nodiscard]] static __m128i aes_expand_key_odd_step(__m128i key0, __m128i key1) noexcept - { - key0 = _mm_aeskeygenassist_si128(key0, 0); - key1 = _mm_xor_si128(key1, _mm_slli_si128(key1, 4)); - key1 = _mm_xor_si128(key1, _mm_slli_si128(key1, 4)); - key1 = _mm_xor_si128(key1, _mm_slli_si128(key1, 4)); - return _mm_xor_si128(key1, _mm_shuffle_epi32(key0, 0xaa)); - } - - void aes_expand_key_128(uint8_t w[176], const uint8_t key[16]) noexcept - { - reinterpret_cast<__m128i*>(w)[0] = _mm_loadu_si128(reinterpret_cast(key)); - reinterpret_cast<__m128i*>(w)[1] = aes_expand_key_step(reinterpret_cast(w)[0], _mm_aeskeygenassist_si128(reinterpret_cast(w)[0], 0x01)); - reinterpret_cast<__m128i*>(w)[2] = aes_expand_key_step(reinterpret_cast(w)[1], _mm_aeskeygenassist_si128(reinterpret_cast(w)[1], 0x02)); - reinterpret_cast<__m128i*>(w)[3] = aes_expand_key_step(reinterpret_cast(w)[2], _mm_aeskeygenassist_si128(reinterpret_cast(w)[2], 0x04)); - reinterpret_cast<__m128i*>(w)[4] = aes_expand_key_step(reinterpret_cast(w)[3], _mm_aeskeygenassist_si128(reinterpret_cast(w)[3], 0x08)); - reinterpret_cast<__m128i*>(w)[5] = aes_expand_key_step(reinterpret_cast(w)[4], _mm_aeskeygenassist_si128(reinterpret_cast(w)[4], 0x10)); - reinterpret_cast<__m128i*>(w)[6] = aes_expand_key_step(reinterpret_cast(w)[5], _mm_aeskeygenassist_si128(reinterpret_cast(w)[5], 0x20)); - reinterpret_cast<__m128i*>(w)[7] = aes_expand_key_step(reinterpret_cast(w)[6], _mm_aeskeygenassist_si128(reinterpret_cast(w)[6], 0x40)); - reinterpret_cast<__m128i*>(w)[8] = aes_expand_key_step(reinterpret_cast(w)[7], _mm_aeskeygenassist_si128(reinterpret_cast(w)[7], 0x80)); - reinterpret_cast<__m128i*>(w)[9] = aes_expand_key_step(reinterpret_cast(w)[8], _mm_aeskeygenassist_si128(reinterpret_cast(w)[8], 0x1B)); - reinterpret_cast<__m128i*>(w)[10] = aes_expand_key_step(reinterpret_cast(w)[9], _mm_aeskeygenassist_si128(reinterpret_cast(w)[9], 0x36)); - } - - static void KEY_192_ASSIST(__m128i* temp1, __m128i* temp2, __m128i* temp3) noexcept - { - __m128i temp4; - *temp2 = _mm_shuffle_epi32(*temp2, 0x55); - temp4 = _mm_slli_si128(*temp1, 0x4); - *temp1 = _mm_xor_si128(*temp1, temp4); - temp4 = _mm_slli_si128(temp4, 0x4); - *temp1 = _mm_xor_si128(*temp1, temp4); - temp4 = _mm_slli_si128(temp4, 0x4); - *temp1 = _mm_xor_si128(*temp1, temp4); - *temp1 = _mm_xor_si128(*temp1, *temp2); - *temp2 = _mm_shuffle_epi32(*temp1, 0xff); - temp4 = _mm_slli_si128(*temp3, 0x4); - *temp3 = _mm_xor_si128(*temp3, temp4); - *temp3 = _mm_xor_si128(*temp3, *temp2); - } - - void aes_expand_key_192(uint8_t w[208], const uint8_t key[24]) noexcept - { - __m128i temp1, temp2, temp3; - __m128i* Key_Schedule = (__m128i*)w; - temp1 = _mm_loadu_si128((__m128i*)key); - temp3 = _mm_set_epi64x(0, *reinterpret_cast(key + 16)); - Key_Schedule[0] = temp1; - Key_Schedule[1] = temp3; - temp2 = _mm_aeskeygenassist_si128(temp3, 0x1); - KEY_192_ASSIST(&temp1, &temp2, &temp3); - Key_Schedule[1] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(Key_Schedule[1]), _mm_castsi128_pd(temp1), 0)); - Key_Schedule[2] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1)); - temp2 = _mm_aeskeygenassist_si128(temp3, 0x2); - KEY_192_ASSIST(&temp1, &temp2, &temp3); - Key_Schedule[3] = temp1; - Key_Schedule[4] = temp3; - temp2 = _mm_aeskeygenassist_si128(temp3, 0x4); - KEY_192_ASSIST(&temp1, &temp2, &temp3); - Key_Schedule[4] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(Key_Schedule[4]), _mm_castsi128_pd(temp1), 0)); - Key_Schedule[5] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1)); - temp2 = _mm_aeskeygenassist_si128(temp3, 0x8); - KEY_192_ASSIST(&temp1, &temp2, &temp3); - Key_Schedule[6] = temp1; - Key_Schedule[7] = temp3; - temp2 = _mm_aeskeygenassist_si128(temp3, 0x10); - KEY_192_ASSIST(&temp1, &temp2, &temp3); - Key_Schedule[7] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(Key_Schedule[7]), _mm_castsi128_pd(temp1), 0)); - Key_Schedule[8] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1)); - temp2 = _mm_aeskeygenassist_si128(temp3, 0x20); - KEY_192_ASSIST(&temp1, &temp2, &temp3); - Key_Schedule[9] = temp1; - Key_Schedule[10] = temp3; - temp2 = _mm_aeskeygenassist_si128(temp3, 0x40); - KEY_192_ASSIST(&temp1, &temp2, &temp3); - Key_Schedule[10] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(Key_Schedule[10]), _mm_castsi128_pd(temp1), 0)); - Key_Schedule[11] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1)); - temp2 = _mm_aeskeygenassist_si128(temp3, 0x80); - KEY_192_ASSIST(&temp1, &temp2, &temp3); - Key_Schedule[12] = temp1; - } - - void aes_expand_key_256(uint8_t w[240], const uint8_t key[32]) noexcept - { - reinterpret_cast<__m128i*>(w)[0] = _mm_loadu_si128(&reinterpret_cast(key)[0]); - reinterpret_cast<__m128i*>(w)[1] = _mm_loadu_si128(&reinterpret_cast(key)[1]); - reinterpret_cast<__m128i*>(w)[2] = aes_expand_key_step(reinterpret_cast(w)[0], _mm_aeskeygenassist_si128(reinterpret_cast(w)[1], 0x01)); - reinterpret_cast<__m128i*>(w)[3] = aes_expand_key_odd_step(reinterpret_cast(w)[2], reinterpret_cast<__m128i*>(w)[1]); - reinterpret_cast<__m128i*>(w)[4] = aes_expand_key_step(reinterpret_cast(w)[2], _mm_aeskeygenassist_si128(reinterpret_cast(w)[3], 0x02)); - reinterpret_cast<__m128i*>(w)[5] = aes_expand_key_odd_step(reinterpret_cast(w)[4], reinterpret_cast<__m128i*>(w)[3]); - reinterpret_cast<__m128i*>(w)[6] = aes_expand_key_step(reinterpret_cast(w)[4], _mm_aeskeygenassist_si128(reinterpret_cast(w)[5], 0x04)); - reinterpret_cast<__m128i*>(w)[7] = aes_expand_key_odd_step(reinterpret_cast(w)[6], reinterpret_cast<__m128i*>(w)[5]); - reinterpret_cast<__m128i*>(w)[8] = aes_expand_key_step(reinterpret_cast(w)[6], _mm_aeskeygenassist_si128(reinterpret_cast(w)[7], 0x08)); - reinterpret_cast<__m128i*>(w)[9] = aes_expand_key_odd_step(reinterpret_cast(w)[8], reinterpret_cast<__m128i*>(w)[7]); - reinterpret_cast<__m128i*>(w)[10] = aes_expand_key_step(reinterpret_cast(w)[8], _mm_aeskeygenassist_si128(reinterpret_cast(w)[9], 0x10)); - reinterpret_cast<__m128i*>(w)[11] = aes_expand_key_odd_step(reinterpret_cast(w)[10], reinterpret_cast<__m128i*>(w)[9]); - reinterpret_cast<__m128i*>(w)[12] = aes_expand_key_step(reinterpret_cast(w)[10], _mm_aeskeygenassist_si128(reinterpret_cast(w)[11], 0x20)); - reinterpret_cast<__m128i*>(w)[13] = aes_expand_key_odd_step(reinterpret_cast(w)[12], reinterpret_cast<__m128i*>(w)[11]); - reinterpret_cast<__m128i*>(w)[14] = aes_expand_key_step(reinterpret_cast(w)[12], _mm_aeskeygenassist_si128(reinterpret_cast(w)[13], 0x40)); - } - - void aes_encrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept - { - __m128i data = *reinterpret_cast(in); - data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[0]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[1]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[2]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[3]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[4]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[5]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[6]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[7]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[8]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[9]); - data = _mm_aesenclast_si128(data, reinterpret_cast(roundKeys)[10]); - *reinterpret_cast<__m128i*>(out) = data; - } - - void aes_encrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept - { - __m128i data = *reinterpret_cast(in); - data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[0]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[1]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[2]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[3]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[4]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[5]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[6]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[7]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[8]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[9]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[10]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[11]); - data = _mm_aesenclast_si128(data, reinterpret_cast(roundKeys)[12]); - *reinterpret_cast<__m128i*>(out) = data; - } - - void aes_encrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept - { - __m128i data = *reinterpret_cast(in); - data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[0]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[1]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[2]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[3]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[4]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[5]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[6]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[7]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[8]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[9]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[10]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[11]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[12]); - data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[13]); - data = _mm_aesenclast_si128(data, reinterpret_cast(roundKeys)[14]); - *reinterpret_cast<__m128i*>(out) = data; - } - - void aes_prepare_decryption_128(uint8_t w[176]) noexcept - { - reinterpret_cast<__m128i*>(w)[1] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[1]); - reinterpret_cast<__m128i*>(w)[2] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[2]); - reinterpret_cast<__m128i*>(w)[3] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[3]); - reinterpret_cast<__m128i*>(w)[4] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[4]); - reinterpret_cast<__m128i*>(w)[5] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[5]); - reinterpret_cast<__m128i*>(w)[6] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[6]); - reinterpret_cast<__m128i*>(w)[7] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[7]); - reinterpret_cast<__m128i*>(w)[8] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[8]); - reinterpret_cast<__m128i*>(w)[9] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[9]); - } - - void aes_prepare_decryption_192(uint8_t w[208]) noexcept - { - reinterpret_cast<__m128i*>(w)[1] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[1]); - reinterpret_cast<__m128i*>(w)[2] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[2]); - reinterpret_cast<__m128i*>(w)[3] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[3]); - reinterpret_cast<__m128i*>(w)[4] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[4]); - reinterpret_cast<__m128i*>(w)[5] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[5]); - reinterpret_cast<__m128i*>(w)[6] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[6]); - reinterpret_cast<__m128i*>(w)[7] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[7]); - reinterpret_cast<__m128i*>(w)[8] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[8]); - reinterpret_cast<__m128i*>(w)[9] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[9]); - reinterpret_cast<__m128i*>(w)[10] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[10]); - reinterpret_cast<__m128i*>(w)[11] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[11]); - } - - void aes_prepare_decryption_256(uint8_t w[240]) noexcept - { - reinterpret_cast<__m128i*>(w)[1] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[1]); - reinterpret_cast<__m128i*>(w)[2] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[2]); - reinterpret_cast<__m128i*>(w)[3] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[3]); - reinterpret_cast<__m128i*>(w)[4] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[4]); - reinterpret_cast<__m128i*>(w)[5] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[5]); - reinterpret_cast<__m128i*>(w)[6] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[6]); - reinterpret_cast<__m128i*>(w)[7] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[7]); - reinterpret_cast<__m128i*>(w)[8] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[8]); - reinterpret_cast<__m128i*>(w)[9] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[9]); - reinterpret_cast<__m128i*>(w)[10] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[10]); - reinterpret_cast<__m128i*>(w)[11] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[11]); - reinterpret_cast<__m128i*>(w)[12] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[12]); - reinterpret_cast<__m128i*>(w)[13] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[13]); - } - - void aes_decrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept - { - __m128i data = *reinterpret_cast(in); - data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[10]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[9]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[8]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[7]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[6]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[5]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[4]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[3]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[2]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[1]); - data = _mm_aesdeclast_si128(data, reinterpret_cast(roundKeys)[0]); - *reinterpret_cast<__m128i*>(out) = data; - } - - void aes_decrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept - { - __m128i data = *reinterpret_cast(in); - data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[12]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[11]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[10]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[9]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[8]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[7]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[6]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[5]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[4]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[3]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[2]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[1]); - data = _mm_aesdeclast_si128(data, reinterpret_cast(roundKeys)[0]); - *reinterpret_cast<__m128i*>(out) = data; - } - - void aes_decrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept - { - __m128i data = *reinterpret_cast(in); - data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[14]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[13]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[12]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[11]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[10]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[9]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[8]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[7]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[6]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[5]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[4]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[3]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[2]); - data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[1]); - data = _mm_aesdeclast_si128(data, reinterpret_cast(roundKeys)[0]); - *reinterpret_cast<__m128i*>(out) = data; - } -#elif SOUP_ARM - void aes_encrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept - { - auto data = vld1q_u8(in); - data = vaeseq_u8(data, vld1q_u8(&roundKeys[0 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[1 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[2 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[3 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[4 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[5 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[6 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[7 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[8 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[9 * 16])); - data = veorq_u8(data, vld1q_u8(&roundKeys[10 * 16])); - vst1q_u8(out, data); - } - - void aes_encrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept - { - auto data = vld1q_u8(in); - data = vaeseq_u8(data, vld1q_u8(&roundKeys[0 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[1 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[2 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[3 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[4 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[5 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[6 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[7 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[8 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[9 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[10 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[11 * 16])); - data = veorq_u8(data, vld1q_u8(&roundKeys[12 * 16])); - vst1q_u8(out, data); - } - - void aes_encrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept - { - auto data = vld1q_u8(in); - data = vaeseq_u8(data, vld1q_u8(&roundKeys[0 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[1 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[2 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[3 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[4 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[5 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[6 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[7 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[8 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[9 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[10 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[11 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[12 * 16])); - data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[13 * 16])); - data = veorq_u8(data, vld1q_u8(&roundKeys[14 * 16])); - vst1q_u8(out, data); - } - - void aes_prepare_decryption_128(uint8_t w[176]) noexcept - { - vst1q_u8(&w[1 * 16], vaesimcq_u8(vld1q_u8(&w[1 * 16]))); - vst1q_u8(&w[2 * 16], vaesimcq_u8(vld1q_u8(&w[2 * 16]))); - vst1q_u8(&w[3 * 16], vaesimcq_u8(vld1q_u8(&w[3 * 16]))); - vst1q_u8(&w[4 * 16], vaesimcq_u8(vld1q_u8(&w[4 * 16]))); - vst1q_u8(&w[5 * 16], vaesimcq_u8(vld1q_u8(&w[5 * 16]))); - vst1q_u8(&w[6 * 16], vaesimcq_u8(vld1q_u8(&w[6 * 16]))); - vst1q_u8(&w[7 * 16], vaesimcq_u8(vld1q_u8(&w[7 * 16]))); - vst1q_u8(&w[8 * 16], vaesimcq_u8(vld1q_u8(&w[8 * 16]))); - vst1q_u8(&w[9 * 16], vaesimcq_u8(vld1q_u8(&w[9 * 16]))); - } - - void aes_prepare_decryption_192(uint8_t w[208]) noexcept - { - vst1q_u8(&w[1 * 16], vaesimcq_u8(vld1q_u8(&w[1 * 16]))); - vst1q_u8(&w[2 * 16], vaesimcq_u8(vld1q_u8(&w[2 * 16]))); - vst1q_u8(&w[3 * 16], vaesimcq_u8(vld1q_u8(&w[3 * 16]))); - vst1q_u8(&w[4 * 16], vaesimcq_u8(vld1q_u8(&w[4 * 16]))); - vst1q_u8(&w[5 * 16], vaesimcq_u8(vld1q_u8(&w[5 * 16]))); - vst1q_u8(&w[6 * 16], vaesimcq_u8(vld1q_u8(&w[6 * 16]))); - vst1q_u8(&w[7 * 16], vaesimcq_u8(vld1q_u8(&w[7 * 16]))); - vst1q_u8(&w[8 * 16], vaesimcq_u8(vld1q_u8(&w[8 * 16]))); - vst1q_u8(&w[9 * 16], vaesimcq_u8(vld1q_u8(&w[9 * 16]))); - vst1q_u8(&w[10 * 16], vaesimcq_u8(vld1q_u8(&w[10 * 16]))); - vst1q_u8(&w[11 * 16], vaesimcq_u8(vld1q_u8(&w[11 * 16]))); - } - - void aes_prepare_decryption_256(uint8_t w[240]) noexcept - { - vst1q_u8(&w[1 * 16], vaesimcq_u8(vld1q_u8(&w[1 * 16]))); - vst1q_u8(&w[2 * 16], vaesimcq_u8(vld1q_u8(&w[2 * 16]))); - vst1q_u8(&w[3 * 16], vaesimcq_u8(vld1q_u8(&w[3 * 16]))); - vst1q_u8(&w[4 * 16], vaesimcq_u8(vld1q_u8(&w[4 * 16]))); - vst1q_u8(&w[5 * 16], vaesimcq_u8(vld1q_u8(&w[5 * 16]))); - vst1q_u8(&w[6 * 16], vaesimcq_u8(vld1q_u8(&w[6 * 16]))); - vst1q_u8(&w[7 * 16], vaesimcq_u8(vld1q_u8(&w[7 * 16]))); - vst1q_u8(&w[8 * 16], vaesimcq_u8(vld1q_u8(&w[8 * 16]))); - vst1q_u8(&w[9 * 16], vaesimcq_u8(vld1q_u8(&w[9 * 16]))); - vst1q_u8(&w[10 * 16], vaesimcq_u8(vld1q_u8(&w[10 * 16]))); - vst1q_u8(&w[11 * 16], vaesimcq_u8(vld1q_u8(&w[11 * 16]))); - vst1q_u8(&w[12 * 16], vaesimcq_u8(vld1q_u8(&w[12 * 16]))); - vst1q_u8(&w[13 * 16], vaesimcq_u8(vld1q_u8(&w[13 * 16]))); - } - - void aes_decrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept - { - auto data = vld1q_u8(in); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[10 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[9 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[8 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[7 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[6 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[5 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[4 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[3 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[2 * 16]))); - data = vaesdq_u8(data, vld1q_u8(&roundKeys[1 * 16])); - data = veorq_u8(data, vld1q_u8(&roundKeys[0 * 16])); - vst1q_u8(out, data); - } - - void aes_decrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept - { - auto data = vld1q_u8(in); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[12 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[11 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[10 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[9 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[8 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[7 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[6 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[5 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[4 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[3 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[2 * 16]))); - data = vaesdq_u8(data, vld1q_u8(&roundKeys[1 * 16])); - data = veorq_u8(data, vld1q_u8(&roundKeys[0 * 16])); - vst1q_u8(out, data); - } - - void aes_decrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept - { - auto data = vld1q_u8(in); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[14 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[13 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[12 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[11 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[10 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[9 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[8 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[7 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[6 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[5 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[4 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[3 * 16]))); - data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[2 * 16]))); - data = vaesdq_u8(data, vld1q_u8(&roundKeys[1 * 16])); - data = veorq_u8(data, vld1q_u8(&roundKeys[0 * 16])); - vst1q_u8(out, data); - } -#endif - } -} +// THIS FILE IS FOR INTERNAL USE ONLY. DO NOT INCLUDE THIS IN YOUR OWN CODE. + +#include "base.hpp" + +#include + +#if SOUP_X86 + #include +#elif SOUP_ARM + #include +#endif + +// x86: +// - https://gist.github.com/acapola/d5b940da024080dfaf5f +// - https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf +// ARM: +// - https://blog.michaelbrase.com/2018/06/04/optimizing-x86-aes-intrinsics-on-armv8-a/ + +NAMESPACE_SOUP +{ + namespace intrin + { +#if SOUP_X86 + [[nodiscard]] static __m128i aes_expand_key_step(__m128i key0, __m128i key1) noexcept + { + key0 = _mm_xor_si128(key0, _mm_slli_si128(key0, 4)); + key0 = _mm_xor_si128(key0, _mm_slli_si128(key0, 4)); + key0 = _mm_xor_si128(key0, _mm_slli_si128(key0, 4)); + return _mm_xor_si128(key0, _mm_shuffle_epi32(key1, 0xff)); + } + + [[nodiscard]] + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + static __m128i aes_expand_key_odd_step(__m128i key0, __m128i key1) noexcept + { + key0 = _mm_aeskeygenassist_si128(key0, 0); + key1 = _mm_xor_si128(key1, _mm_slli_si128(key1, 4)); + key1 = _mm_xor_si128(key1, _mm_slli_si128(key1, 4)); + key1 = _mm_xor_si128(key1, _mm_slli_si128(key1, 4)); + return _mm_xor_si128(key1, _mm_shuffle_epi32(key0, 0xaa)); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_expand_key_128(uint8_t w[176], const uint8_t key[16]) noexcept + { + reinterpret_cast<__m128i*>(w)[0] = _mm_loadu_si128(reinterpret_cast(key)); + reinterpret_cast<__m128i*>(w)[1] = aes_expand_key_step(reinterpret_cast(w)[0], _mm_aeskeygenassist_si128(reinterpret_cast(w)[0], 0x01)); + reinterpret_cast<__m128i*>(w)[2] = aes_expand_key_step(reinterpret_cast(w)[1], _mm_aeskeygenassist_si128(reinterpret_cast(w)[1], 0x02)); + reinterpret_cast<__m128i*>(w)[3] = aes_expand_key_step(reinterpret_cast(w)[2], _mm_aeskeygenassist_si128(reinterpret_cast(w)[2], 0x04)); + reinterpret_cast<__m128i*>(w)[4] = aes_expand_key_step(reinterpret_cast(w)[3], _mm_aeskeygenassist_si128(reinterpret_cast(w)[3], 0x08)); + reinterpret_cast<__m128i*>(w)[5] = aes_expand_key_step(reinterpret_cast(w)[4], _mm_aeskeygenassist_si128(reinterpret_cast(w)[4], 0x10)); + reinterpret_cast<__m128i*>(w)[6] = aes_expand_key_step(reinterpret_cast(w)[5], _mm_aeskeygenassist_si128(reinterpret_cast(w)[5], 0x20)); + reinterpret_cast<__m128i*>(w)[7] = aes_expand_key_step(reinterpret_cast(w)[6], _mm_aeskeygenassist_si128(reinterpret_cast(w)[6], 0x40)); + reinterpret_cast<__m128i*>(w)[8] = aes_expand_key_step(reinterpret_cast(w)[7], _mm_aeskeygenassist_si128(reinterpret_cast(w)[7], 0x80)); + reinterpret_cast<__m128i*>(w)[9] = aes_expand_key_step(reinterpret_cast(w)[8], _mm_aeskeygenassist_si128(reinterpret_cast(w)[8], 0x1B)); + reinterpret_cast<__m128i*>(w)[10] = aes_expand_key_step(reinterpret_cast(w)[9], _mm_aeskeygenassist_si128(reinterpret_cast(w)[9], 0x36)); + } + + static void KEY_192_ASSIST(__m128i* temp1, __m128i* temp2, __m128i* temp3) noexcept + { + __m128i temp4; + *temp2 = _mm_shuffle_epi32(*temp2, 0x55); + temp4 = _mm_slli_si128(*temp1, 0x4); + *temp1 = _mm_xor_si128(*temp1, temp4); + temp4 = _mm_slli_si128(temp4, 0x4); + *temp1 = _mm_xor_si128(*temp1, temp4); + temp4 = _mm_slli_si128(temp4, 0x4); + *temp1 = _mm_xor_si128(*temp1, temp4); + *temp1 = _mm_xor_si128(*temp1, *temp2); + *temp2 = _mm_shuffle_epi32(*temp1, 0xff); + temp4 = _mm_slli_si128(*temp3, 0x4); + *temp3 = _mm_xor_si128(*temp3, temp4); + *temp3 = _mm_xor_si128(*temp3, *temp2); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_expand_key_192(uint8_t w[208], const uint8_t key[24]) noexcept + { + __m128i temp1, temp2, temp3; + __m128i* Key_Schedule = (__m128i*)w; + temp1 = _mm_loadu_si128((__m128i*)key); + temp3 = _mm_set_epi64x(0, *reinterpret_cast(key + 16)); + Key_Schedule[0] = temp1; + Key_Schedule[1] = temp3; + temp2 = _mm_aeskeygenassist_si128(temp3, 0x1); + KEY_192_ASSIST(&temp1, &temp2, &temp3); + Key_Schedule[1] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(Key_Schedule[1]), _mm_castsi128_pd(temp1), 0)); + Key_Schedule[2] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1)); + temp2 = _mm_aeskeygenassist_si128(temp3, 0x2); + KEY_192_ASSIST(&temp1, &temp2, &temp3); + Key_Schedule[3] = temp1; + Key_Schedule[4] = temp3; + temp2 = _mm_aeskeygenassist_si128(temp3, 0x4); + KEY_192_ASSIST(&temp1, &temp2, &temp3); + Key_Schedule[4] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(Key_Schedule[4]), _mm_castsi128_pd(temp1), 0)); + Key_Schedule[5] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1)); + temp2 = _mm_aeskeygenassist_si128(temp3, 0x8); + KEY_192_ASSIST(&temp1, &temp2, &temp3); + Key_Schedule[6] = temp1; + Key_Schedule[7] = temp3; + temp2 = _mm_aeskeygenassist_si128(temp3, 0x10); + KEY_192_ASSIST(&temp1, &temp2, &temp3); + Key_Schedule[7] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(Key_Schedule[7]), _mm_castsi128_pd(temp1), 0)); + Key_Schedule[8] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1)); + temp2 = _mm_aeskeygenassist_si128(temp3, 0x20); + KEY_192_ASSIST(&temp1, &temp2, &temp3); + Key_Schedule[9] = temp1; + Key_Schedule[10] = temp3; + temp2 = _mm_aeskeygenassist_si128(temp3, 0x40); + KEY_192_ASSIST(&temp1, &temp2, &temp3); + Key_Schedule[10] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(Key_Schedule[10]), _mm_castsi128_pd(temp1), 0)); + Key_Schedule[11] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1)); + temp2 = _mm_aeskeygenassist_si128(temp3, 0x80); + KEY_192_ASSIST(&temp1, &temp2, &temp3); + Key_Schedule[12] = temp1; + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_expand_key_256(uint8_t w[240], const uint8_t key[32]) noexcept + { + reinterpret_cast<__m128i*>(w)[0] = _mm_loadu_si128(&reinterpret_cast(key)[0]); + reinterpret_cast<__m128i*>(w)[1] = _mm_loadu_si128(&reinterpret_cast(key)[1]); + reinterpret_cast<__m128i*>(w)[2] = aes_expand_key_step(reinterpret_cast(w)[0], _mm_aeskeygenassist_si128(reinterpret_cast(w)[1], 0x01)); + reinterpret_cast<__m128i*>(w)[3] = aes_expand_key_odd_step(reinterpret_cast(w)[2], reinterpret_cast<__m128i*>(w)[1]); + reinterpret_cast<__m128i*>(w)[4] = aes_expand_key_step(reinterpret_cast(w)[2], _mm_aeskeygenassist_si128(reinterpret_cast(w)[3], 0x02)); + reinterpret_cast<__m128i*>(w)[5] = aes_expand_key_odd_step(reinterpret_cast(w)[4], reinterpret_cast<__m128i*>(w)[3]); + reinterpret_cast<__m128i*>(w)[6] = aes_expand_key_step(reinterpret_cast(w)[4], _mm_aeskeygenassist_si128(reinterpret_cast(w)[5], 0x04)); + reinterpret_cast<__m128i*>(w)[7] = aes_expand_key_odd_step(reinterpret_cast(w)[6], reinterpret_cast<__m128i*>(w)[5]); + reinterpret_cast<__m128i*>(w)[8] = aes_expand_key_step(reinterpret_cast(w)[6], _mm_aeskeygenassist_si128(reinterpret_cast(w)[7], 0x08)); + reinterpret_cast<__m128i*>(w)[9] = aes_expand_key_odd_step(reinterpret_cast(w)[8], reinterpret_cast<__m128i*>(w)[7]); + reinterpret_cast<__m128i*>(w)[10] = aes_expand_key_step(reinterpret_cast(w)[8], _mm_aeskeygenassist_si128(reinterpret_cast(w)[9], 0x10)); + reinterpret_cast<__m128i*>(w)[11] = aes_expand_key_odd_step(reinterpret_cast(w)[10], reinterpret_cast<__m128i*>(w)[9]); + reinterpret_cast<__m128i*>(w)[12] = aes_expand_key_step(reinterpret_cast(w)[10], _mm_aeskeygenassist_si128(reinterpret_cast(w)[11], 0x20)); + reinterpret_cast<__m128i*>(w)[13] = aes_expand_key_odd_step(reinterpret_cast(w)[12], reinterpret_cast<__m128i*>(w)[11]); + reinterpret_cast<__m128i*>(w)[14] = aes_expand_key_step(reinterpret_cast(w)[12], _mm_aeskeygenassist_si128(reinterpret_cast(w)[13], 0x40)); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_encrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept + { + __m128i data = *reinterpret_cast(in); + data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[0]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[1]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[2]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[3]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[4]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[5]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[6]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[7]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[8]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[9]); + data = _mm_aesenclast_si128(data, reinterpret_cast(roundKeys)[10]); + *reinterpret_cast<__m128i*>(out) = data; + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_encrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept + { + __m128i data = *reinterpret_cast(in); + data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[0]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[1]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[2]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[3]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[4]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[5]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[6]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[7]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[8]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[9]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[10]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[11]); + data = _mm_aesenclast_si128(data, reinterpret_cast(roundKeys)[12]); + *reinterpret_cast<__m128i*>(out) = data; + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_encrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept + { + __m128i data = *reinterpret_cast(in); + data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[0]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[1]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[2]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[3]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[4]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[5]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[6]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[7]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[8]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[9]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[10]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[11]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[12]); + data = _mm_aesenc_si128(data, reinterpret_cast(roundKeys)[13]); + data = _mm_aesenclast_si128(data, reinterpret_cast(roundKeys)[14]); + *reinterpret_cast<__m128i*>(out) = data; + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_prepare_decryption_128(uint8_t w[176]) noexcept + { + reinterpret_cast<__m128i*>(w)[1] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[1]); + reinterpret_cast<__m128i*>(w)[2] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[2]); + reinterpret_cast<__m128i*>(w)[3] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[3]); + reinterpret_cast<__m128i*>(w)[4] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[4]); + reinterpret_cast<__m128i*>(w)[5] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[5]); + reinterpret_cast<__m128i*>(w)[6] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[6]); + reinterpret_cast<__m128i*>(w)[7] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[7]); + reinterpret_cast<__m128i*>(w)[8] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[8]); + reinterpret_cast<__m128i*>(w)[9] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[9]); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_prepare_decryption_192(uint8_t w[208]) noexcept + { + reinterpret_cast<__m128i*>(w)[1] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[1]); + reinterpret_cast<__m128i*>(w)[2] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[2]); + reinterpret_cast<__m128i*>(w)[3] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[3]); + reinterpret_cast<__m128i*>(w)[4] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[4]); + reinterpret_cast<__m128i*>(w)[5] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[5]); + reinterpret_cast<__m128i*>(w)[6] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[6]); + reinterpret_cast<__m128i*>(w)[7] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[7]); + reinterpret_cast<__m128i*>(w)[8] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[8]); + reinterpret_cast<__m128i*>(w)[9] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[9]); + reinterpret_cast<__m128i*>(w)[10] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[10]); + reinterpret_cast<__m128i*>(w)[11] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[11]); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_prepare_decryption_256(uint8_t w[240]) noexcept + { + reinterpret_cast<__m128i*>(w)[1] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[1]); + reinterpret_cast<__m128i*>(w)[2] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[2]); + reinterpret_cast<__m128i*>(w)[3] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[3]); + reinterpret_cast<__m128i*>(w)[4] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[4]); + reinterpret_cast<__m128i*>(w)[5] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[5]); + reinterpret_cast<__m128i*>(w)[6] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[6]); + reinterpret_cast<__m128i*>(w)[7] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[7]); + reinterpret_cast<__m128i*>(w)[8] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[8]); + reinterpret_cast<__m128i*>(w)[9] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[9]); + reinterpret_cast<__m128i*>(w)[10] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[10]); + reinterpret_cast<__m128i*>(w)[11] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[11]); + reinterpret_cast<__m128i*>(w)[12] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[12]); + reinterpret_cast<__m128i*>(w)[13] = _mm_aesimc_si128(reinterpret_cast<__m128i*>(w)[13]); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_decrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept + { + __m128i data = *reinterpret_cast(in); + data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[10]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[9]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[8]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[7]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[6]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[5]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[4]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[3]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[2]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[1]); + data = _mm_aesdeclast_si128(data, reinterpret_cast(roundKeys)[0]); + *reinterpret_cast<__m128i*>(out) = data; + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_decrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept + { + __m128i data = *reinterpret_cast(in); + data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[12]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[11]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[10]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[9]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[8]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[7]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[6]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[5]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[4]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[3]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[2]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[1]); + data = _mm_aesdeclast_si128(data, reinterpret_cast(roundKeys)[0]); + *reinterpret_cast<__m128i*>(out) = data; + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_decrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept + { + __m128i data = *reinterpret_cast(in); + data = _mm_xor_si128(data, reinterpret_cast(roundKeys)[14]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[13]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[12]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[11]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[10]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[9]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[8]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[7]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[6]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[5]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[4]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[3]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[2]); + data = _mm_aesdec_si128(data, reinterpret_cast(roundKeys)[1]); + data = _mm_aesdeclast_si128(data, reinterpret_cast(roundKeys)[0]); + *reinterpret_cast<__m128i*>(out) = data; + } +#elif SOUP_ARM + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_encrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept + { + auto data = vld1q_u8(in); + data = vaeseq_u8(data, vld1q_u8(&roundKeys[0 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[1 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[2 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[3 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[4 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[5 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[6 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[7 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[8 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[9 * 16])); + data = veorq_u8(data, vld1q_u8(&roundKeys[10 * 16])); + vst1q_u8(out, data); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_encrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept + { + auto data = vld1q_u8(in); + data = vaeseq_u8(data, vld1q_u8(&roundKeys[0 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[1 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[2 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[3 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[4 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[5 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[6 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[7 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[8 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[9 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[10 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[11 * 16])); + data = veorq_u8(data, vld1q_u8(&roundKeys[12 * 16])); + vst1q_u8(out, data); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_encrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept + { + auto data = vld1q_u8(in); + data = vaeseq_u8(data, vld1q_u8(&roundKeys[0 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[1 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[2 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[3 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[4 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[5 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[6 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[7 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[8 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[9 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[10 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[11 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[12 * 16])); + data = vaeseq_u8(vaesmcq_u8(data), vld1q_u8(&roundKeys[13 * 16])); + data = veorq_u8(data, vld1q_u8(&roundKeys[14 * 16])); + vst1q_u8(out, data); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_prepare_decryption_128(uint8_t w[176]) noexcept + { + vst1q_u8(&w[1 * 16], vaesimcq_u8(vld1q_u8(&w[1 * 16]))); + vst1q_u8(&w[2 * 16], vaesimcq_u8(vld1q_u8(&w[2 * 16]))); + vst1q_u8(&w[3 * 16], vaesimcq_u8(vld1q_u8(&w[3 * 16]))); + vst1q_u8(&w[4 * 16], vaesimcq_u8(vld1q_u8(&w[4 * 16]))); + vst1q_u8(&w[5 * 16], vaesimcq_u8(vld1q_u8(&w[5 * 16]))); + vst1q_u8(&w[6 * 16], vaesimcq_u8(vld1q_u8(&w[6 * 16]))); + vst1q_u8(&w[7 * 16], vaesimcq_u8(vld1q_u8(&w[7 * 16]))); + vst1q_u8(&w[8 * 16], vaesimcq_u8(vld1q_u8(&w[8 * 16]))); + vst1q_u8(&w[9 * 16], vaesimcq_u8(vld1q_u8(&w[9 * 16]))); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_prepare_decryption_192(uint8_t w[208]) noexcept + { + vst1q_u8(&w[1 * 16], vaesimcq_u8(vld1q_u8(&w[1 * 16]))); + vst1q_u8(&w[2 * 16], vaesimcq_u8(vld1q_u8(&w[2 * 16]))); + vst1q_u8(&w[3 * 16], vaesimcq_u8(vld1q_u8(&w[3 * 16]))); + vst1q_u8(&w[4 * 16], vaesimcq_u8(vld1q_u8(&w[4 * 16]))); + vst1q_u8(&w[5 * 16], vaesimcq_u8(vld1q_u8(&w[5 * 16]))); + vst1q_u8(&w[6 * 16], vaesimcq_u8(vld1q_u8(&w[6 * 16]))); + vst1q_u8(&w[7 * 16], vaesimcq_u8(vld1q_u8(&w[7 * 16]))); + vst1q_u8(&w[8 * 16], vaesimcq_u8(vld1q_u8(&w[8 * 16]))); + vst1q_u8(&w[9 * 16], vaesimcq_u8(vld1q_u8(&w[9 * 16]))); + vst1q_u8(&w[10 * 16], vaesimcq_u8(vld1q_u8(&w[10 * 16]))); + vst1q_u8(&w[11 * 16], vaesimcq_u8(vld1q_u8(&w[11 * 16]))); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_prepare_decryption_256(uint8_t w[240]) noexcept + { + vst1q_u8(&w[1 * 16], vaesimcq_u8(vld1q_u8(&w[1 * 16]))); + vst1q_u8(&w[2 * 16], vaesimcq_u8(vld1q_u8(&w[2 * 16]))); + vst1q_u8(&w[3 * 16], vaesimcq_u8(vld1q_u8(&w[3 * 16]))); + vst1q_u8(&w[4 * 16], vaesimcq_u8(vld1q_u8(&w[4 * 16]))); + vst1q_u8(&w[5 * 16], vaesimcq_u8(vld1q_u8(&w[5 * 16]))); + vst1q_u8(&w[6 * 16], vaesimcq_u8(vld1q_u8(&w[6 * 16]))); + vst1q_u8(&w[7 * 16], vaesimcq_u8(vld1q_u8(&w[7 * 16]))); + vst1q_u8(&w[8 * 16], vaesimcq_u8(vld1q_u8(&w[8 * 16]))); + vst1q_u8(&w[9 * 16], vaesimcq_u8(vld1q_u8(&w[9 * 16]))); + vst1q_u8(&w[10 * 16], vaesimcq_u8(vld1q_u8(&w[10 * 16]))); + vst1q_u8(&w[11 * 16], vaesimcq_u8(vld1q_u8(&w[11 * 16]))); + vst1q_u8(&w[12 * 16], vaesimcq_u8(vld1q_u8(&w[12 * 16]))); + vst1q_u8(&w[13 * 16], vaesimcq_u8(vld1q_u8(&w[13 * 16]))); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_decrypt_block_128(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[176]) noexcept + { + auto data = vld1q_u8(in); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[10 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[9 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[8 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[7 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[6 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[5 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[4 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[3 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[2 * 16]))); + data = vaesdq_u8(data, vld1q_u8(&roundKeys[1 * 16])); + data = veorq_u8(data, vld1q_u8(&roundKeys[0 * 16])); + vst1q_u8(out, data); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_decrypt_block_192(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[208]) noexcept + { + auto data = vld1q_u8(in); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[12 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[11 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[10 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[9 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[8 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[7 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[6 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[5 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[4 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[3 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[2 * 16]))); + data = vaesdq_u8(data, vld1q_u8(&roundKeys[1 * 16])); + data = veorq_u8(data, vld1q_u8(&roundKeys[0 * 16])); + vst1q_u8(out, data); + } + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("aes"))) + #endif + void aes_decrypt_block_256(const uint8_t in[16], uint8_t out[16], const uint8_t roundKeys[240]) noexcept + { + auto data = vld1q_u8(in); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[14 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[13 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[12 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[11 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[10 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[9 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[8 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[7 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[6 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[5 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[4 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[3 * 16]))); + data = vaesimcq_u8(vaesdq_u8(data, vld1q_u8(&roundKeys[2 * 16]))); + data = vaesdq_u8(data, vld1q_u8(&roundKeys[1 * 16])); + data = veorq_u8(data, vld1q_u8(&roundKeys[0 * 16])); + vst1q_u8(out, data); + } +#endif + } +} diff --git a/src/vendor/Soup/soup/base.hpp b/src/vendor/Soup/soup/base.hpp index 86415f330..f995e5707 100644 --- a/src/vendor/Soup/soup/base.hpp +++ b/src/vendor/Soup/soup/base.hpp @@ -79,11 +79,13 @@ namespace soup { namespace pluto_vendored {}; using namespace pluto_vendored; }; #if defined(_MSC_VER) && !defined(__clang__) #define SOUP_FORCEINLINE __forceinline #define SOUP_NOINLINE __declspec(noinline) - #define SOUP_PURE + #define SOUP_PURE __declspec(noalias) + #define SOUP_UNIQADDR __restrict #else #define SOUP_FORCEINLINE __attribute__((always_inline)) inline #define SOUP_NOINLINE __attribute__((noinline)) #define SOUP_PURE __attribute__((pure)) + #define SOUP_UNIQADDR __restrict__ #endif // === CPU macros @@ -102,16 +104,13 @@ namespace soup { namespace pluto_vendored {}; using namespace pluto_vendored; }; #if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) #define SOUP_ARM true + #if defined(__clang_major__) && __clang_major__ <= 14 && !defined(__ARM_FEATURE_CRYPTO) + #error Your version of Clang predates some important fixes for ARM codegen. Provide -march=armv8+crypto+crc to compile Soup. Note that the resulting binary may be incorrect. + #endif #else #define SOUP_ARM false #endif -#if 'ABCD' == 0x41424344ul - #define SOUP_LITTLE_ENDIAN -#else - static_assert('ABCD' == 0x44434241ul); // If it's not little endian, it has to be big endian. -#endif - // === Determine if code inspector #ifdef __INTELLISENSE__ @@ -191,12 +190,9 @@ namespace soup { namespace pluto_vendored {}; using namespace pluto_vendored; }; #endif #ifndef SOUP_EXCAL - // An 'excal' function is 'noexcept' except it may throw std::bad_alloc. - // - // We generally don't attempt to handle allocation failures, not least because it's basically impossible on modern systems. - // Because of this, we declare that 'excal' functions are 'noexcept' to avoid superfluous unwind information. + // An 'excal' function may not throw any exception other than std::bad_alloc (in case of an allocation failure). // - // For visual distinction with IDE hover features, we use `throw()`, but it's functionally identical to `noexcept`. + // If you don't handle allocate failures, you can slightly reduce your binary size by setting this macro to `noexcept` or `throw()`. #define SOUP_EXCAL #endif diff --git a/src/vendor/Soup/soup/bitutil.hpp b/src/vendor/Soup/soup/bitutil.hpp index ee68c54f8..69c6a6708 100644 --- a/src/vendor/Soup/soup/bitutil.hpp +++ b/src/vendor/Soup/soup/bitutil.hpp @@ -102,6 +102,7 @@ NAMESPACE_SOUP #endif } +#if SOUP_BITS >= 64 [[nodiscard]] static unsigned long getLeastSignificantSetBit(uint64_t mask) noexcept { SOUP_DEBUG_ASSERT(mask != 0); // UB! @@ -115,6 +116,7 @@ NAMESPACE_SOUP return __builtin_ctz(mask); #endif } +#endif template static constexpr void unsetLeastSignificantSetBit(T& val) diff --git a/src/vendor/Soup/soup/crc32.cpp b/src/vendor/Soup/soup/crc32.cpp index c4ef61ce0..e84c0e6e9 100644 --- a/src/vendor/Soup/soup/crc32.cpp +++ b/src/vendor/Soup/soup/crc32.cpp @@ -2,14 +2,15 @@ #include "base.hpp" -#if defined(SOUP_USE_INTRIN) && SOUP_BITS == 64 && (SOUP_X86 || SOUP_ARM) -#define CRC32_USE_INTRIN true +#if SOUP_BITS == 64 && (SOUP_X86 || SOUP_ARM) + #define CRC32_USE_INTRIN true #else -#define CRC32_USE_INTRIN false + #define CRC32_USE_INTRIN false #endif #if CRC32_USE_INTRIN -#include "CpuInfo.hpp" + #include "crc32_intrin.hpp" + #include "CpuInfo.hpp" #endif #include "Endian.hpp" #include "Reader.hpp" @@ -19,14 +20,6 @@ NAMESPACE_SOUP { -#if CRC32_USE_INTRIN - namespace intrin - { - extern uint32_t crc32_pclmul(const uint8_t* p, size_t size, uint32_t crc) noexcept; - extern uint32_t crc32_armv8(const uint8_t* p, size_t size, uint32_t crc) noexcept; - } -#endif - static const uint32_t crc32_lookup4[4][256] = { {00, 016701630226, 035603460454, 023102250672, 0733342031, 016032572217, 035130722465, 023631112643, 01666704062, 017167134244, 034065364436, 022764554610, 01155446053, 017654276275, 034756026407, 022057616621, 03555610144, 015254020362, 036356270510, 020457440736, 03266552175, 015567362353, 036465132521, 020364702707, 02333114126, 014432724300, 037530574572, 021231344754, 02400256117, 014301466331, 037203636543, 021502006765, 07333420310, 011432210136, 032530040744, 024231670562, 07400762321, 011301152107, 032203302775, 024502532553, 06555324372, 010254514154, 033356744726, 025457174500, 06266066343, 010567656165, 033465406717, 025364236531, 04666230254, 012167400072, 031065650600, 027764060426, 04155172265, 012654742043, 031756512631, 027057322417, 05000534236, 013701304010, 030603154662, 026102764444, 05733676207, 013032046021, 030130216653, 026631426475, diff --git a/src/vendor/Soup/Intrin/crc32_intrin.cpp b/src/vendor/Soup/soup/crc32_intrin.hpp similarity index 87% rename from src/vendor/Soup/Intrin/crc32_intrin.cpp rename to src/vendor/Soup/soup/crc32_intrin.hpp index 7ade7b6e5..fa5de710b 100644 --- a/src/vendor/Soup/Intrin/crc32_intrin.cpp +++ b/src/vendor/Soup/soup/crc32_intrin.hpp @@ -1,4 +1,6 @@ -#include "../soup/base.hpp" +// THIS FILE IS FOR INTERNAL USE ONLY. DO NOT INCLUDE THIS IN YOUR OWN CODE. + +#include "base.hpp" #include #include @@ -7,7 +9,7 @@ #include // _mm_extract_epi32 #include // _mm_clmulepi64_si128 #elif SOUP_ARM - #if SOUP_WINDOWS + #if defined(_MSC_VER) && !defined(__clang__) #include #else #include @@ -19,6 +21,9 @@ NAMESPACE_SOUP namespace intrin { #if SOUP_X86 + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("sse4.1,pclmul"))) + #endif uint32_t crc32_pclmul(const uint8_t* p, size_t size, uint32_t crc) noexcept { // Original source: https://github.com/richgel999/fpng/blob/main/src/fpng.cpp @@ -48,6 +53,9 @@ NAMESPACE_SOUP return ~_mm_extract_epi32(_mm_xor_si128(b, _mm_clmulepi64_si128(_mm_and_si128(_mm_clmulepi64_si128(_mm_and_si128(b, z), u, 16), z), u, 0)), 1); } #elif SOUP_ARM + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("crc"))) + #endif uint32_t crc32_armv8(const uint8_t* p, size_t size, uint32_t crc) noexcept { crc = ~crc; diff --git a/src/vendor/Soup/soup/dnsHeader.hpp b/src/vendor/Soup/soup/dnsHeader.hpp index 2afc6f6ff..6acace101 100644 --- a/src/vendor/Soup/soup/dnsHeader.hpp +++ b/src/vendor/Soup/soup/dnsHeader.hpp @@ -16,13 +16,13 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { - return s.u16_be(id) + return s.u16be(id) && s.u8(bitfield1) && s.u8(bitfield2) - && s.u16_be(qdcount) - && s.u16_be(ancount) - && s.u16_be(nscount) - && s.u16_be(arcount) + && s.u16be(qdcount) + && s.u16be(ancount) + && s.u16be(nscount) + && s.u16be(arcount) ; } diff --git a/src/vendor/Soup/soup/dnsName.cpp b/src/vendor/Soup/soup/dnsName.cpp index 09e79a031..01539645c 100644 --- a/src/vendor/Soup/soup/dnsName.cpp +++ b/src/vendor/Soup/soup/dnsName.cpp @@ -11,7 +11,7 @@ NAMESPACE_SOUP && max_recursions != 0 ) { - MemoryRefReader sr(data, false); + MemoryRefReader sr(data); sr.offset = ptr; dnsName cont; diff --git a/src/vendor/Soup/soup/dnsName.hpp b/src/vendor/Soup/soup/dnsName.hpp index 3bb702e9c..82282eaff 100644 --- a/src/vendor/Soup/soup/dnsName.hpp +++ b/src/vendor/Soup/soup/dnsName.hpp @@ -57,7 +57,7 @@ NAMESPACE_SOUP { uint16_t data = ptr; data |= 0xC000; - return s.u16_be(data); + return s.u16be(data); } else { diff --git a/src/vendor/Soup/soup/dnsQuestion.hpp b/src/vendor/Soup/soup/dnsQuestion.hpp index 83b8c66c1..f0e076ccf 100644 --- a/src/vendor/Soup/soup/dnsQuestion.hpp +++ b/src/vendor/Soup/soup/dnsQuestion.hpp @@ -16,8 +16,8 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { return name.io(s) - && s.u16_be(qtype) - && s.u16_be(qclass) + && s.u16be(qtype) + && s.u16be(qclass) ; } }; diff --git a/src/vendor/Soup/soup/dnsRawResolver.cpp b/src/vendor/Soup/soup/dnsRawResolver.cpp index 252c18b89..6d642a328 100644 --- a/src/vendor/Soup/soup/dnsRawResolver.cpp +++ b/src/vendor/Soup/soup/dnsRawResolver.cpp @@ -3,8 +3,8 @@ #include "dnsHeader.hpp" #include "dnsQuestion.hpp" #include "dnsResource.hpp" +#include "MemoryRefReader.hpp" #include "string.hpp" -#include "StringWriter.hpp" NAMESPACE_SOUP { @@ -37,7 +37,7 @@ NAMESPACE_SOUP std::string dnsRawResolver::getQuery(dnsType qtype, const std::string& name, uint16_t id) SOUP_EXCAL { - StringWriter sw(false); + StringWriter sw; dnsHeader dh{}; dh.id = id; @@ -53,9 +53,9 @@ NAMESPACE_SOUP return sw.data; } - std::vector> dnsRawResolver::parseResponse(std::string&& data) SOUP_EXCAL + std::vector> dnsRawResolver::parseResponse(const std::string& data) SOUP_EXCAL { - StringReader sr(std::move(data), false); + MemoryRefReader sr(data); dnsHeader dh; dh.read(sr); @@ -72,7 +72,7 @@ NAMESPACE_SOUP dnsResource dr; dr.read(sr); - std::string name = string::join(dr.name.resolve(sr.data), '.'); + std::string name = string::join(dr.name.resolve(data), '.'); if (dr.rclass != DNS_IN) { @@ -89,21 +89,21 @@ NAMESPACE_SOUP } else if (dr.rtype == DNS_CNAME) { - StringReader rdata_sr(std::move(dr.rdata), false); + MemoryRefReader rdata_sr(dr.rdata); dnsName cname; cname.read(rdata_sr); - res.emplace_back(soup::make_unique(std::move(name), dr.ttl, string::join(cname.resolve(sr.data), '.'))); + res.emplace_back(soup::make_unique(std::move(name), dr.ttl, string::join(cname.resolve(data), '.'))); } else if (dr.rtype == DNS_PTR) { - StringReader rdata_sr(std::move(dr.rdata), false); + MemoryRefReader rdata_sr(dr.rdata); dnsName cname; cname.read(rdata_sr); - res.emplace_back(soup::make_unique(std::move(name), dr.ttl, string::join(cname.resolve(sr.data), '.'))); + res.emplace_back(soup::make_unique(std::move(name), dr.ttl, string::join(cname.resolve(data), '.'))); } else if (dr.rtype == DNS_TXT) { @@ -121,33 +121,33 @@ NAMESPACE_SOUP uint16_t priority; dnsName target; - StringReader rdata_sr(std::move(dr.rdata), false); - rdata_sr.u16_be(priority); + MemoryRefReader rdata_sr(dr.rdata); + rdata_sr.u16be(priority); target.read(rdata_sr); - res.emplace_back(soup::make_unique(std::move(name), dr.ttl, priority, string::join(target.resolve(sr.data), '.'))); + res.emplace_back(soup::make_unique(std::move(name), dr.ttl, priority, string::join(target.resolve(data), '.'))); } else if (dr.rtype == DNS_SRV) { uint16_t priority, weight, port; dnsName target; - StringReader rdata_sr(std::move(dr.rdata), false); - rdata_sr.u16_be(priority); - rdata_sr.u16_be(weight); - rdata_sr.u16_be(port); + MemoryRefReader rdata_sr(dr.rdata); + rdata_sr.u16be(priority); + rdata_sr.u16be(weight); + rdata_sr.u16be(port); target.read(rdata_sr); - res.emplace_back(soup::make_unique(std::move(name), dr.ttl, priority, weight, string::join(target.resolve(sr.data), '.'), port)); + res.emplace_back(soup::make_unique(std::move(name), dr.ttl, priority, weight, string::join(target.resolve(data), '.'), port)); } else if (dr.rtype == DNS_NS) { - StringReader rdata_sr(std::move(dr.rdata), false); + MemoryRefReader rdata_sr(dr.rdata); dnsName cname; cname.read(rdata_sr); - res.emplace_back(soup::make_unique(std::move(name), dr.ttl, string::join(cname.resolve(sr.data), '.'))); + res.emplace_back(soup::make_unique(std::move(name), dr.ttl, string::join(cname.resolve(data), '.'))); } } return res; diff --git a/src/vendor/Soup/soup/dnsRawResolver.hpp b/src/vendor/Soup/soup/dnsRawResolver.hpp index 21bb692d5..423a94d8c 100644 --- a/src/vendor/Soup/soup/dnsRawResolver.hpp +++ b/src/vendor/Soup/soup/dnsRawResolver.hpp @@ -10,6 +10,6 @@ NAMESPACE_SOUP [[nodiscard]] static UniquePtr checkBuiltinResultTask(dnsType qtype, const std::string& name) SOUP_EXCAL; [[nodiscard]] static std::string getQuery(dnsType qtype, const std::string& name, uint16_t id = 0) SOUP_EXCAL; - [[nodiscard]] static std::vector> parseResponse(std::string&& data) SOUP_EXCAL; + [[nodiscard]] static std::vector> parseResponse(const std::string& data) SOUP_EXCAL; }; } diff --git a/src/vendor/Soup/soup/dnsResource.hpp b/src/vendor/Soup/soup/dnsResource.hpp index ea6311259..8dce5de12 100644 --- a/src/vendor/Soup/soup/dnsResource.hpp +++ b/src/vendor/Soup/soup/dnsResource.hpp @@ -17,10 +17,10 @@ NAMESPACE_SOUP SOUP_PACKET_IO(s) { return name.io(s) - && s.u16_be(rtype) - && s.u16_be(rclass) - && s.u32_be(ttl) - && s.template str_lp(rdata) + && s.u16be(rtype) + && s.u16be(rclass) + && s.u32be(ttl) + && s.template str_lp(rdata) ; } }; diff --git a/src/vendor/Soup/soup/dns_records.cpp b/src/vendor/Soup/soup/dns_records.cpp index 08d7202fd..1e6c73c50 100644 --- a/src/vendor/Soup/soup/dns_records.cpp +++ b/src/vendor/Soup/soup/dns_records.cpp @@ -76,7 +76,7 @@ NAMESPACE_SOUP dnsName value; value.name = string::explode(data, '.'); - StringWriter sw(false); + StringWriter sw; value.write(sw); return sw.data; } diff --git a/src/vendor/Soup/soup/ioBase.hpp b/src/vendor/Soup/soup/ioBase.hpp index 997939129..304648382 100644 --- a/src/vendor/Soup/soup/ioBase.hpp +++ b/src/vendor/Soup/soup/ioBase.hpp @@ -19,13 +19,13 @@ NAMESPACE_SOUP SOUP_INT_STRUCT(u48_t, u64_t); SOUP_INT_STRUCT(u56_t, u64_t); - SOUP_INT_STRUCT(u16_be_t, u16_t); - SOUP_INT_STRUCT(u24_be_t, u32_t); - SOUP_INT_STRUCT(u32_be_t, u32_t); + SOUP_INT_STRUCT(u16be_t, u16_t); + SOUP_INT_STRUCT(u24be_t, u32_t); + SOUP_INT_STRUCT(u32be_t, u32_t); - SOUP_INT_STRUCT(u16_le_t, u16_t); - SOUP_INT_STRUCT(u24_le_t, u32_t); - SOUP_INT_STRUCT(u32_le_t, u32_t); + SOUP_INT_STRUCT(u16le_t, u16_t); + SOUP_INT_STRUCT(u24le_t, u32_t); + SOUP_INT_STRUCT(u32le_t, u32_t); class ioVirtualBase { @@ -43,12 +43,12 @@ NAMESPACE_SOUP } public: - [[nodiscard]] bool isBigEndian() const noexcept + [[deprecated]] bool isBigEndian() const noexcept { return (ENDIAN_BIG == ENDIAN_NATIVE) == native_endianness; } - [[nodiscard]] bool isLittleEndian() const noexcept + [[deprecated]] bool isLittleEndian() const noexcept { return (ENDIAN_LITTLE == ENDIAN_NATIVE) == native_endianness; } @@ -56,6 +56,7 @@ NAMESPACE_SOUP virtual ~ioVirtualBase() = default; virtual bool raw(void* data, size_t len) noexcept = 0; + [[nodiscard]] virtual size_t getPosition() = 0; bool b(bool& v) noexcept { @@ -93,25 +94,29 @@ NAMESPACE_SOUP template bool ser(T& v) noexcept; - bool u16(uint16_t& v) noexcept + [[deprecated]] bool u16(uint16_t& v) noexcept { - return u16(v, native_endianness); + return native_endianness ? u16(v) : u16(v); } - bool u16_be(uint16_t& v) noexcept + [[deprecated("Renamed to u16be")]] bool u16_be(uint16_t& v) noexcept { return u16be(v); } + [[deprecated("Renamed to u16le")]] bool u16_le(uint16_t& v) noexcept { return u16le(v); } + + bool u16be(uint16_t& v) noexcept { - return u16(v, ENDIAN_NATIVE == ENDIAN_BIG); + return u16(v); } - bool u16_le(uint16_t& v) noexcept + bool u16le(uint16_t& v) noexcept { - return u16(v, ENDIAN_NATIVE == ENDIAN_LITTLE); + return u16(v); } protected: - bool u16(uint16_t& v, bool native_endianness) noexcept + template + bool u16(uint16_t& v) noexcept { - if (native_endianness) + if constexpr (native_endianness) { return raw(&v, sizeof(v)); } @@ -132,25 +137,29 @@ NAMESPACE_SOUP } public: - bool u32(uint32_t& v) noexcept + [[deprecated]] bool u32(uint32_t& v) noexcept { - return u32(v, native_endianness); + return native_endianness ? u32(v) : u32(v); } - bool u32_be(uint32_t& v) noexcept + [[deprecated("Renamed to u32be")]] bool u32_be(uint32_t& v) noexcept { return u32be(v); } + [[deprecated("Renamed to u32le")]] bool u32_le(uint32_t& v) noexcept { return u32le(v); } + + bool u32be(uint32_t& v) noexcept { - return u32(v, ENDIAN_NATIVE == ENDIAN_BIG); + return u32(v); } - bool u32_le(uint32_t& v) noexcept + bool u32le(uint32_t& v) noexcept { - return u32(v, ENDIAN_NATIVE == ENDIAN_LITTLE); + return u32(v); } protected: - bool u32(uint32_t& v, bool native_endianness) noexcept + template + bool u32(uint32_t& v) noexcept { - if (native_endianness) + if constexpr (native_endianness) { return raw(&v, sizeof(v)); } @@ -171,25 +180,29 @@ NAMESPACE_SOUP } public: - bool u64(uint64_t& v) noexcept + [[deprecated]] bool u64(uint64_t& v) noexcept { - return u64(v, native_endianness); + return native_endianness ? u64(v) : u64(v); } - bool u64_be(uint64_t& v) noexcept + [[deprecated("Renamed to u64be")]] bool u64_be(uint64_t& v) noexcept { return u64be(v); } + [[deprecated("Renamed to u64le")]] bool u64_le(uint64_t& v) noexcept { return u64le(v); } + + bool u64be(uint64_t& v) noexcept { - return u64(v, ENDIAN_NATIVE == ENDIAN_BIG); + return u64(v); } - bool u64_le(uint64_t& v) noexcept + bool u64le(uint64_t& v) noexcept { - return u64(v, ENDIAN_NATIVE == ENDIAN_LITTLE); + return u64(v); } protected: - bool u64(uint64_t& v, bool native_endianness) noexcept + template + bool u64(uint64_t& v) noexcept { - if (native_endianness) + if constexpr (native_endianness) { return raw(&v, sizeof(v)); } @@ -215,44 +228,45 @@ NAMESPACE_SOUP return u8(*(uint8_t*)&v); } - bool i16(int16_t& v) noexcept - { - return u16(*(uint16_t*)&v); - } + bool i16(int16_t& v) noexcept { return u16(*(uint16_t*)&v); } + bool i16le(int16_t& v) noexcept { return u16le(*(uint16_t*)&v); } + bool i16be(int16_t& v) noexcept { return u16be(*(uint16_t*)&v); } - bool i32(int32_t& v) noexcept - { - return u32(*(uint32_t*)&v); - } + bool i32(int32_t& v) noexcept { return u32(*(uint32_t*)&v); } + bool i32le(int32_t& v) noexcept { return u32le(*(uint32_t*)&v); } + bool i32be(int32_t& v) noexcept { return u32be(*(uint32_t*)&v); } - bool i64(int64_t& v) noexcept - { - return u64(*(uint64_t*)&v); - } + bool i64(int64_t& v) noexcept { return u64(*(uint64_t*)&v); } + bool i64le(int64_t& v) noexcept { return u64le(*(uint64_t*)&v); } + bool i64be(int64_t& v) noexcept { return u64be(*(uint64_t*)&v); } bool u24(uint32_t& v) noexcept { - return u24(v, native_endianness); + return native_endianness ? u24(v) : u24(v); } - bool u24_be(uint32_t& v) noexcept + [[deprecated("Renamed to u24be")]] bool u24_be(uint32_t& v) noexcept { return u24be(v); } + [[deprecated("Renamed to u24le")]] bool u24_le(uint32_t& v) noexcept { return u24le(v); } + + bool u24be(uint32_t& v) noexcept { - return u24(v, ENDIAN_NATIVE == ENDIAN_BIG); + return u24(v); } - bool u24_le(uint32_t& v) noexcept + bool u24le(uint32_t& v) noexcept { - return u24(v, ENDIAN_NATIVE == ENDIAN_LITTLE); + return u24(v); } protected: - bool u24(uint32_t& v, bool native_endianness) noexcept + template + bool u24(uint32_t& v) noexcept { - if (isRead()) + if constexpr (is_read) { v = 0; } - if (native_endianness) + if constexpr (native_endianness) { return u8(((uint8_t*)&v)[0]) && u8(((uint8_t*)&v)[1]) @@ -267,9 +281,9 @@ NAMESPACE_SOUP } public: - bool u40(uint64_t& v) noexcept + [[deprecated]] bool u40(uint64_t& v) noexcept { - if (isRead()) + if constexpr (is_read) { v = 0; } @@ -291,9 +305,9 @@ NAMESPACE_SOUP } } - bool u48(uint64_t& v) noexcept + [[deprecated]] bool u48(uint64_t& v) noexcept { - if (isRead()) + if constexpr (is_read) { v = 0; } @@ -317,9 +331,9 @@ NAMESPACE_SOUP } } - bool u56(uint64_t& v) noexcept + [[deprecated]] bool u56(uint64_t& v) noexcept { - if (isRead()) + if constexpr (is_read) { v = 0; } @@ -347,12 +361,12 @@ NAMESPACE_SOUP bool f32(float& v) noexcept { - return raw(&v, 4); + return u32le(*reinterpret_cast(&v)); } bool f64(double& v) noexcept { - return raw(&v, 8); + return u64le(*reinterpret_cast(&v)); } }; @@ -360,19 +374,12 @@ NAMESPACE_SOUP #define IOBASE_SER_METHOD_IMPL_2(t, is_read) template<> template<> inline bool ioBase::ser(t ## _t& v) noexcept { return t(v); } IOBASE_SER_METHOD_IMPL(u8) - IOBASE_SER_METHOD_IMPL(u16) - IOBASE_SER_METHOD_IMPL(u24) - IOBASE_SER_METHOD_IMPL(u32) - IOBASE_SER_METHOD_IMPL(u40) - IOBASE_SER_METHOD_IMPL(u48) - IOBASE_SER_METHOD_IMPL(u56) - IOBASE_SER_METHOD_IMPL(u64) - - IOBASE_SER_METHOD_IMPL(u16_be) - IOBASE_SER_METHOD_IMPL(u24_be) - IOBASE_SER_METHOD_IMPL(u32_be) - - IOBASE_SER_METHOD_IMPL(u16_le) - IOBASE_SER_METHOD_IMPL(u24_le) - IOBASE_SER_METHOD_IMPL(u32_le) + + IOBASE_SER_METHOD_IMPL(u16be) + IOBASE_SER_METHOD_IMPL(u24be) + IOBASE_SER_METHOD_IMPL(u32be) + + IOBASE_SER_METHOD_IMPL(u16le) + IOBASE_SER_METHOD_IMPL(u24le) + IOBASE_SER_METHOD_IMPL(u32le) } diff --git a/src/vendor/Soup/soup/json.cpp b/src/vendor/Soup/soup/json.cpp index b99600cc4..4fce9831f 100644 --- a/src/vendor/Soup/soup/json.cpp +++ b/src/vendor/Soup/soup/json.cpp @@ -122,22 +122,7 @@ NAMESPACE_SOUP return {}; } - void json::decode(UniquePtr& out, const std::string& data) - { - out = decode(data); - } - - UniquePtr json::decodeForDedicatedVariable(const std::string& data) - { - return decode(data); - } - - void json::binaryDecode(UniquePtr& out, Reader& r) - { - out = binaryDecodeForDedicatedVariable(r); - } - - UniquePtr json::binaryDecodeForDedicatedVariable(Reader& r) + UniquePtr json::binaryDecode(Reader& r) { uint8_t b; if (r.u8(b)) @@ -158,7 +143,7 @@ NAMESPACE_SOUP else if (type == JSON_FLOAT) { uint64_t val; - if (r.u64(val)) + if (r.u64le(val)) { return soup::make_unique(*reinterpret_cast(&val)); } @@ -190,7 +175,7 @@ NAMESPACE_SOUP { UniquePtr node; - if (binaryDecode(node, r), !node) + if (node = binaryDecode(r), !node) { break; } @@ -207,11 +192,11 @@ NAMESPACE_SOUP UniquePtr key; UniquePtr val; - if (binaryDecode(key, r), !key) + if (key = binaryDecode(r), !key) { break; } - if (binaryDecode(val, r), !val) + if (val = binaryDecode(r), !val) { break; } diff --git a/src/vendor/Soup/soup/json.hpp b/src/vendor/Soup/soup/json.hpp index 5ca3d8387..264b9f973 100644 --- a/src/vendor/Soup/soup/json.hpp +++ b/src/vendor/Soup/soup/json.hpp @@ -21,13 +21,13 @@ NAMESPACE_SOUP // 2. The returned UniquePtr might be default-constructed in case of a parse error, so you'd be dereferencing a nullptr. [[nodiscard]] static UniquePtr decode(const std::string& data); [[nodiscard]] static UniquePtr decode(const char*& c); - - [[deprecated]] static void decode(UniquePtr& out, const std::string& data); - [[deprecated]] static UniquePtr decodeForDedicatedVariable(const std::string& data); + [[deprecated]] static void decode(UniquePtr& out, const std::string& data) { out = decode(data); } + [[deprecated]] static UniquePtr decodeForDedicatedVariable(const std::string& data) { return decode(data); } // specific to soup - static void binaryDecode(UniquePtr& out, Reader& r); - [[nodiscard]] static UniquePtr binaryDecodeForDedicatedVariable(Reader& r); + [[nodiscard]] static UniquePtr binaryDecode(Reader& r); + [[deprecated]] static void binaryDecode(UniquePtr& out, Reader& r) { out = binaryDecode(r); } + [[deprecated]] static UniquePtr binaryDecodeForDedicatedVariable(Reader& r) { return binaryDecode(r); } // internal static void handleLeadingSpace(const char*& c); diff --git a/src/vendor/Soup/soup/os.cpp b/src/vendor/Soup/soup/os.cpp index 803c4199b..16bbc0537 100644 --- a/src/vendor/Soup/soup/os.cpp +++ b/src/vendor/Soup/soup/os.cpp @@ -125,16 +125,12 @@ NAMESPACE_SOUP return result; } +#if !SOUP_WINDOWS pid_t os::getProcessId() noexcept { -#if SOUP_WINDOWS - return GetCurrentProcessId(); -#else return ::getpid(); -#endif } -#if !SOUP_WINDOWS void os::sleep(unsigned int ms) noexcept { #if _POSIX_C_SOURCE >= 199309L diff --git a/src/vendor/Soup/soup/os.hpp b/src/vendor/Soup/soup/os.hpp index 9d6b56632..d19956986 100644 --- a/src/vendor/Soup/soup/os.hpp +++ b/src/vendor/Soup/soup/os.hpp @@ -60,6 +60,11 @@ NAMESPACE_SOUP }; #if SOUP_WINDOWS + inline pid_t os::getProcessId() noexcept + { + return GetCurrentProcessId(); + } + inline void os::sleep(unsigned int ms) noexcept { ::Sleep(ms); diff --git a/src/vendor/Soup/soup/plusaes.hpp b/src/vendor/Soup/soup/plusaes.hpp deleted file mode 100644 index b531052f6..000000000 --- a/src/vendor/Soup/soup/plusaes.hpp +++ /dev/null @@ -1,1313 +0,0 @@ -// Source: https://github.com/Sainan/plusaes/tree/workaround32 - -// Copyright (C) 2015 kkAyataka -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef PLUSAES_HPP__ -#define PLUSAES_HPP__ - -#include -#include -#include -#include -#include -#include - -/** @defgroup Base - * @{ */ - -/** Version number of the plusaes. - * 0x01020304 -> 1.2.3.4 */ -#define PLUSAES_VERSION 0x01000000 - -/** @} */ - -/** AES cipher APIs */ -namespace plusaes { -namespace detail { - -const int kWordSize = 4; -typedef unsigned int Word; - -const int kBlockSize = 4; -/** @private */ -struct State { - Word w[4]; - Word & operator[](const int index) { - return w[index]; - } - const Word & operator[](const int index) const { - return w[index]; - } -}; - -const int kStateSize = 16; // Word * BlockSize -typedef State RoundKey; -typedef std::vector RoundKeys; - -inline void add_round_key(const RoundKey &key, State &state) { - for (int i = 0; i < kBlockSize; ++i) { - state[i] ^= key[i]; - } -} - -const unsigned char kSbox[] = { - 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 unsigned char kInvSbox[] = { - 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 -}; - -inline Word sub_word(const Word w) { - return kSbox[(w >> 0) & 0xFF] << 0 | - kSbox[(w >> 8) & 0xFF] << 8 | - kSbox[(w >> 16) & 0xFF] << 16 | - kSbox[(w >> 24) & 0xFF] << 24; -} - -inline Word inv_sub_word(const Word w) { - return kInvSbox[(w >> 0) & 0xFF] << 0 | - kInvSbox[(w >> 8) & 0xFF] << 8 | - kInvSbox[(w >> 16) & 0xFF] << 16 | - kInvSbox[(w >> 24) & 0xFF] << 24; -} - -inline void sub_bytes(State &state) { - for (int i = 0; i < kBlockSize; ++i) { - state[i] = sub_word(state[i]); - } -} - -inline void inv_sub_bytes(State &state) { - for (int i = 0; i < kBlockSize; ++i) { - state[i] = inv_sub_word(state[i]); - } -} - -inline void shift_rows(State &state) { - const State ori = { state[0], state[1], state[2], state[3] }; - for (int r = 1; r < kWordSize; ++r) { - const Word m2 = 0xFF << (r * 8); - const Word m1 = ~m2; - for (int c = 0; c < kBlockSize; ++c) { - state[c] = (state[c] & m1) | (ori[(c + r) % kBlockSize] & m2); - } - } -} - -inline void inv_shift_rows(State &state) { - const State ori = { state[0], state[1], state[2], state[3] }; - for (int r = 1; r < kWordSize; ++r) { - const Word m2 = 0xFF << (r * 8); - const Word m1 = ~m2; - for (int c = 0; c < kBlockSize; ++c) { - state[c] = (state[c] & m1) | (ori[(c + kBlockSize - r) % kWordSize] & m2); - } - } -} - -inline unsigned char mul2(const unsigned char b) { - unsigned char m2 = b << 1; - if (b & 0x80) { - m2 ^= 0x011B; - } - - return m2; -} - -inline unsigned char mul(const unsigned char b, const unsigned char m) { - unsigned char v = 0; - unsigned char t = b; - for (int i = 0; i < 8; ++i) { // 8-bits - if ((m >> i) & 0x01) { - v ^= t; - } - - t = mul2(t); - } - - return v; -} - -inline void mix_columns(State &state) { - for (int i = 0; i < kBlockSize; ++i) { - const unsigned char v0_1 = (state[i] >> 0) & 0xFF; - const unsigned char v1_1 = (state[i] >> 8) & 0xFF; - const unsigned char v2_1 = (state[i] >> 16) & 0xFF; - const unsigned char v3_1 = (state[i] >> 24) & 0xFF; - - const unsigned char v0_2 = mul2(v0_1); - const unsigned char v1_2 = mul2(v1_1); - const unsigned char v2_2 = mul2(v2_1); - const unsigned char v3_2 = mul2(v3_1); - - const unsigned char v0_3 = v0_2 ^ v0_1; - const unsigned char v1_3 = v1_2 ^ v1_1; - const unsigned char v2_3 = v2_2 ^ v2_1; - const unsigned char v3_3 = v3_2 ^ v3_1; - - state[i] = - (v0_2 ^ v1_3 ^ v2_1 ^ v3_1) << 0 | - (v0_1 ^ v1_2 ^ v2_3 ^ v3_1) << 8 | - (v0_1 ^ v1_1 ^ v2_2 ^ v3_3) << 16 | - (v0_3 ^ v1_1 ^ v2_1 ^ v3_2) << 24; - } -} - -inline void inv_mix_columns(State &state) { - for (int i = 0; i < kBlockSize; ++i) { - const unsigned char v0 = (state[i] >> 0) & 0xFF; - const unsigned char v1 = (state[i] >> 8) & 0xFF; - const unsigned char v2 = (state[i] >> 16) & 0xFF; - const unsigned char v3 = (state[i] >> 24) & 0xFF; - - state[i] = - (mul(v0, 0x0E) ^ mul(v1, 0x0B) ^ mul(v2, 0x0D) ^ mul(v3, 0x09)) << 0 | - (mul(v0, 0x09) ^ mul(v1, 0x0E) ^ mul(v2, 0x0B) ^ mul(v3, 0x0D)) << 8 | - (mul(v0, 0x0D) ^ mul(v1, 0x09) ^ mul(v2, 0x0E) ^ mul(v3, 0x0B)) << 16 | - (mul(v0, 0x0B) ^ mul(v1, 0x0D) ^ mul(v2, 0x09) ^ mul(v3, 0x0E)) << 24; - } -} - -inline Word rot_word(const Word v) { - return ((v >> 8) & 0x00FFFFFF) | ((v & 0xFF) << 24); -} - -/** - * @private - * @throws std::invalid_argument - */ -inline unsigned int get_round_count(const int key_size) { - switch (key_size) { - case 16: - return 10; - case 24: - return 12; - case 32: - return 14; - default: - SOUP_THROW(std::invalid_argument("Invalid key size")); - } -} - -/** - * @private - * @throws std::invalid_argument - */ -inline RoundKeys expand_key(const unsigned char *key, const int key_size) { - if (key_size != 16 && key_size != 24 && key_size != 32) { - SOUP_THROW(std::invalid_argument("Invalid key size")); - } - - const Word rcon[] = { - 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, - 0x20, 0x40, 0x80, 0x1b, 0x36 - }; - - const int nb = kBlockSize; - const int nk = key_size / nb; - const int nr = get_round_count(key_size); - - std::vector w(nb * (nr + 1)); - for (int i = 0; i < nk; ++ i) { - memcpy(&w[i], key + (i * kWordSize), kWordSize); - } - - for (int i = nk; i < nb * (nr + 1); ++i) { - Word t = w[i - 1]; - if (i % nk == 0) { - t = sub_word(rot_word(t)) ^ rcon[i / nk]; - } - else if (nk > 6 && i % nk == 4) { - t = sub_word(t); - } - - w[i] = t ^ w[i - nk]; - } - - RoundKeys keys(nr + 1); - memcpy(&keys[0], &w[0], w.size() * kWordSize); - - return keys; -} - -inline void copy_bytes_to_state(const unsigned char data[16], State &state) { - memcpy(&state[0], data + 0, kWordSize); - memcpy(&state[1], data + 4, kWordSize); - memcpy(&state[2], data + 8, kWordSize); - memcpy(&state[3], data + 12, kWordSize); -} - -inline void copy_state_to_bytes(const State &state, unsigned char buf[16]) { - memcpy(buf + 0, &state[0], kWordSize); - memcpy(buf + 4, &state[1], kWordSize); - memcpy(buf + 8, &state[2], kWordSize); - memcpy(buf + 12, &state[3], kWordSize); -} - -inline void xor_data(unsigned char data[kStateSize], const unsigned char v[kStateSize]) { - for (int i = 0; i < kStateSize; ++i) { - data[i] ^= v[i]; - } -} - -/** increment counter (128-bit int) by 1 */ -inline void incr_counter(unsigned char counter[kStateSize]) { - unsigned n = kStateSize, c = 1; - do { - --n; - c += counter[n]; - counter[n] = c; - c >>= 8; - } while (n); -} - -inline void encrypt_state(const RoundKeys &rkeys, const unsigned char data[16], unsigned char encrypted[16]) { - State s; - copy_bytes_to_state(data, s); - - add_round_key(rkeys[0], s); - - for (unsigned int i = 1; i < rkeys.size() - 1; ++i) { - sub_bytes(s); - shift_rows(s); - mix_columns(s); - add_round_key(rkeys[i], s); - } - - sub_bytes(s); - shift_rows(s); - add_round_key(rkeys.back(), s); - - copy_state_to_bytes(s, encrypted); -} - -inline void decrypt_state(const RoundKeys &rkeys, const unsigned char data[16], unsigned char decrypted[16]) { - State s; - copy_bytes_to_state(data, s); - - add_round_key(rkeys.back(), s); - inv_shift_rows(s); - inv_sub_bytes(s); - - for (std::size_t i = rkeys.size() - 2; i > 0; --i) { - add_round_key(rkeys[i], s); - inv_mix_columns(s); - inv_shift_rows(s); - inv_sub_bytes(s); - } - - add_round_key(rkeys[0], s); - - copy_state_to_bytes(s, decrypted); -} - -template -std::vector key_from_string(const char (*key_str)[KeyLen]) { - std::vector key(KeyLen - 1); - memcpy(&key[0], *key_str, KeyLen - 1); - return key; -} - -inline bool is_valid_key_size(const std::size_t key_size) { - if (key_size != 16 && key_size != 24 && key_size != 32) { - return false; - } - else { - return true; - } -} - - -namespace gcm { - -const int kBlockBitSize = 128; -const int kBlockByteSize = kBlockBitSize / 8; - -/** - * @private - * GCM operation unit as bit. - * This library handles 128 bit little endian bit array. - * e.g. 0^127 || 1 == "000...0001" (bit string) == 1 - */ -typedef std::bitset bitset128; - -/** - * @private - * GCM operation unit. - * Little endian byte array - * - * If bitset128 is 1: 0^127 || 1 == "000...0001" (bit string) == 1 - * byte array is 0x00, 0x00, 0x00 ... 0x01 (low -> high). - * Byte array is NOT 0x01, 0x00 ... 0x00. - * - * This library handles GCM bit string in two ways. - * One is an array of bitset, which is a little endian 128-bit array's array. - * - * <- first byte - * bitset128 || bitset128 || bitset128... - * - * The other one is a byte array. - * <- first byte - * byte || byte || byte... - */ -class Block { -public: - Block() noexcept { - init_v(0, 0); - } - - Block(const unsigned char * bytes, const unsigned long bytes_size) noexcept { - init_v(bytes, bytes_size); - } - - Block(const std::vector & bytes) noexcept { - init_v(&bytes[0], bytes.size()); - } - - Block(const std::bitset<128> & bits) noexcept; // implementation below - - inline unsigned char * data() noexcept { - return v_; - } - - inline const unsigned char* data() const noexcept { - return v_; - } - - inline std::bitset<128> to_bits() const noexcept { - std::bitset<128> bits; - for (int i = 0; i < 16; ++i) { - bits <<= 8; - bits |= v_[i]; - } - - return bits; - } - - inline Block operator^(const Block & b) const noexcept { - Block r; - for (int i = 0; i < 16; ++i) { - r.data()[i] = data()[i] ^ b.data()[i]; - } - return r; - } - -private: - unsigned char v_[16]; - - inline void init_v(const unsigned char * bytes, const std::size_t bytes_size) noexcept { - memset(v_, 0, sizeof(v_)); - - const std::size_t cs = (std::min)(bytes_size, static_cast(16)); - for (std::size_t i = 0; i < cs; ++i) { - v_[i] = bytes[i]; - } - } -}; - -// Workaround for clang optimization in 32-bit build via Visual Studio producing incorrect results (https://github.com/kkAyataka/plusaes/issues/43) -#if defined(__clang__) && defined(_WIN32) && !defined(_WIN64) -#pragma optimize("", off) -#endif -inline Block::Block(const std::bitset<128> & bits) noexcept -{ - init_v(0, 0); - const std::bitset<128> mask(0xFF); // 1 byte mask - for (std::size_t i = 0; i < 16; ++i) { - v_[15 - i] = static_cast(((bits >> (i * 8)) & mask).to_ulong()); - } -} -#if defined(__clang__) && defined(_WIN32) && !defined(_WIN64) -#pragma optimize("", on) -#endif - -template -unsigned long ceil(const T v) { - return static_cast(std::ceil(v) + 0.5); -} - -template -std::bitset operator||(const std::bitset &v1, const std::bitset &v2) { - std::bitset ret(v1.to_string() + v2.to_string()); - return ret; -} - -template -std::bitset lsb(const std::bitset &X) { - std::bitset r; - for (std::size_t i = 0; i < S; ++i) { - r[i] = X[i]; - } - return r; -} - -template -std::bitset msb(const std::bitset &X) { - std::bitset r; - for (std::size_t i = 0; i < S; ++i) { - r[S - 1 - i] = X[X.size() - 1 - i]; - } - return r; -} - -template -std::bitset inc32(const std::bitset X) { - const std::size_t S = 32; - - const auto a = msb(X); - const std::bitset b((lsb(X).to_ulong() + 1)); // % (2^32); - // lsb<32> is low 32-bit value - // Spec.'s "mod 2^S" is not necessary when S is 32 (inc32). - // ...and 2^32 is over 32-bit integer. - - return a || b; -} - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wself-assign" -#endif // __clang__ - -/** Algorithm 1 @private */ -inline Block mul_blocks(const Block X, const Block Y) noexcept { - const bitset128 R = (std::bitset<8>("11100001") || std::bitset<120>()); - - bitset128 X_bits = X.to_bits(); - bitset128 Z; - bitset128 V = Y.to_bits(); - for (int i = 127; i >= 0; --i) { - // Z - if (X_bits[i] == false) { - Z = Z; - } - else { - Z = Z ^ V; - } - - // V - if (V[0] == false) { - V = V >> 1; - } - else { - V = (V >> 1) ^ R; - } - } - - return Z; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif // __clang__ - -/** Algorithm 2 @private */ -inline Block ghash(const Block & H, const std::vector & X) noexcept { - const std::size_t m = X.size() / kBlockByteSize; - Block Ym; - for (std::size_t i = 0; i < m; ++i) { - const Block Xi(&X[i * kBlockByteSize], kBlockByteSize); - Ym = mul_blocks((Ym ^ Xi), H); - } - - return Ym; -} - -template -std::bitset make_bitset(const unsigned char * bytes, const std::size_t bytes_size) { - std::bitset bits; - for (auto i = 0u; i < bytes_size; ++i) { - bits <<= 8; - bits |= bytes[i]; - } - return bits; -} - -/** Algorithm 3 @private */ -inline std::vector gctr(const detail::RoundKeys & rkeys, const Block & ICB, const unsigned char * X, const std::size_t X_size){ - if (!X || X_size == 0) { - return std::vector(); - } - else { - const unsigned long n = ceil(X_size * 8.0 / kBlockBitSize); - std::vector Y(X_size); - - Block CB; - for (std::size_t i = 0; i < n; ++i) { - // CB - if (i == 0) { // first - CB = ICB; - } - else { - CB = inc32(CB.to_bits()); - } - - // CIPH - Block eCB; - encrypt_state(rkeys, CB.data(), eCB.data()); - - // Y - int op_size = 0; - if (i < n - 1) { - op_size = kBlockByteSize; - } - else { // last - op_size = (X_size % kBlockByteSize) ? (X_size % kBlockByteSize) : kBlockByteSize; - } - const Block Yi = Block(X + i * kBlockBitSize / 8, op_size) ^ eCB; - memcpy(&Y[i * kBlockByteSize], Yi.data(), op_size); - } - - return Y; - } -} - -inline void push_back(std::vector & bytes, const unsigned char * data, const std::size_t data_size) { - bytes.insert(bytes.end(), data, data + data_size); -} - -inline void push_back(std::vector & bytes, const std::bitset<64> & bits) { - const std::bitset<64> mask(0xFF); // 1 byte mask - for (std::size_t i = 0; i < 8; ++i) { - bytes.push_back(static_cast(((bits >> ((7 - i) * 8)) & mask).to_ulong())); - } -} - -inline void push_back_zero_bits(std::vector& bytes, const std::size_t zero_bits_size) { - const std::vector zero_bytes(zero_bits_size / 8); - bytes.insert(bytes.end(), zero_bytes.begin(), zero_bytes.end()); -} - -inline Block calc_H(const RoundKeys & rkeys) { - std::vector H_raw(gcm::kBlockByteSize); - encrypt_state(rkeys, &H_raw[0], &H_raw[0]); - return gcm::Block(H_raw); -} - -inline Block calc_J0(const Block & H, const unsigned char * iv, const std::size_t iv_size) { - if (iv_size == 12) { - const std::bitset<96> iv_bits = gcm::make_bitset<96>(iv, iv_size); - return iv_bits || std::bitset<31>() || std::bitset<1>(1); - } - else { - const auto len_iv = iv_size * 8; - const auto s = 128 * gcm::ceil(len_iv / 128.0) - len_iv; - std::vector ghash_in; - gcm::push_back(ghash_in, iv, iv_size); - gcm::push_back_zero_bits(ghash_in, s + 64); - gcm::push_back(ghash_in, std::bitset<64>(len_iv)); - - return gcm::ghash(H, ghash_in); - } -} - -inline void calc_gcm_tag( - const unsigned char * data, - const std::size_t data_size, - const unsigned char * aadata, - const std::size_t aadata_size, - const unsigned char * key, - const std::size_t key_size, - const unsigned char * iv, - const std::size_t iv_size, - unsigned char * tag, - const std::size_t tag_size -) { - const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size)); - const gcm::Block H = gcm::calc_H(rkeys); - const gcm::Block J0 = gcm::calc_J0(H, iv, iv_size); - - const auto lenC = data_size * 8; - const auto lenA = aadata_size * 8; - const std::size_t u = 128 * gcm::ceil(lenC / 128.0) - lenC; - const std::size_t v = 128 * gcm::ceil(lenA / 128.0) - lenA; - - std::vector ghash_in; - ghash_in.reserve((aadata_size + v / 8) + (data_size + u / 8) + 8 + 8); - gcm::push_back(ghash_in, aadata, aadata_size); - gcm::push_back_zero_bits(ghash_in, v); - gcm::push_back(ghash_in, data, data_size); - gcm::push_back_zero_bits(ghash_in, u); - gcm::push_back(ghash_in, std::bitset<64>(lenA)); - gcm::push_back(ghash_in, std::bitset<64>(lenC)); - const gcm::Block S = gcm::ghash(H, ghash_in); - const std::vector T = gcm::gctr(rkeys, J0, S.data(), gcm::kBlockByteSize); - - // return - memcpy(tag, &T[0], (std::min)(tag_size, static_cast(16))); -} - -/** Algorithm 4 and 5 @private */ -inline void crypt_gcm( - const unsigned char* data, - const std::size_t data_size, - const unsigned char* key, - const std::size_t key_size, - const unsigned char* iv, - const std::size_t iv_size, - unsigned char* crypted -) { - const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size)); - const gcm::Block H = gcm::calc_H(rkeys); - const gcm::Block J0 = gcm::calc_J0(H, iv, iv_size); - - const std::vector C = gcm::gctr(rkeys, gcm::inc32(J0.to_bits()), data, data_size); - - if (crypted) { - memcpy(crypted, &C[0], data_size); - } -} - -} // namespce detail::gcm - -} // namespace detail - -/** @defgroup Base Base - * Base definitions and convenient functions - * @{ */ - -/** Version number of plusaes. */ -inline unsigned int version() { - return PLUSAES_VERSION; -} - -/** Create 128-bit key from string. */ -inline std::vector key_from_string(const char (*key_str)[17]) { - return detail::key_from_string<17>(key_str); -} - -/** Create 192-bit key from string. */ -inline std::vector key_from_string(const char (*key_str)[25]) { - return detail::key_from_string<25>(key_str); -} - -/** Create 256-bit key from string. */ -inline std::vector key_from_string(const char (*key_str)[33]) { - return detail::key_from_string<33>(key_str); -} - -/** Calculates encrypted data size when padding is enabled. */ -inline unsigned long get_padded_encrypted_size(const unsigned long data_size) { - return data_size + detail::kStateSize - (data_size % detail::kStateSize); -} - -/** Error code */ -typedef enum { - kErrorOk = 0, - kErrorInvalidDataSize = 1, - kErrorInvalidKeySize, - kErrorInvalidBufferSize, - kErrorInvalidKey, - kErrorDeprecated, // kErrorInvalidNonceSize - kErrorInvalidIvSize, - kErrorInvalidTagSize, - kErrorInvalidTag -} Error; - -/** @} */ - -namespace detail { - -inline Error check_encrypt_cond( - const unsigned long data_size, - const unsigned long key_size, - const unsigned long encrypted_size, - const bool pads) { - // check data size - if (!pads && (data_size % kStateSize != 0)) { - return kErrorInvalidDataSize; - } - - // check key size - if (!detail::is_valid_key_size(key_size)) { - return kErrorInvalidKeySize; - } - - // check encrypted buffer size - if (pads) { - const unsigned long required_size = get_padded_encrypted_size(data_size); - if (encrypted_size < required_size) { - return kErrorInvalidBufferSize; - } - } - else { - if (encrypted_size < data_size) { - return kErrorInvalidBufferSize; - } - } - return kErrorOk; -} - -inline Error check_decrypt_cond( - const unsigned long data_size, - const unsigned long key_size, - const unsigned long decrypted_size, - const unsigned long * padded_size - ) { - // check data size - if (data_size % 16 != 0) { - return kErrorInvalidDataSize; - } - - // check key size - if (!detail::is_valid_key_size(key_size)) { - return kErrorInvalidKeySize; - } - - // check decrypted buffer size - if (!padded_size) { - if (decrypted_size < data_size) { - return kErrorInvalidBufferSize; - } - } - else { - if (decrypted_size < (data_size - kStateSize)) { - return kErrorInvalidBufferSize; - } - } - - return kErrorOk; -} - -inline bool check_padding(const unsigned long padding, const unsigned char data[kStateSize]) { - if (padding > kStateSize) { - return false; - } - - for (unsigned long i = 0; i < padding; ++i) { - if (data[kStateSize - 1 - i] != padding) { - return false; - } - } - - return true; -} - -inline Error check_gcm_cond( - const std::size_t key_size, - const std::size_t iv_size, - const std::size_t tag_size -) { - // check key size - if (!detail::is_valid_key_size(key_size)) { - return kErrorInvalidKeySize; - } - - if (iv_size < 1) { - return kErrorInvalidIvSize; - } - - // check tag size - if ((tag_size < 12 || 16 < tag_size) && - (tag_size != 8) && - (tag_size != 4)) { - return kErrorInvalidTagSize; - } - - return kErrorOk; -} - -} // namespace detail - -/** @defgroup ECB ECB - * ECB mode functions - * @{ */ - -/** - * Encrypts data with ECB mode. - * @param [in] data Data. - * @param [in] data_size Data size. - * If the pads is false, data size must be multiple of 16. - * @param [in] key key bytes. The key length must be 16 (128-bit), 24 (192-bit) or 32 (256-bit). - * @param [in] key_size key size. - * @param [out] encrypted Encrypted data buffer. - * @param [in] encrypted_size Encrypted data buffer size. - * @param [in] pads If this value is true, encrypted data is padded by PKCS. - * Encrypted data size must be multiple of 16. - * If the pads is true, encrypted data is padded with PKCS. - * So the data is multiple of 16, encrypted data size needs additonal 16 bytes. - * @since 1.0.0 - */ -inline Error encrypt_ecb( - const unsigned char * data, - const unsigned long data_size, - const unsigned char * key, - const unsigned long key_size, - unsigned char *encrypted, - const unsigned long encrypted_size, - const bool pads - ) { - const Error e = detail::check_encrypt_cond(data_size, key_size, encrypted_size, pads); - if (e != kErrorOk) { - return e; - } - - const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size)); - - const unsigned long bc = data_size / detail::kStateSize; - for (unsigned long i = 0; i < bc; ++i) { - detail::encrypt_state(rkeys, data + (i * detail::kStateSize), encrypted + (i * detail::kStateSize)); - } - - if (pads) { - const int rem = data_size % detail::kStateSize; - const char pad_v = detail::kStateSize - rem; - - std::vector ib(detail::kStateSize, pad_v), ob(detail::kStateSize); - memcpy(&ib[0], data + data_size - rem, rem); - - detail::encrypt_state(rkeys, &ib[0], &ob[0]); - memcpy(encrypted + (data_size - rem), &ob[0], detail::kStateSize); - } - - return kErrorOk; -} - -/** - * Decrypts data with ECB mode. - * @param [in] data Data bytes. - * @param [in] data_size Data size. - * @param [in] key Key bytes. - * @param [in] key_size Key size. - * @param [out] decrypted Decrypted data buffer. - * @param [in] decrypted_size Decrypted data buffer size. - * @param [out] padded_size If this value is NULL, this function does not remove padding. - * If this value is not NULL, this function removes padding by PKCS - * and returns padded size using padded_size. - * @since 1.0.0 - */ -inline Error decrypt_ecb( - const unsigned char * data, - const unsigned long data_size, - const unsigned char * key, - const unsigned long key_size, - unsigned char * decrypted, - const unsigned long decrypted_size, - unsigned long * padded_size - ) { - const Error e = detail::check_decrypt_cond(data_size, key_size, decrypted_size, padded_size); - if (e != kErrorOk) { - return e; - } - - const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size)); - - const unsigned long bc = data_size / detail::kStateSize - 1; - for (unsigned long i = 0; i < bc; ++i) { - detail::decrypt_state(rkeys, data + (i * detail::kStateSize), decrypted + (i * detail::kStateSize)); - } - - unsigned char last[detail::kStateSize] = {}; - detail::decrypt_state(rkeys, data + (bc * detail::kStateSize), last); - - if (padded_size) { - *padded_size = last[detail::kStateSize - 1]; - const unsigned long cs = detail::kStateSize - *padded_size; - - if (!detail::check_padding(*padded_size, last)) { - return kErrorInvalidKey; - } - else if (decrypted_size >= (bc * detail::kStateSize) + cs) { - memcpy(decrypted + (bc * detail::kStateSize), last, cs); - } - else { - return kErrorInvalidBufferSize; - } - } - else { - memcpy(decrypted + (bc * detail::kStateSize), last, sizeof(last)); - } - - return kErrorOk; -} - -/** @} */ - -/** @defgroup CBC CBC - * CBC mode functions - * @{ */ - -/** - * Encrypt data with CBC mode. - * @param [in] data Data. - * @param [in] data_size Data size. - * If the pads is false, data size must be multiple of 16. - * @param [in] key key bytes. The key length must be 16 (128-bit), 24 (192-bit) or 32 (256-bit). - * @param [in] key_size key size. - * @param [in] iv Initialize vector. - * @param [out] encrypted Encrypted data buffer. - * @param [in] encrypted_size Encrypted data buffer size. - * @param [in] pads If this value is true, encrypted data is padded by PKCS. - * Encrypted data size must be multiple of 16. - * If the pads is true, encrypted data is padded with PKCS. - * So the data is multiple of 16, encrypted data size needs additonal 16 bytes. - * @since 1.0.0 - */ -inline Error encrypt_cbc( - const unsigned char * data, - const unsigned long data_size, - const unsigned char * key, - const unsigned long key_size, - const unsigned char (* iv)[16], - unsigned char * encrypted, - const unsigned long encrypted_size, - const bool pads - ) { - const Error e = detail::check_encrypt_cond(data_size, key_size, encrypted_size, pads); - if (e != kErrorOk) { - return e; - } - - const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size)); - - unsigned char s[detail::kStateSize] = {}; // encrypting data - - // calculate padding value - const bool ge16 = (data_size >= detail::kStateSize); - const int rem = data_size % detail::kStateSize; - const unsigned char pad_v = detail::kStateSize - rem; - - // encrypt 1st state - if (ge16) { - memcpy(s, data, detail::kStateSize); - } - else { - memset(s, pad_v, detail::kStateSize); - memcpy(s, data, data_size); - } - if (iv) { - detail::xor_data(s, *iv); - } - detail::encrypt_state(rkeys, s, encrypted); - - // encrypt mid - const unsigned long bc = data_size / detail::kStateSize; - for (unsigned long i = 1; i < bc; ++i) { - const long offset = i * detail::kStateSize; - memcpy(s, data + offset, detail::kStateSize); - detail::xor_data(s, encrypted + offset - detail::kStateSize); - - detail::encrypt_state(rkeys, s, encrypted + offset); - } - - // enctypt last - if (pads && ge16) { - std::vector ib(detail::kStateSize, pad_v), ob(detail::kStateSize); - memcpy(&ib[0], data + data_size - rem, rem); - - detail::xor_data(&ib[0], encrypted + (bc - 1) * detail::kStateSize); - - detail::encrypt_state(rkeys, &ib[0], &ob[0]); - memcpy(encrypted + (data_size - rem), &ob[0], detail::kStateSize); - } - - return kErrorOk; -} - -/** - * Decrypt data with CBC mode. - * @param [in] data Data bytes. - * @param [in] data_size Data size. - * @param [in] key Key bytes. - * @param [in] key_size Key size. - * @param [in] iv Initialize vector. - * @param [out] decrypted Decrypted data buffer. - * @param [in] decrypted_size Decrypted data buffer size. - * @param [out] padded_size If this value is NULL, this function does not remove padding. - * If this value is not NULL, this function removes padding by PKCS - * and returns padded size using padded_size. - * @since 1.0.0 - */ -inline Error decrypt_cbc( - const unsigned char * data, - const unsigned long data_size, - const unsigned char * key, - const unsigned long key_size, - const unsigned char (* iv)[16], - unsigned char * decrypted, - const unsigned long decrypted_size, - unsigned long * padded_size - ) { - const Error e = detail::check_decrypt_cond(data_size, key_size, decrypted_size, padded_size); - if (e != kErrorOk) { - return e; - } - - const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size)); - - // decrypt 1st state - detail::decrypt_state(rkeys, data, decrypted); - if (iv) { - detail::xor_data(decrypted, *iv); - } - - // decrypt mid - const unsigned long bc = data_size / detail::kStateSize - 1; - for (unsigned long i = 1; i < bc; ++i) { - const long offset = i * detail::kStateSize; - detail::decrypt_state(rkeys, data + offset, decrypted + offset); - detail::xor_data(decrypted + offset, data + offset - detail::kStateSize); - } - - // decrypt last - unsigned char last[detail::kStateSize] = {}; - if (data_size > detail::kStateSize) { - detail::decrypt_state(rkeys, data + (bc * detail::kStateSize), last); - detail::xor_data(last, data + (bc * detail::kStateSize - detail::kStateSize)); - } - else { - memcpy(last, decrypted, data_size); - memset(decrypted, 0, decrypted_size); - } - - if (padded_size) { - *padded_size = last[detail::kStateSize - 1]; - const unsigned long cs = detail::kStateSize - *padded_size; - - if (!detail::check_padding(*padded_size, last)) { - return kErrorInvalidKey; - } - else if (decrypted_size >= (bc * detail::kStateSize) + cs) { - memcpy(decrypted + (bc * detail::kStateSize), last, cs); - } - else { - return kErrorInvalidBufferSize; - } - } - else { - memcpy(decrypted + (bc * detail::kStateSize), last, sizeof(last)); - } - - return kErrorOk; -} - -/** @} */ - -/** @defgroup GCM GCM - * GCM mode functions - * @{ */ - -/** - * Encrypts data with GCM mode and gets an authentication tag. - * - * You can specify iv size and tag size. - * But usually you should use the other overloaded function whose iv and tag size is fixed. - * - * @returns kErrorOk - * @returns kErrorInvalidKeySize - * @returns kErrorInvalidIvSize - * @returns kErrorInvalidTagSize - */ -inline Error encrypt_gcm( - unsigned char * data, - const std::size_t data_size, - const unsigned char * aadata, - const std::size_t aadata_size, - const unsigned char * key, - const std::size_t key_size, - const unsigned char * iv, - const std::size_t iv_size, - unsigned char * tag, - const std::size_t tag_size -) { - const Error err = detail::check_gcm_cond(key_size, iv_size, tag_size); - if (err != kErrorOk) { - return err; - } - - detail::gcm::crypt_gcm(data, data_size, key, key_size, iv, iv_size, data); - detail::gcm::calc_gcm_tag(data, data_size, aadata, aadata_size, key, key_size, iv, iv_size, tag, tag_size); - - return kErrorOk; -} - -/** - * Encrypts data with GCM mode and gets an authentication tag. - * - * @param [in,out] data Input data and output buffer. - * This buffer is replaced with encrypted data. - * @param [in] data_size data size - * @param [in] aadata Additional Authenticated data - * @param [in] aadata_size aadata size - * @param [in] key Cipher key - * @param [in] key_size Cipher key size. This value must be 16 (128-bit), 24 (192-bit), or 32 (256-bit). - * @param [in] iv Initialization vector - * @param [out] tag Calculated authentication tag data - * - * @returns kErrorOk - * @returns kErrorInvalidKeySize - */ -inline Error encrypt_gcm( - unsigned char * data, - const std::size_t data_size, - const unsigned char * aadata, - const std::size_t aadata_size, - const unsigned char * key, - const std::size_t key_size, - const unsigned char (*iv)[12], - unsigned char (*tag)[16] -) { - return encrypt_gcm(data, data_size, aadata, aadata_size, key, key_size, *iv, 12, *tag, 16); -} - -/** - * Decrypts data with GCM mode and checks an authentication tag. - * - * You can specify iv size and tag size. - * But usually you should use the other overloaded function whose iv and tag size is fixed. - * - * @returns kErrorOk - * @returns kErrorInvalidKeySize - * @returns kErrorInvalidIvSize - * @returns kErrorInvalidTagSize - * @returns kErrorInvalidTag - */ -inline Error decrypt_gcm( - unsigned char * data, - const std::size_t data_size, - const unsigned char * aadata, - const std::size_t aadata_size, - const unsigned char * key, - const std::size_t key_size, - const unsigned char * iv, - const std::size_t iv_size, - const unsigned char * tag, - const std::size_t tag_size -) { - const Error err = detail::check_gcm_cond(key_size, iv_size, tag_size); - if (err != kErrorOk) { - return err; - } - - unsigned char * C = data; - const auto C_size = data_size; - unsigned char tagd[16] = {}; - detail::gcm::calc_gcm_tag(C, C_size, aadata, aadata_size, key, key_size, iv, iv_size, tagd, 16); - - if (memcmp(tag, tagd, tag_size) != 0) { - return kErrorInvalidTag; - } - else { - detail::gcm::crypt_gcm(C, C_size, key, key_size, iv, iv_size, C); - - return kErrorOk; - } -} - -/** - * Decrypts data with GCM mode and checks an authentication tag. - * - * @param [in,out] data Input data and output buffer. - * This buffer is replaced with decrypted data. - * @param [in] data_size data size - * @param [in] aadata Additional Authenticated data - * @param [in] aadata_size aadata size - * @param [in] key Cipher key - * @param [in] key_size Cipher key size. This value must be 16 (128-bit), 24 (192-bit), or 32 (256-bit). - * @param [in] iv Initialization vector - * @param [in] tag Authentication tag data - * - * @returns kErrorOk - * @returns kErrorInvalidKeySize - * @returns kErrorInvalidTag - */ -inline Error decrypt_gcm( - unsigned char * data, - const std::size_t data_size, - const unsigned char * aadata, - const std::size_t aadata_size, - const unsigned char * key, - const std::size_t key_size, - const unsigned char (*iv)[12], - const unsigned char (*tag)[16] -) { - return decrypt_gcm(data, data_size, aadata, aadata_size, key, key_size, *iv, 12, *tag, 16); -} - -/** @} */ - -/** @defgroup CTR CTR - * CTR mode function - * @{ */ - -/** - * Encrypts or decrypt data in-place with CTR mode. - * - * @param [in,out] data Input data and output buffer. - * This buffer is replaced with encrypted / decrypted data. - * @param [in] data_size Data size. - * @param [in] key Cipher key - * @param [in] key_size Cipher key size. This value must be 16 (128-bit), 24 (192-bit), or 32 (256-bit). - * @param [in] nonce Nonce of the counter initialization. - * - * @returns kErrorOk - * @returns kErrorInvalidKeySize - * @since 1.0.0 - */ -inline Error crypt_ctr( - unsigned char * data, - const std::size_t data_size, - const unsigned char * key, - const std::size_t key_size, - const unsigned char (*nonce)[16] -) { - if (!detail::is_valid_key_size(key_size)) return kErrorInvalidKeySize; - const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size)); - - unsigned long pos = 0; - unsigned long blkpos = detail::kStateSize; - unsigned char blk[detail::kStateSize] = {}; - unsigned char counter[detail::kStateSize] = {}; - memcpy(counter, nonce, 16); - - while (pos < data_size) { - if (blkpos == detail::kStateSize) { - detail::encrypt_state(rkeys, counter, blk); - detail::incr_counter(counter); - blkpos = 0; - } - data[pos++] ^= blk[blkpos++]; - } - - return kErrorOk; -} - -/** @} */ - -} // namespace plusaes - -#endif // PLUSAES_HPP__ diff --git a/src/vendor/Soup/soup/sha1.cpp b/src/vendor/Soup/soup/sha1.cpp index ae2898387..9b565ad01 100644 --- a/src/vendor/Soup/soup/sha1.cpp +++ b/src/vendor/Soup/soup/sha1.cpp @@ -2,27 +2,22 @@ #include "base.hpp" -#if defined(SOUP_USE_INTRIN) && SOUP_BITS == 64 && (SOUP_X86 || SOUP_ARM) -#define SHA1_USE_INTRIN true +#if SOUP_BITS == 64 && (SOUP_X86 || SOUP_ARM) + #define SHA1_USE_INTRIN true #else -#define SHA1_USE_INTRIN false + #define SHA1_USE_INTRIN false #endif -#if SHA1_USE_INTRIN -#include "CpuInfo.hpp" -#include "Endian.hpp" -#endif #include "MemoryRefReader.hpp" -NAMESPACE_SOUP -{ #if SHA1_USE_INTRIN - namespace intrin - { - extern void sha1_transform(uint32_t state[5], const uint8_t data[64]) noexcept; - } + #include "CpuInfo.hpp" + #include "Endian.hpp" + #include "sha1_intrin.hpp" #endif +NAMESPACE_SOUP +{ // Original source: https://github.com/vog/sha1 // Original licence: Dedicated to the public domain. diff --git a/src/vendor/Soup/Intrin/sha1_transform.cpp b/src/vendor/Soup/soup/sha1_intrin.hpp similarity index 94% rename from src/vendor/Soup/Intrin/sha1_transform.cpp rename to src/vendor/Soup/soup/sha1_intrin.hpp index 9d5fbe1c4..1ecc86a54 100644 --- a/src/vendor/Soup/Intrin/sha1_transform.cpp +++ b/src/vendor/Soup/soup/sha1_intrin.hpp @@ -1,366 +1,374 @@ -#include "../soup/base.hpp" - -#include - -#if SOUP_X86 - #include -#elif SOUP_ARM - #include -#endif - -NAMESPACE_SOUP -{ - namespace intrin - { - // Original source: https://github.com/noloader/SHA-Intrinsics - // Original licence: Dedicated to the public domain. - -#if SOUP_X86 - void sha1_transform(uint32_t state[5], const uint8_t data[64]) noexcept - { - __m128i ABCD, ABCD_SAVE, E0, E0_SAVE, E1; - __m128i MSG0, MSG1, MSG2, MSG3; - const __m128i MASK = _mm_set_epi64x(0x0001020304050607ULL, 0x08090a0b0c0d0e0fULL); - - /* Load initial values */ - ABCD = _mm_loadu_si128((const __m128i*) state); - E0 = _mm_set_epi32(state[4], 0, 0, 0); - ABCD = _mm_shuffle_epi32(ABCD, 0x1B); - - /* Save current state */ - ABCD_SAVE = ABCD; - E0_SAVE = E0; - - /* Rounds 0-3 */ - MSG0 = _mm_loadu_si128((const __m128i*)(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 __m128i*)(data + 16)); - 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 __m128i*)(data + 32)); - 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 __m128i*)(data + 48)); - 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); - - /* Combine state */ - E0 = _mm_sha1nexte_epu32(E0, E0_SAVE); - ABCD = _mm_add_epi32(ABCD, ABCD_SAVE); - - /* Save state */ - ABCD = _mm_shuffle_epi32(ABCD, 0x1B); - _mm_storeu_si128((__m128i*) state, ABCD); - state[4] = _mm_extract_epi32(E0, 3); - } -#elif SOUP_ARM - void sha1_transform(uint32_t state[5], const uint8_t data[64]) noexcept - { - uint32x4_t ABCD, ABCD_SAVED; - uint32x4_t TMP0, TMP1; - uint32x4_t MSG0, MSG1, MSG2, MSG3; - uint32_t E0, E0_SAVED, E1; - - /* Load state */ - ABCD = vld1q_u32(&state[0]); - E0 = state[4]; - - /* Save state */ - ABCD_SAVED = ABCD; - E0_SAVED = E0; - - /* Load message */ - MSG0 = vld1q_u32((const uint32_t*)(data)); - MSG1 = vld1q_u32((const uint32_t*)(data + 16)); - MSG2 = vld1q_u32((const uint32_t*)(data + 32)); - MSG3 = vld1q_u32((const uint32_t*)(data + 48)); - - TMP0 = vaddq_u32(MSG0, vdupq_n_u32(0x5A827999)); - TMP1 = vaddq_u32(MSG1, vdupq_n_u32(0x5A827999)); - - /* Rounds 0-3 */ - E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); - ABCD = vsha1cq_u32(ABCD, E0, TMP0); - TMP0 = vaddq_u32(MSG2, vdupq_n_u32(0x5A827999)); - 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, vdupq_n_u32(0x5A827999)); - 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, vdupq_n_u32(0x5A827999)); - 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, vdupq_n_u32(0x6ED9EBA1)); - 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, vdupq_n_u32(0x6ED9EBA1)); - 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, vdupq_n_u32(0x6ED9EBA1)); - 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, vdupq_n_u32(0x6ED9EBA1)); - 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, vdupq_n_u32(0x6ED9EBA1)); - 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, vdupq_n_u32(0x8F1BBCDC)); - 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, vdupq_n_u32(0x8F1BBCDC)); - 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, vdupq_n_u32(0x8F1BBCDC)); - 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, vdupq_n_u32(0x8F1BBCDC)); - 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, vdupq_n_u32(0x8F1BBCDC)); - 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, vdupq_n_u32(0xCA62C1D6)); - 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, vdupq_n_u32(0xCA62C1D6)); - 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, vdupq_n_u32(0xCA62C1D6)); - 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, vdupq_n_u32(0xCA62C1D6)); - 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, vdupq_n_u32(0xCA62C1D6)); - 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); - - /* Combine state */ - E0 += E0_SAVED; - ABCD = vaddq_u32(ABCD_SAVED, ABCD); - - /* Save state */ - vst1q_u32(&state[0], ABCD); - state[4] = E0; - } -#endif - } -} +// THIS FILE IS FOR INTERNAL USE ONLY. DO NOT INCLUDE THIS IN YOUR OWN CODE. + +#include "base.hpp" + +#include + +#if SOUP_X86 + #include +#elif SOUP_ARM + #include +#endif + +NAMESPACE_SOUP +{ + namespace intrin + { + // Original source: https://github.com/noloader/SHA-Intrinsics + // Original licence: Dedicated to the public domain. + +#if SOUP_X86 + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("sha,sse4.1"))) + #endif + void sha1_transform(uint32_t state[5], const uint8_t data[64]) noexcept + { + __m128i ABCD, ABCD_SAVE, E0, E0_SAVE, E1; + __m128i MSG0, MSG1, MSG2, MSG3; + const __m128i MASK = _mm_set_epi64x(0x0001020304050607ULL, 0x08090a0b0c0d0e0fULL); + + /* Load initial values */ + ABCD = _mm_loadu_si128((const __m128i*) state); + E0 = _mm_set_epi32(state[4], 0, 0, 0); + ABCD = _mm_shuffle_epi32(ABCD, 0x1B); + + /* Save current state */ + ABCD_SAVE = ABCD; + E0_SAVE = E0; + + /* Rounds 0-3 */ + MSG0 = _mm_loadu_si128((const __m128i*)(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 __m128i*)(data + 16)); + 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 __m128i*)(data + 32)); + 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 __m128i*)(data + 48)); + 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); + + /* Combine state */ + E0 = _mm_sha1nexte_epu32(E0, E0_SAVE); + ABCD = _mm_add_epi32(ABCD, ABCD_SAVE); + + /* Save state */ + ABCD = _mm_shuffle_epi32(ABCD, 0x1B); + _mm_storeu_si128((__m128i*) state, ABCD); + state[4] = _mm_extract_epi32(E0, 3); + } +#elif SOUP_ARM + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("sha2"))) + #endif + void sha1_transform(uint32_t state[5], const uint8_t data[64]) noexcept + { + uint32x4_t ABCD, ABCD_SAVED; + uint32x4_t TMP0, TMP1; + uint32x4_t MSG0, MSG1, MSG2, MSG3; + uint32_t E0, E0_SAVED, E1; + + /* Load state */ + ABCD = vld1q_u32(&state[0]); + E0 = state[4]; + + /* Save state */ + ABCD_SAVED = ABCD; + E0_SAVED = E0; + + /* Load message */ + MSG0 = vld1q_u32((const uint32_t*)(data)); + MSG1 = vld1q_u32((const uint32_t*)(data + 16)); + MSG2 = vld1q_u32((const uint32_t*)(data + 32)); + MSG3 = vld1q_u32((const uint32_t*)(data + 48)); + + TMP0 = vaddq_u32(MSG0, vdupq_n_u32(0x5A827999)); + TMP1 = vaddq_u32(MSG1, vdupq_n_u32(0x5A827999)); + + /* Rounds 0-3 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, vdupq_n_u32(0x5A827999)); + 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, vdupq_n_u32(0x5A827999)); + 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, vdupq_n_u32(0x5A827999)); + 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, vdupq_n_u32(0x6ED9EBA1)); + 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, vdupq_n_u32(0x6ED9EBA1)); + 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, vdupq_n_u32(0x6ED9EBA1)); + 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, vdupq_n_u32(0x6ED9EBA1)); + 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, vdupq_n_u32(0x6ED9EBA1)); + 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, vdupq_n_u32(0x8F1BBCDC)); + 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, vdupq_n_u32(0x8F1BBCDC)); + 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, vdupq_n_u32(0x8F1BBCDC)); + 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, vdupq_n_u32(0x8F1BBCDC)); + 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, vdupq_n_u32(0x8F1BBCDC)); + 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, vdupq_n_u32(0xCA62C1D6)); + 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, vdupq_n_u32(0xCA62C1D6)); + 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, vdupq_n_u32(0xCA62C1D6)); + 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, vdupq_n_u32(0xCA62C1D6)); + 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, vdupq_n_u32(0xCA62C1D6)); + 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); + + /* Combine state */ + E0 += E0_SAVED; + ABCD = vaddq_u32(ABCD_SAVED, ABCD); + + /* Save state */ + vst1q_u32(&state[0], ABCD); + state[4] = E0; + } +#endif + } +} diff --git a/src/vendor/Soup/soup/sha256.cpp b/src/vendor/Soup/soup/sha256.cpp index f93aa623f..8e4b66788 100644 --- a/src/vendor/Soup/soup/sha256.cpp +++ b/src/vendor/Soup/soup/sha256.cpp @@ -2,16 +2,18 @@ #include "base.hpp" -#if defined(SOUP_USE_INTRIN) && SOUP_BITS == 64 && (SOUP_X86 || SOUP_ARM) -#define SHA256_USE_INTRIN true +#if SOUP_BITS == 64 && (SOUP_X86 || SOUP_ARM) + #define SHA256_USE_INTRIN true #else -#define SHA256_USE_INTRIN false + #define SHA256_USE_INTRIN false #endif +#include "Reader.hpp" + #if SHA256_USE_INTRIN -#include "CpuInfo.hpp" + #include "CpuInfo.hpp" + #include "sha256_intrin.hpp" #endif -#include "Reader.hpp" /* Original source: https://github.com/983/SHA-256 @@ -20,13 +22,6 @@ Original licence: Dedicated to the public domain. NAMESPACE_SOUP { -#if SHA256_USE_INTRIN - namespace intrin - { - extern void sha256_transform(uint32_t state[8], const uint8_t data[64]) noexcept; - } -#endif - struct sha256_state { uint32_t state[8]; diff --git a/src/vendor/Soup/Intrin/sha256_transform.cpp b/src/vendor/Soup/soup/sha256_intrin.hpp similarity index 95% rename from src/vendor/Soup/Intrin/sha256_transform.cpp rename to src/vendor/Soup/soup/sha256_intrin.hpp index 4e7f0db64..60a8b6378 100644 --- a/src/vendor/Soup/Intrin/sha256_transform.cpp +++ b/src/vendor/Soup/soup/sha256_intrin.hpp @@ -1,382 +1,390 @@ -#include "../soup/base.hpp" - -#include - -#if SOUP_X86 -#include -#elif SOUP_ARM -#include -#endif - -NAMESPACE_SOUP -{ - namespace intrin - { - // Original source: https://github.com/noloader/SHA-Intrinsics - // Original licence: Dedicated to the public domain. - -#if SOUP_X86 - void sha256_transform(uint32_t state[8], const uint8_t data[64]) noexcept - { - __m128i STATE0, STATE1; - __m128i MSG, TMP; - __m128i MSG0, MSG1, MSG2, MSG3; - __m128i ABEF_SAVE, CDGH_SAVE; - const __m128i MASK = _mm_set_epi64x(0x0c0d0e0f08090a0bULL, 0x0405060700010203ULL); - - /* Load initial values */ - TMP = _mm_loadu_si128((const __m128i*) & state[0]); - STATE1 = _mm_loadu_si128((const __m128i*) & state[4]); - - 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 */ - - /* Save current state */ - ABEF_SAVE = STATE0; - CDGH_SAVE = STATE1; - - /* Rounds 0-3 */ - MSG = _mm_loadu_si128((const __m128i*) (data + 0)); - MSG0 = _mm_shuffle_epi8(MSG, MASK); - MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0xE9B5DBA5B5C0FBCFULL, 0x71374491428A2F98ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - - /* Rounds 4-7 */ - MSG1 = _mm_loadu_si128((const __m128i*) (data + 16)); - MSG1 = _mm_shuffle_epi8(MSG1, MASK); - MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0xAB1C5ED5923F82A4ULL, 0x59F111F13956C25BULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG0 = _mm_sha256msg1_epu32(MSG0, MSG1); - - /* Rounds 8-11 */ - MSG2 = _mm_loadu_si128((const __m128i*) (data + 32)); - MSG2 = _mm_shuffle_epi8(MSG2, MASK); - MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0x550C7DC3243185BEULL, 0x12835B01D807AA98ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG1 = _mm_sha256msg1_epu32(MSG1, MSG2); - - /* Rounds 12-15 */ - MSG3 = _mm_loadu_si128((const __m128i*) (data + 48)); - MSG3 = _mm_shuffle_epi8(MSG3, MASK); - MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0xC19BF1749BDC06A7ULL, 0x80DEB1FE72BE5D74ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG3, MSG2, 4); - MSG0 = _mm_add_epi32(MSG0, TMP); - MSG0 = _mm_sha256msg2_epu32(MSG0, MSG3); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG2 = _mm_sha256msg1_epu32(MSG2, MSG3); - - /* Rounds 16-19 */ - MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0x240CA1CC0FC19DC6ULL, 0xEFBE4786E49B69C1ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG0, MSG3, 4); - MSG1 = _mm_add_epi32(MSG1, TMP); - MSG1 = _mm_sha256msg2_epu32(MSG1, MSG0); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG3 = _mm_sha256msg1_epu32(MSG3, MSG0); - - /* Rounds 20-23 */ - MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0x76F988DA5CB0A9DCULL, 0x4A7484AA2DE92C6FULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG1, MSG0, 4); - MSG2 = _mm_add_epi32(MSG2, TMP); - MSG2 = _mm_sha256msg2_epu32(MSG2, MSG1); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG0 = _mm_sha256msg1_epu32(MSG0, MSG1); - - /* Rounds 24-27 */ - MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0xBF597FC7B00327C8ULL, 0xA831C66D983E5152ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG2, MSG1, 4); - MSG3 = _mm_add_epi32(MSG3, TMP); - MSG3 = _mm_sha256msg2_epu32(MSG3, MSG2); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG1 = _mm_sha256msg1_epu32(MSG1, MSG2); - - /* Rounds 28-31 */ - MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0x1429296706CA6351ULL, 0xD5A79147C6E00BF3ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG3, MSG2, 4); - MSG0 = _mm_add_epi32(MSG0, TMP); - MSG0 = _mm_sha256msg2_epu32(MSG0, MSG3); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG2 = _mm_sha256msg1_epu32(MSG2, MSG3); - - /* Rounds 32-35 */ - MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0x53380D134D2C6DFCULL, 0x2E1B213827B70A85ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG0, MSG3, 4); - MSG1 = _mm_add_epi32(MSG1, TMP); - MSG1 = _mm_sha256msg2_epu32(MSG1, MSG0); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG3 = _mm_sha256msg1_epu32(MSG3, MSG0); - - /* Rounds 36-39 */ - MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0x92722C8581C2C92EULL, 0x766A0ABB650A7354ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG1, MSG0, 4); - MSG2 = _mm_add_epi32(MSG2, TMP); - MSG2 = _mm_sha256msg2_epu32(MSG2, MSG1); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG0 = _mm_sha256msg1_epu32(MSG0, MSG1); - - /* Rounds 40-43 */ - MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0xC76C51A3C24B8B70ULL, 0xA81A664BA2BFE8A1ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG2, MSG1, 4); - MSG3 = _mm_add_epi32(MSG3, TMP); - MSG3 = _mm_sha256msg2_epu32(MSG3, MSG2); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG1 = _mm_sha256msg1_epu32(MSG1, MSG2); - - /* Rounds 44-47 */ - MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0x106AA070F40E3585ULL, 0xD6990624D192E819ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG3, MSG2, 4); - MSG0 = _mm_add_epi32(MSG0, TMP); - MSG0 = _mm_sha256msg2_epu32(MSG0, MSG3); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG2 = _mm_sha256msg1_epu32(MSG2, MSG3); - - /* Rounds 48-51 */ - MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0x34B0BCB52748774CULL, 0x1E376C0819A4C116ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG0, MSG3, 4); - MSG1 = _mm_add_epi32(MSG1, TMP); - MSG1 = _mm_sha256msg2_epu32(MSG1, MSG0); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - MSG3 = _mm_sha256msg1_epu32(MSG3, MSG0); - - /* Rounds 52-55 */ - MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0x682E6FF35B9CCA4FULL, 0x4ED8AA4A391C0CB3ULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG1, MSG0, 4); - MSG2 = _mm_add_epi32(MSG2, TMP); - MSG2 = _mm_sha256msg2_epu32(MSG2, MSG1); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - - /* Rounds 56-59 */ - MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0x8CC7020884C87814ULL, 0x78A5636F748F82EEULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - TMP = _mm_alignr_epi8(MSG2, MSG1, 4); - MSG3 = _mm_add_epi32(MSG3, TMP); - MSG3 = _mm_sha256msg2_epu32(MSG3, MSG2); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - - /* Rounds 60-63 */ - MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0xC67178F2BEF9A3F7ULL, 0xA4506CEB90BEFFFAULL)); - STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); - MSG = _mm_shuffle_epi32(MSG, 0x0E); - STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); - - /* Combine state */ - STATE0 = _mm_add_epi32(STATE0, ABEF_SAVE); - STATE1 = _mm_add_epi32(STATE1, CDGH_SAVE); - - 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((__m128i*) & state[0], STATE0); - _mm_storeu_si128((__m128i*) & state[4], STATE1); - } -#elif SOUP_ARM - inline const uint32_t sha256_k[8 * 8] = { - 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, - }; - - void sha256_transform(uint32_t state[8], const uint8_t data[64]) noexcept - { - uint32x4_t STATE0, STATE1, ABEF_SAVE, CDGH_SAVE; - uint32x4_t MSG0, MSG1, MSG2, MSG3; - uint32x4_t TMP0, TMP1, TMP2; - - /* Load state */ - STATE0 = vld1q_u32(&state[0]); - STATE1 = vld1q_u32(&state[4]); - - /* Save state */ - ABEF_SAVE = STATE0; - CDGH_SAVE = STATE1; - - /* Load message */ - MSG0 = vld1q_u32((const uint32_t*)(data + 0)); - MSG1 = vld1q_u32((const uint32_t*)(data + 16)); - MSG2 = vld1q_u32((const uint32_t*)(data + 32)); - MSG3 = vld1q_u32((const uint32_t*)(data + 48)); - - /* Reverse for little endian */ - 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); - - /* Combine state */ - STATE0 = vaddq_u32(STATE0, ABEF_SAVE); - STATE1 = vaddq_u32(STATE1, CDGH_SAVE); - - /* Save state */ - vst1q_u32(&state[0], STATE0); - vst1q_u32(&state[4], STATE1); - } -#endif - } -} +// THIS FILE IS FOR INTERNAL USE ONLY. DO NOT INCLUDE THIS IN YOUR OWN CODE. + +#include "base.hpp" + +#include + +#if SOUP_X86 + #include +#elif SOUP_ARM + #include +#endif + +NAMESPACE_SOUP +{ + namespace intrin + { + // Original source: https://github.com/noloader/SHA-Intrinsics + // Original licence: Dedicated to the public domain. + +#if SOUP_X86 + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("sha,sse4.1"))) + #endif + void sha256_transform(uint32_t state[8], const uint8_t data[64]) noexcept + { + __m128i STATE0, STATE1; + __m128i MSG, TMP; + __m128i MSG0, MSG1, MSG2, MSG3; + __m128i ABEF_SAVE, CDGH_SAVE; + const __m128i MASK = _mm_set_epi64x(0x0c0d0e0f08090a0bULL, 0x0405060700010203ULL); + + /* Load initial values */ + TMP = _mm_loadu_si128((const __m128i*) & state[0]); + STATE1 = _mm_loadu_si128((const __m128i*) & state[4]); + + 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 */ + + /* Save current state */ + ABEF_SAVE = STATE0; + CDGH_SAVE = STATE1; + + /* Rounds 0-3 */ + MSG = _mm_loadu_si128((const __m128i*) (data + 0)); + MSG0 = _mm_shuffle_epi8(MSG, MASK); + MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0xE9B5DBA5B5C0FBCFULL, 0x71374491428A2F98ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + /* Rounds 4-7 */ + MSG1 = _mm_loadu_si128((const __m128i*) (data + 16)); + MSG1 = _mm_shuffle_epi8(MSG1, MASK); + MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0xAB1C5ED5923F82A4ULL, 0x59F111F13956C25BULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG0 = _mm_sha256msg1_epu32(MSG0, MSG1); + + /* Rounds 8-11 */ + MSG2 = _mm_loadu_si128((const __m128i*) (data + 32)); + MSG2 = _mm_shuffle_epi8(MSG2, MASK); + MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0x550C7DC3243185BEULL, 0x12835B01D807AA98ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG1 = _mm_sha256msg1_epu32(MSG1, MSG2); + + /* Rounds 12-15 */ + MSG3 = _mm_loadu_si128((const __m128i*) (data + 48)); + MSG3 = _mm_shuffle_epi8(MSG3, MASK); + MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0xC19BF1749BDC06A7ULL, 0x80DEB1FE72BE5D74ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG3, MSG2, 4); + MSG0 = _mm_add_epi32(MSG0, TMP); + MSG0 = _mm_sha256msg2_epu32(MSG0, MSG3); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG2 = _mm_sha256msg1_epu32(MSG2, MSG3); + + /* Rounds 16-19 */ + MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0x240CA1CC0FC19DC6ULL, 0xEFBE4786E49B69C1ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG0, MSG3, 4); + MSG1 = _mm_add_epi32(MSG1, TMP); + MSG1 = _mm_sha256msg2_epu32(MSG1, MSG0); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG3 = _mm_sha256msg1_epu32(MSG3, MSG0); + + /* Rounds 20-23 */ + MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0x76F988DA5CB0A9DCULL, 0x4A7484AA2DE92C6FULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG1, MSG0, 4); + MSG2 = _mm_add_epi32(MSG2, TMP); + MSG2 = _mm_sha256msg2_epu32(MSG2, MSG1); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG0 = _mm_sha256msg1_epu32(MSG0, MSG1); + + /* Rounds 24-27 */ + MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0xBF597FC7B00327C8ULL, 0xA831C66D983E5152ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG2, MSG1, 4); + MSG3 = _mm_add_epi32(MSG3, TMP); + MSG3 = _mm_sha256msg2_epu32(MSG3, MSG2); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG1 = _mm_sha256msg1_epu32(MSG1, MSG2); + + /* Rounds 28-31 */ + MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0x1429296706CA6351ULL, 0xD5A79147C6E00BF3ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG3, MSG2, 4); + MSG0 = _mm_add_epi32(MSG0, TMP); + MSG0 = _mm_sha256msg2_epu32(MSG0, MSG3); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG2 = _mm_sha256msg1_epu32(MSG2, MSG3); + + /* Rounds 32-35 */ + MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0x53380D134D2C6DFCULL, 0x2E1B213827B70A85ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG0, MSG3, 4); + MSG1 = _mm_add_epi32(MSG1, TMP); + MSG1 = _mm_sha256msg2_epu32(MSG1, MSG0); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG3 = _mm_sha256msg1_epu32(MSG3, MSG0); + + /* Rounds 36-39 */ + MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0x92722C8581C2C92EULL, 0x766A0ABB650A7354ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG1, MSG0, 4); + MSG2 = _mm_add_epi32(MSG2, TMP); + MSG2 = _mm_sha256msg2_epu32(MSG2, MSG1); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG0 = _mm_sha256msg1_epu32(MSG0, MSG1); + + /* Rounds 40-43 */ + MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0xC76C51A3C24B8B70ULL, 0xA81A664BA2BFE8A1ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG2, MSG1, 4); + MSG3 = _mm_add_epi32(MSG3, TMP); + MSG3 = _mm_sha256msg2_epu32(MSG3, MSG2); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG1 = _mm_sha256msg1_epu32(MSG1, MSG2); + + /* Rounds 44-47 */ + MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0x106AA070F40E3585ULL, 0xD6990624D192E819ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG3, MSG2, 4); + MSG0 = _mm_add_epi32(MSG0, TMP); + MSG0 = _mm_sha256msg2_epu32(MSG0, MSG3); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG2 = _mm_sha256msg1_epu32(MSG2, MSG3); + + /* Rounds 48-51 */ + MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0x34B0BCB52748774CULL, 0x1E376C0819A4C116ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG0, MSG3, 4); + MSG1 = _mm_add_epi32(MSG1, TMP); + MSG1 = _mm_sha256msg2_epu32(MSG1, MSG0); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG3 = _mm_sha256msg1_epu32(MSG3, MSG0); + + /* Rounds 52-55 */ + MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0x682E6FF35B9CCA4FULL, 0x4ED8AA4A391C0CB3ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG1, MSG0, 4); + MSG2 = _mm_add_epi32(MSG2, TMP); + MSG2 = _mm_sha256msg2_epu32(MSG2, MSG1); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + /* Rounds 56-59 */ + MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0x8CC7020884C87814ULL, 0x78A5636F748F82EEULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG2, MSG1, 4); + MSG3 = _mm_add_epi32(MSG3, TMP); + MSG3 = _mm_sha256msg2_epu32(MSG3, MSG2); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + /* Rounds 60-63 */ + MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0xC67178F2BEF9A3F7ULL, 0xA4506CEB90BEFFFAULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + /* Combine state */ + STATE0 = _mm_add_epi32(STATE0, ABEF_SAVE); + STATE1 = _mm_add_epi32(STATE1, CDGH_SAVE); + + 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((__m128i*) & state[0], STATE0); + _mm_storeu_si128((__m128i*) & state[4], STATE1); + } +#elif SOUP_ARM + inline const uint32_t sha256_k[8 * 8] = { + 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, + }; + + #if defined(__GNUC__) || defined(__clang__) + __attribute__((target("sha2"))) + #endif + void sha256_transform(uint32_t state[8], const uint8_t data[64]) noexcept + { + uint32x4_t STATE0, STATE1, ABEF_SAVE, CDGH_SAVE; + uint32x4_t MSG0, MSG1, MSG2, MSG3; + uint32x4_t TMP0, TMP1, TMP2; + + /* Load state */ + STATE0 = vld1q_u32(&state[0]); + STATE1 = vld1q_u32(&state[4]); + + /* Save state */ + ABEF_SAVE = STATE0; + CDGH_SAVE = STATE1; + + /* Load message */ + MSG0 = vld1q_u32((const uint32_t*)(data + 0)); + MSG1 = vld1q_u32((const uint32_t*)(data + 16)); + MSG2 = vld1q_u32((const uint32_t*)(data + 32)); + MSG3 = vld1q_u32((const uint32_t*)(data + 48)); + + /* Reverse for little endian */ + 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); + + /* Combine state */ + STATE0 = vaddq_u32(STATE0, ABEF_SAVE); + STATE1 = vaddq_u32(STATE1, CDGH_SAVE); + + /* Save state */ + vst1q_u32(&state[0], STATE0); + vst1q_u32(&state[4], STATE1); + } +#endif + } +}