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
"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",
- "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",
@@ -40,11 +39,9 @@ NAMESPACE_SOUP
"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",
- "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",
- "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",
@@ -66,7 +63,6 @@ NAMESPACE_SOUP
"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",
- "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",
@@ -149,10 +145,29 @@ NAMESPACE_SOUP
"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",
- "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",
};
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