diff --git a/Foundation/Foundation.vxbuild b/Foundation/Foundation.vxbuild
index 1e6ad3a27..01634f496 100644
--- a/Foundation/Foundation.vxbuild
+++ b/Foundation/Foundation.vxbuild
@@ -92,6 +92,8 @@ SOURCES="
Runnable.cpp
SHA1Engine.cpp
SHA2Engine.cpp
+ SHA3Engine.cpp
+ BLAKE2Engine.cpp
Semaphore.cpp
SharedLibrary.cpp
SimpleFileChannel.cpp
diff --git a/Foundation/Foundation_CE_vs90.vcproj b/Foundation/Foundation_CE_vs90.vcproj
index 4ab67f9ec..9c12e2204 100644
--- a/Foundation/Foundation_CE_vs90.vcproj
+++ b/Foundation/Foundation_CE_vs90.vcproj
@@ -1806,6 +1806,10 @@
RelativePath=".\src\SHA1Engine.cpp"/>
+
+
@@ -1829,6 +1833,10 @@
RelativePath=".\include\Poco\SHA1Engine.h"/>
+
+
+
@@ -611,6 +611,8 @@
+
+
@@ -1238,6 +1240,8 @@
+
+
@@ -1447,4 +1451,4 @@
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_WEC2013_vs110.vcxproj.filters b/Foundation/Foundation_WEC2013_vs110.vcxproj.filters
index 12afbd6bb..28d93c001 100644
--- a/Foundation/Foundation_WEC2013_vs110.vcxproj.filters
+++ b/Foundation/Foundation_WEC2013_vs110.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -468,6 +468,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1367,6 +1373,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1994,4 +2006,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_WEC2013_vs120.vcxproj b/Foundation/Foundation_WEC2013_vs120.vcxproj
index 6231a05bc..72145be10 100644
--- a/Foundation/Foundation_WEC2013_vs120.vcxproj
+++ b/Foundation/Foundation_WEC2013_vs120.vcxproj
@@ -1,4 +1,4 @@
-
+
@@ -611,6 +611,8 @@
+
+
@@ -1238,6 +1240,8 @@
+
+
@@ -1447,4 +1451,4 @@
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_WEC2013_vs120.vcxproj.filters b/Foundation/Foundation_WEC2013_vs120.vcxproj.filters
index 8438c98cd..4d87cbc59 100644
--- a/Foundation/Foundation_WEC2013_vs120.vcxproj.filters
+++ b/Foundation/Foundation_WEC2013_vs120.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -468,6 +468,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1367,6 +1373,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1994,4 +2006,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_vs100.vcxproj b/Foundation/Foundation_vs100.vcxproj
index f0ef4e5b2..69cbbd03d 100644
--- a/Foundation/Foundation_vs100.vcxproj
+++ b/Foundation/Foundation_vs100.vcxproj
@@ -540,6 +540,8 @@
+
+
@@ -1134,6 +1136,8 @@
+
+
diff --git a/Foundation/Foundation_vs100.vcxproj.filters b/Foundation/Foundation_vs100.vcxproj.filters
index fa69faf52..fb7452c84 100644
--- a/Foundation/Foundation_vs100.vcxproj.filters
+++ b/Foundation/Foundation_vs100.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1355,6 +1361,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1934,4 +1946,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_vs110.vcxproj b/Foundation/Foundation_vs110.vcxproj
index 136e586c8..927a104d2 100644
--- a/Foundation/Foundation_vs110.vcxproj
+++ b/Foundation/Foundation_vs110.vcxproj
@@ -544,6 +544,8 @@
+
+
@@ -1138,6 +1140,8 @@
+
+
diff --git a/Foundation/Foundation_vs110.vcxproj.filters b/Foundation/Foundation_vs110.vcxproj.filters
index 415ffeb33..6d42c05f2 100644
--- a/Foundation/Foundation_vs110.vcxproj.filters
+++ b/Foundation/Foundation_vs110.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1355,6 +1361,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1934,4 +1946,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_vs120.vcxproj b/Foundation/Foundation_vs120.vcxproj
index 774b1fb9e..130886103 100644
--- a/Foundation/Foundation_vs120.vcxproj
+++ b/Foundation/Foundation_vs120.vcxproj
@@ -548,6 +548,8 @@
+
+
@@ -1142,6 +1144,8 @@
+
+
diff --git a/Foundation/Foundation_vs120.vcxproj.filters b/Foundation/Foundation_vs120.vcxproj.filters
index 3b33ea1c4..a3c0fa387 100644
--- a/Foundation/Foundation_vs120.vcxproj.filters
+++ b/Foundation/Foundation_vs120.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1355,6 +1361,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1934,4 +1946,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_vs140.vcxproj b/Foundation/Foundation_vs140.vcxproj
index 7596761f2..4120b7711 100644
--- a/Foundation/Foundation_vs140.vcxproj
+++ b/Foundation/Foundation_vs140.vcxproj
@@ -826,6 +826,8 @@
+
+
true
@@ -1234,6 +1236,8 @@
+
+
diff --git a/Foundation/Foundation_vs140.vcxproj.filters b/Foundation/Foundation_vs140.vcxproj.filters
index 91e38cb8f..134650ead 100644
--- a/Foundation/Foundation_vs140.vcxproj.filters
+++ b/Foundation/Foundation_vs140.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1355,6 +1361,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1934,4 +1946,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_vs150.vcxproj b/Foundation/Foundation_vs150.vcxproj
index 206eaaa60..09c896188 100644
--- a/Foundation/Foundation_vs150.vcxproj
+++ b/Foundation/Foundation_vs150.vcxproj
@@ -826,6 +826,8 @@
+
+
true
@@ -1234,6 +1236,8 @@
+
+
diff --git a/Foundation/Foundation_vs150.vcxproj.filters b/Foundation/Foundation_vs150.vcxproj.filters
index 91e38cb8f..134650ead 100644
--- a/Foundation/Foundation_vs150.vcxproj.filters
+++ b/Foundation/Foundation_vs150.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1355,6 +1361,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1934,4 +1946,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_vs90.vcproj b/Foundation/Foundation_vs90.vcproj
index fdf7b3c90..ffb1f1ec1 100644
--- a/Foundation/Foundation_vs90.vcproj
+++ b/Foundation/Foundation_vs90.vcproj
@@ -1760,6 +1760,10 @@
RelativePath=".\src\SHA1Engine.cpp"/>
+
+
@@ -1783,6 +1787,10 @@
RelativePath=".\include\Poco\SHA1Engine.h"/>
+
+
+
+
@@ -1132,6 +1134,8 @@
+
+
diff --git a/Foundation/Foundation_x64_vs100.vcxproj.filters b/Foundation/Foundation_x64_vs100.vcxproj.filters
index 5fb7907ea..c7acec533 100644
--- a/Foundation/Foundation_x64_vs100.vcxproj.filters
+++ b/Foundation/Foundation_x64_vs100.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1931,4 +1937,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_x64_vs110.vcxproj b/Foundation/Foundation_x64_vs110.vcxproj
index dabc282b1..f2c077df7 100644
--- a/Foundation/Foundation_x64_vs110.vcxproj
+++ b/Foundation/Foundation_x64_vs110.vcxproj
@@ -542,6 +542,8 @@
+
+
@@ -1136,6 +1138,8 @@
+
+
diff --git a/Foundation/Foundation_x64_vs110.vcxproj.filters b/Foundation/Foundation_x64_vs110.vcxproj.filters
index 3a05a478d..3eb87c1c5 100644
--- a/Foundation/Foundation_x64_vs110.vcxproj.filters
+++ b/Foundation/Foundation_x64_vs110.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1355,6 +1361,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1934,4 +1946,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_x64_vs120.vcxproj b/Foundation/Foundation_x64_vs120.vcxproj
index 8fb7a7bec..47f44f699 100644
--- a/Foundation/Foundation_x64_vs120.vcxproj
+++ b/Foundation/Foundation_x64_vs120.vcxproj
@@ -549,6 +549,8 @@
+
+
@@ -1143,6 +1145,8 @@
+
+
diff --git a/Foundation/Foundation_x64_vs120.vcxproj.filters b/Foundation/Foundation_x64_vs120.vcxproj.filters
index 6b187f9ad..972fed2a1 100644
--- a/Foundation/Foundation_x64_vs120.vcxproj.filters
+++ b/Foundation/Foundation_x64_vs120.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1355,6 +1361,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1934,4 +1946,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_x64_vs140.vcxproj b/Foundation/Foundation_x64_vs140.vcxproj
index b101f201a..afa9272fe 100644
--- a/Foundation/Foundation_x64_vs140.vcxproj
+++ b/Foundation/Foundation_x64_vs140.vcxproj
@@ -824,6 +824,8 @@
+
+
true
@@ -1232,6 +1234,8 @@
+
+
diff --git a/Foundation/Foundation_x64_vs140.vcxproj.filters b/Foundation/Foundation_x64_vs140.vcxproj.filters
index 3a32faa67..c1b0fc237 100644
--- a/Foundation/Foundation_x64_vs140.vcxproj.filters
+++ b/Foundation/Foundation_x64_vs140.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1355,6 +1361,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1934,4 +1946,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_x64_vs150.vcxproj b/Foundation/Foundation_x64_vs150.vcxproj
index 683e08868..e72ae3486 100644
--- a/Foundation/Foundation_x64_vs150.vcxproj
+++ b/Foundation/Foundation_x64_vs150.vcxproj
@@ -824,6 +824,8 @@
+
+
true
@@ -1232,6 +1234,8 @@
+
+
diff --git a/Foundation/Foundation_x64_vs150.vcxproj.filters b/Foundation/Foundation_x64_vs150.vcxproj.filters
index 3a32faa67..c1b0fc237 100644
--- a/Foundation/Foundation_x64_vs150.vcxproj.filters
+++ b/Foundation/Foundation_x64_vs150.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -480,6 +480,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
SharedLibrary\Source Files
@@ -1355,6 +1361,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
SharedLibrary\Header Files
@@ -1934,4 +1946,4 @@
Logging\Message Files
-
\ No newline at end of file
+
diff --git a/Foundation/Foundation_x64_vs90.vcproj b/Foundation/Foundation_x64_vs90.vcproj
index 26557619f..75f6e7878 100644
--- a/Foundation/Foundation_x64_vs90.vcproj
+++ b/Foundation/Foundation_x64_vs90.vcproj
@@ -1765,6 +1765,10 @@
RelativePath=".\src\SHA1Engine.cpp"/>
+
+
@@ -1788,6 +1792,10 @@
RelativePath=".\include\Poco\SHA1Engine.h"/>
+
+
+#include
+#include
+
+#if defined(_MSC_VER)
+#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
+#else
+#define BLAKE2_PACKED(x) x __attribute__((packed))
+#endif
+#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
+#if defined(_MSC_VER)
+#define BLAKE2_INLINE __inline
+#elif defined(__GNUC__)
+#define BLAKE2_INLINE __inline__
+#else
+#define BLAKE2_INLINE
+#endif
+#else
+#define BLAKE2_INLINE inline
+#endif
+
+namespace Poco {
+static BLAKE2_INLINE uint32_t load32(const void *src)
+{
+#if defined(POCO_ARCH_LITTLE_ENDIAN)
+ uint32_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ const uint8_t *p = (const uint8_t *)src;
+ return ((uint32_t)(p[0]) << 0) |
+ ((uint32_t)(p[1]) << 8) |
+ ((uint32_t)(p[2]) << 16) |
+ ((uint32_t)(p[3]) << 24);
+#endif
+}
+
+static BLAKE2_INLINE uint64_t load64(const void *src)
+{
+#if defined(POCO_ARCH_LITTLE_ENDIAN)
+ uint64_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ const uint8_t *p = (const uint8_t *)src;
+ return ((uint64_t)(p[0]) << 0) |
+ ((uint64_t)(p[1]) << 8) |
+ ((uint64_t)(p[2]) << 16) |
+ ((uint64_t)(p[3]) << 24) |
+ ((uint64_t)(p[4]) << 32) |
+ ((uint64_t)(p[5]) << 40) |
+ ((uint64_t)(p[6]) << 48) |
+ ((uint64_t)(p[7]) << 56);
+#endif
+}
+
+static BLAKE2_INLINE uint16_t load16(const void *src)
+{
+#if defined(POCO_ARCH_LITTLE_ENDIAN)
+ uint16_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ const uint8_t *p = (const uint8_t *)src;
+ return ((uint16_t)(p[0]) << 0) |
+ ((uint16_t)(p[1]) << 8);
+#endif
+}
+
+static BLAKE2_INLINE void store16(void *dst, uint16_t w)
+{
+#if defined(POCO_ARCH_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
+ uint8_t *p = (uint8_t *)dst;
+ *p++ = (uint8_t)w; w >>= 8;
+ *p++ = (uint8_t)w;
+#endif
+}
+
+static BLAKE2_INLINE void store32(void *dst, uint32_t w)
+{
+#if defined(POCO_ARCH_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
+ uint8_t *p = (uint8_t *)dst;
+ p[0] = (uint8_t)(w >> 0);
+ p[1] = (uint8_t)(w >> 8);
+ p[2] = (uint8_t)(w >> 16);
+ p[3] = (uint8_t)(w >> 24);
+#endif
+}
+
+static BLAKE2_INLINE void store64(void *dst, uint64_t w)
+{
+#if defined(POCO_ARCH_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
+ uint8_t *p = (uint8_t *)dst;
+ p[0] = (uint8_t)(w >> 0);
+ p[1] = (uint8_t)(w >> 8);
+ p[2] = (uint8_t)(w >> 16);
+ p[3] = (uint8_t)(w >> 24);
+ p[4] = (uint8_t)(w >> 32);
+ p[5] = (uint8_t)(w >> 40);
+ p[6] = (uint8_t)(w >> 48);
+ p[7] = (uint8_t)(w >> 56);
+#endif
+}
+
+static BLAKE2_INLINE uint64_t load48(const void *src)
+{
+ const uint8_t *p = (const uint8_t *)src;
+ return ((uint64_t)(p[0]) << 0) |
+ ((uint64_t)(p[1]) << 8) |
+ ((uint64_t)(p[2]) << 16) |
+ ((uint64_t)(p[3]) << 24) |
+ ((uint64_t)(p[4]) << 32) |
+ ((uint64_t)(p[5]) << 40);
+}
+
+static BLAKE2_INLINE void store48(void *dst, uint64_t w)
+{
+ uint8_t *p = (uint8_t *)dst;
+ p[0] = (uint8_t)(w >> 0);
+ p[1] = (uint8_t)(w >> 8);
+ p[2] = (uint8_t)(w >> 16);
+ p[3] = (uint8_t)(w >> 24);
+ p[4] = (uint8_t)(w >> 32);
+ p[5] = (uint8_t)(w >> 40);
+}
+
+static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c)
+{
+ return (w >> c) | (w << (32 - c));
+}
+
+static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c)
+{
+ return (w >> c) | (w << (64 - c));
+}
+
+#define BLAKE2B_BLOCKBYTES 128
+#define BLAKE2B_OUTBYTES 64
+#define BLAKE2B_KEYBYTES 64
+#define BLAKE2B_SALTBYTES 16
+#define BLAKE2B_PERSONALBYTES 16
+
+static const uint64_t blake2b_IV[8] =
+{
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+static const uint8_t blake2b_sigma[12][16] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
+};
+
+typedef struct
+{
+ uint64_t h[8];
+ uint64_t t[2];
+ uint64_t f[2];
+ uint8_t buf[BLAKE2B_BLOCKBYTES];
+ size_t buflen;
+ size_t outlen;
+ uint8_t last_node;
+} blake2b_state;
+
+BLAKE2_PACKED(struct blake2b_param__
+{
+ uint8_t digest_length; /* 1 */
+ uint8_t key_length; /* 2 */
+ uint8_t fanout; /* 3 */
+ uint8_t depth; /* 4 */
+ uint32_t leaf_length; /* 8 */
+ uint32_t node_offset; /* 12 */
+ uint32_t xof_length; /* 16 */
+ uint8_t node_depth; /* 17 */
+ uint8_t inner_length; /* 18 */
+ uint8_t reserved[14]; /* 32 */
+ uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
+ uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
+});
+
+typedef struct blake2b_param__ blake2b_param;
+
+#define G(r,i,a,b,c,d) \
+ do { \
+ a = a + b + m[blake2b_sigma[r][2*i+0]]; \
+ d = rotr64(d ^ a, 32); \
+ c = c + d; \
+ b = rotr64(b ^ c, 24); \
+ a = a + b + m[blake2b_sigma[r][2*i+1]]; \
+ d = rotr64(d ^ a, 16); \
+ c = c + d; \
+ b = rotr64(b ^ c, 63); \
+ } while(0)
+
+#define ROUND(r) \
+ do { \
+ G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
+ G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
+ G(r,2,v[ 2],v[ 6],v[10],v[14]); \
+ G(r,3,v[ 3],v[ 7],v[11],v[15]); \
+ G(r,4,v[ 0],v[ 5],v[10],v[15]); \
+ G(r,5,v[ 1],v[ 6],v[11],v[12]); \
+ G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
+ G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
+ } while(0)
+
+static void blake2b_compress(blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES])
+{
+ uint64_t m[16];
+ uint64_t v[16];
+ size_t i;
+
+ for (i = 0; i < 16; ++i) {
+ m[i] = load64(block + i * sizeof(m[i]));
+ }
+
+ for (i = 0; i < 8; ++i) {
+ v[i] = S->h[i];
+ }
+
+ v[8] = blake2b_IV[0];
+ v[9] = blake2b_IV[1];
+ v[10] = blake2b_IV[2];
+ v[11] = blake2b_IV[3];
+ v[12] = blake2b_IV[4] ^ S->t[0];
+ v[13] = blake2b_IV[5] ^ S->t[1];
+ v[14] = blake2b_IV[6] ^ S->f[0];
+ v[15] = blake2b_IV[7] ^ S->f[1];
+
+ ROUND(0);
+ ROUND(1);
+ ROUND(2);
+ ROUND(3);
+ ROUND(4);
+ ROUND(5);
+ ROUND(6);
+ ROUND(7);
+ ROUND(8);
+ ROUND(9);
+ ROUND(10);
+ ROUND(11);
+
+ for (i = 0; i < 8; ++i) {
+ S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+ }
+}
+
+BLAKE2Engine::BLAKE2Engine(ALGORITHM algorithm)
+ : _algorithm(algorithm)
+ , _context(NULL)
+{
+ _digest.reserve(digestLength());
+ reset();
+}
+
+BLAKE2Engine::~BLAKE2Engine()
+{
+ reset();
+ free(_context);
+}
+
+void BLAKE2Engine::updateImpl(const void* buffer_, std::size_t count)
+{
+ if (_context == NULL || buffer_ == NULL || count == 0) return;
+ const unsigned char * in = (const unsigned char *)buffer_;
+ blake2b_state* S = (blake2b_state*)_context;
+ size_t left = S->buflen;
+ size_t fill = BLAKE2B_BLOCKBYTES - left;
+ if (count > fill)
+ {
+ S->buflen = 0;
+ memcpy(S->buf + left, in, fill); /* Fill buffer */
+ S->t[0] += BLAKE2B_BLOCKBYTES;
+ S->t[1] += (S->t[0] < BLAKE2B_BLOCKBYTES);
+ blake2b_compress(S, S->buf); /* Compress */
+ in += fill; count -= fill;
+ while (count > BLAKE2B_BLOCKBYTES)
+ {
+ S->t[0] += BLAKE2B_BLOCKBYTES;
+ S->t[1] += (S->t[0] < BLAKE2B_BLOCKBYTES);
+ blake2b_compress(S, in);
+ in += BLAKE2B_BLOCKBYTES;
+ count -= BLAKE2B_BLOCKBYTES;
+ }
+ }
+ memcpy(S->buf + S->buflen, in, count);
+ S->buflen += count;
+}
+
+std::size_t BLAKE2Engine::digestLength() const
+{
+ return (size_t)((int)_algorithm / 8);
+}
+
+void BLAKE2Engine::reset()
+{
+ if (_context != NULL) free(_context);
+ _context = calloc(1, sizeof(blake2b_state));
+ blake2b_param P[1];
+ uint8_t outlen = (uint8_t)(_algorithm / 8);
+ if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return;
+ P->digest_length = outlen;
+ P->key_length = 0;
+ P->fanout = 1;
+ P->depth = 1;
+ store32(&P->leaf_length, 0);
+ store32(&P->node_offset, 0);
+ store32(&P->xof_length, 0);
+ P->node_depth = 0;
+ P->inner_length = 0;
+ memset(P->reserved, 0, sizeof(P->reserved));
+ memset(P->salt, 0, sizeof(P->salt));
+ memset(P->personal, 0, sizeof(P->personal));
+ blake2b_state* S = (blake2b_state*)_context;
+ for (size_t i = 0; i < 8; ++i) S->h[i] = blake2b_IV[i];
+ const uint8_t *p = (const uint8_t *)(P);
+ for (size_t i = 0; i < 8; ++i) S->h[i] ^= load64(p + sizeof(S->h[i]) * i);
+ S->outlen = P->digest_length;
+ _digest.resize(S->outlen);
+}
+
+const DigestEngine::Digest& BLAKE2Engine::digest()
+{
+ _digest.clear();
+ if (_context == NULL) return _digest;
+ blake2b_state* S = (blake2b_state*)_context;
+ uint8_t buffer[BLAKE2B_OUTBYTES] = { 0 };
+ if (S->f[0] != 0) return _digest;
+ S->t[0] += S->buflen;
+ S->t[1] += (S->t[0] < S->buflen);
+ if (S->last_node) S->f[1] = (uint64_t)-1;
+ S->f[0] = (uint64_t)-1;
+ memset(S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen);
+ blake2b_compress(S, S->buf);
+ for (size_t i = 0; i < 8; ++i) store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
+ _digest.insert(_digest.begin(), buffer, buffer + digestLength());
+ memset(buffer, 0, BLAKE2B_OUTBYTES);
+ reset();
+ return _digest;
+}
+
+} // namespace Poco
diff --git a/Foundation/src/SHA3Engine.cpp b/Foundation/src/SHA3Engine.cpp
new file mode 100644
index 000000000..730d2bd36
--- /dev/null
+++ b/Foundation/src/SHA3Engine.cpp
@@ -0,0 +1,650 @@
+//
+// SHA3Engine.cpp
+//
+// Library: Foundation
+// Package: Crypt
+// Module: SHA3Engine
+//
+// Code of class SHA3Engine.
+//
+/// This class implements the SHA-3 message digest algorithm.
+/// (FIPS 202, see http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf)
+//
+// Based on the Keccak Code Package (public domain)
+// https://github.com/gvanas/KeccakCodePackage
+//
+// Copyright (c) 2017, Applied Informatics Software Engineering GmbH
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+#include "Poco/SHA3Engine.h"
+#include
+#include
+
+namespace Poco {
+
+#ifdef _MSC_VER
+#pragma intrinsic(memcpy)
+#endif
+
+ #if defined(__GNUC__)
+#define ALIGN(x) __attribute__ ((aligned(x)))
+#elif defined(_MSC_VER)
+#define ALIGN(x) __declspec(align(x))
+#elif defined(__ARMCC_VERSION)
+#define ALIGN(x) __align(x)
+#else
+#define ALIGN(x)
+#endif
+
+#ifdef POCO_PTR_IS_64_BIT
+static const UInt64 KeccakRoundConstants[24] =
+{
+ 0x0000000000000001,
+ 0x0000000000008082,
+ 0x800000000000808a,
+ 0x8000000080008000,
+ 0x000000000000808b,
+ 0x0000000080000001,
+ 0x8000000080008081,
+ 0x8000000000008009,
+ 0x000000000000008a,
+ 0x0000000000000088,
+ 0x0000000080008009,
+ 0x000000008000000a,
+ 0x000000008000808b,
+ 0x800000000000008b,
+ 0x8000000000008089,
+ 0x8000000000008003,
+ 0x8000000000008002,
+ 0x8000000000000080,
+ 0x000000000000800a,
+ 0x800000008000000a,
+ 0x8000000080008081,
+ 0x8000000000008080,
+ 0x0000000080000001,
+ 0x8000000080008008,
+};
+static const unsigned int KeccakRhoOffsets[25] =
+{
+ 0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14
+};
+#define KeccakP1600_stateAlignment 8
+#else
+static const UInt32 KeccakRoundConstants[24][2] =
+{
+ 0x00000001, 0x00000000,
+ 0x00000000, 0x00000089,
+ 0x00000000, 0x8000008B,
+ 0x00000000, 0x80008080,
+ 0x00000001, 0x0000008B,
+ 0x00000001, 0x00008000,
+ 0x00000001, 0x80008088,
+ 0x00000001, 0x80000082,
+ 0x00000000, 0x0000000B,
+ 0x00000000, 0x0000000A,
+ 0x00000001, 0x00008082,
+ 0x00000000, 0x00008003,
+ 0x00000001, 0x0000808B,
+ 0x00000001, 0x8000000B,
+ 0x00000001, 0x8000008A,
+ 0x00000001, 0x80000081,
+ 0x00000000, 0x80000081,
+ 0x00000000, 0x80000008,
+ 0x00000000, 0x00000083,
+ 0x00000000, 0x80008003,
+ 0x00000001, 0x80008088,
+ 0x00000000, 0x80000088,
+ 0x00000001, 0x00008000,
+ 0x00000000, 0x80008082
+};
+
+static const unsigned int KeccakRhoOffsets[25] =
+{
+ 0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14
+};
+#define KeccakP1600_stateAlignment 4
+#endif
+
+ALIGN(KeccakP1600_stateAlignment) typedef struct KeccakWidth1600_SpongeInstanceStruct
+{
+ unsigned char state[200];
+ unsigned int rate;
+ unsigned int byteIOIndex;
+ int squeezing;
+} KeccakWidth1600_SpongeInstance;
+
+typedef struct
+{
+ KeccakWidth1600_SpongeInstance sponge;
+ unsigned int fixedOutputLength;
+ unsigned char delimitedSuffix;
+} HASHCONTEXT;
+
+SHA3Engine::SHA3Engine(ALGORITHM algorithm)
+ : _algorithm(algorithm)
+ , _context(NULL)
+{
+ _digest.reserve(digestLength());
+ reset();
+}
+
+SHA3Engine::~SHA3Engine()
+{
+ reset();
+ free(_context);
+}
+
+#ifdef POCO_PTR_IS_64_BIT
+void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
+{
+ assert(offset < 200);
+ assert(offset + length <= 200);
+ for (unsigned int i = 0; i> (64-offset))) : a)
+#define index(x, y) (((x)%5)+5*((y)%5))
+
+static void theta(UInt64 *A)
+{
+ unsigned int x, y;
+ UInt64 C[5], D[5];
+
+ for (x = 0; x<5; x++) {
+ C[x] = 0;
+ for (y = 0; y<5; y++)
+ C[x] ^= A[index(x, y)];
+ }
+ for (x = 0; x<5; x++)
+ D[x] = ROL64(C[(x + 1) % 5], 1) ^ C[(x + 4) % 5];
+ for (x = 0; x<5; x++)
+ for (y = 0; y<5; y++)
+ A[index(x, y)] ^= D[x];
+}
+
+static void rho(UInt64 *A)
+{
+ unsigned int x, y;
+
+ for (x = 0; x<5; x++) for (y = 0; y<5; y++)
+ A[index(x, y)] = ROL64(A[index(x, y)], KeccakRhoOffsets[index(x, y)]);
+}
+
+static void pi(UInt64 *A)
+{
+ unsigned int x, y;
+ UInt64 tempA[25];
+
+ for (x = 0; x<5; x++) for (y = 0; y<5; y++)
+ tempA[index(x, y)] = A[index(x, y)];
+ for (x = 0; x<5; x++) for (y = 0; y<5; y++)
+ A[index(0 * x + 1 * y, 2 * x + 3 * y)] = tempA[index(x, y)];
+}
+
+static void chi(UInt64 *A)
+{
+ unsigned int x, y;
+ UInt64 C[5];
+
+ for (y = 0; y<5; y++) {
+ for (x = 0; x<5; x++)
+ C[x] = A[index(x, y)] ^ ((~A[index(x + 1, y)]) & A[index(x + 2, y)]);
+ for (x = 0; x<5; x++)
+ A[index(x, y)] = C[x];
+ }
+}
+
+static void iota(UInt64 *A, unsigned int indexRound)
+{
+ A[index(0, 0)] ^= KeccakRoundConstants[indexRound];
+}
+
+void KeccakP1600Round(UInt64 *state, unsigned int indexRound)
+{
+ theta(state);
+ rho(state);
+ pi(state);
+ chi(state);
+ iota(state, indexRound);
+}
+
+void KeccakP1600OnWords(UInt64 *state, unsigned int nrRounds)
+{
+ for (unsigned int i = (24 - nrRounds); i < 24; i++) KeccakP1600Round(state, i);
+}
+
+void KeccakP1600_Permute_24rounds(void *state)
+{
+#ifndef POCO_ARCH_LITTLE_ENDIAN
+ UInt64 stateAsWords[1600 / 64];
+#endif
+#ifdef POCO_ARCH_LITTLE_ENDIAN
+ KeccakP1600OnWords((UInt64*)state, 24);
+#else
+ fromBytesToWords(stateAsWords, (const unsigned char *)state);
+ KeccakP1600OnWords(stateAsWords, 24);
+ fromWordsToBytes((unsigned char *)state, stateAsWords);
+#endif
+}
+
+void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length)
+{
+ assert(offset < 200);
+ assert(offset + length <= 200);
+ memcpy(data, (unsigned char*)state + offset, length);
+}
+#else
+void toBitInterleaving(UInt32 low, UInt32 high, UInt32 *even, UInt32 *odd)
+{
+ unsigned int i;
+
+ *even = 0;
+ *odd = 0;
+ for (i = 0; i<64; i++) {
+ unsigned int inBit;
+ if (i < 32)
+ inBit = (low >> i) & 1;
+ else
+ inBit = (high >> (i - 32)) & 1;
+ if ((i % 2) == 0)
+ *even |= inBit << (i / 2);
+ else
+ *odd |= inBit << ((i - 1) / 2);
+ }
+}
+
+void fromBitInterleaving(UInt32 even, UInt32 odd, UInt32 *low, UInt32 *high)
+{
+ unsigned int i;
+
+ *low = 0;
+ *high = 0;
+ for (i = 0; i<64; i++) {
+ unsigned int inBit;
+ if ((i % 2) == 0)
+ inBit = (even >> (i / 2)) & 1;
+ else
+ inBit = (odd >> ((i - 1) / 2)) & 1;
+ if (i < 32)
+ *low |= inBit << i;
+ else
+ *high |= inBit << (i - 32);
+ }
+}
+
+void KeccakP1600_AddBytesInLane(void *state, unsigned int lanePosition, const unsigned char *data, unsigned int offset, unsigned int length)
+{
+ if ((lanePosition < 25) && (offset < 8) && (offset + length <= 8)) {
+ UInt8 laneAsBytes[8];
+ UInt32 low, high;
+ UInt32 lane[2];
+ UInt32 *stateAsHalfLanes;
+
+ memset(laneAsBytes, 0, 8);
+ memcpy(laneAsBytes + offset, data, length);
+ low = laneAsBytes[0]
+ | ((UInt32)(laneAsBytes[1]) << 8)
+ | ((UInt32)(laneAsBytes[2]) << 16)
+ | ((UInt32)(laneAsBytes[3]) << 24);
+ high = laneAsBytes[4]
+ | ((UInt32)(laneAsBytes[5]) << 8)
+ | ((UInt32)(laneAsBytes[6]) << 16)
+ | ((UInt32)(laneAsBytes[7]) << 24);
+ toBitInterleaving(low, high, lane, lane + 1);
+ stateAsHalfLanes = (UInt32*)state;
+ stateAsHalfLanes[lanePosition * 2 + 0] ^= lane[0];
+ stateAsHalfLanes[lanePosition * 2 + 1] ^= lane[1];
+ }
+}
+
+void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
+{
+ unsigned int lanePosition = offset / 8;
+ unsigned int offsetInLane = offset % 8;
+
+ assert(offset < 200);
+ assert(offset + length <= 200);
+ while (length > 0) {
+ unsigned int bytesInLane = 8 - offsetInLane;
+ if (bytesInLane > length)
+ bytesInLane = length;
+ KeccakP1600_AddBytesInLane(state, lanePosition, data, offsetInLane, bytesInLane);
+ length -= bytesInLane;
+ lanePosition++;
+ offsetInLane = 0;
+ data += bytesInLane;
+ }
+}
+
+void KeccakP1600_AddByte(void *state, unsigned char byte, unsigned int offset)
+{
+ unsigned char data[1];
+ assert(offset < 200);
+ data[0] = byte;
+ KeccakP1600_AddBytes(state, data, offset, 1);
+}
+
+#define ROL32(a, offset) ((offset != 0) ? ((((UInt32)a) << offset) ^ (((UInt32)a) >> (32-offset))) : a)
+#define index(x, y,z) ((((x)%5)+5*((y)%5))*2 + z)
+void ROL64(UInt32 inEven, UInt32 inOdd, UInt32 *outEven, UInt32 *outOdd, unsigned int offset)
+{
+ if ((offset % 2) == 0) {
+ *outEven = ROL32(inEven, offset / 2);
+ *outOdd = ROL32(inOdd, offset / 2);
+ }
+ else {
+ *outEven = ROL32(inOdd, (offset + 1) / 2);
+ *outOdd = ROL32(inEven, (offset - 1) / 2);
+ }
+}
+
+static void theta(UInt32 *A)
+{
+ unsigned int x, y, z;
+ UInt32 C[5][2], D[5][2];
+ for (x = 0; x<5; x++) {
+ for (z = 0; z<2; z++) {
+ C[x][z] = 0;
+ for (y = 0; y<5; y++)
+ C[x][z] ^= A[index(x, y, z)];
+ }
+ }
+ for (x = 0; x<5; x++) {
+ ROL64(C[(x + 1) % 5][0], C[(x + 1) % 5][1], &(D[x][0]), &(D[x][1]), 1);
+ for (z = 0; z<2; z++)
+ D[x][z] ^= C[(x + 4) % 5][z];
+ }
+ for (x = 0; x<5; x++)
+ for (y = 0; y<5; y++)
+ for (z = 0; z<2; z++)
+ A[index(x, y, z)] ^= D[x][z];
+}
+
+static void rho(UInt32 *A)
+{
+ unsigned int x, y;
+ for (x = 0; x<5; x++) for (y = 0; y<5; y++)
+ ROL64(A[index(x, y, 0)], A[index(x, y, 1)], &(A[index(x, y, 0)]), &(A[index(x, y, 1)]), KeccakRhoOffsets[5 * y + x]);
+}
+
+static void pi(UInt32 *A)
+{
+ unsigned int x, y, z;
+ UInt32 tempA[50];
+ for (x = 0; x<5; x++) for (y = 0; y<5; y++) for (z = 0; z<2; z++)
+ tempA[index(x, y, z)] = A[index(x, y, z)];
+ for (x = 0; x<5; x++) for (y = 0; y<5; y++) for (z = 0; z<2; z++)
+ A[index(0 * x + 1 * y, 2 * x + 3 * y, z)] = tempA[index(x, y, z)];
+}
+
+static void chi(UInt32 *A)
+{
+ unsigned int x, y, z;
+ UInt32 C[5][2];
+ for (y = 0; y<5; y++) {
+ for (x = 0; x<5; x++)
+ for (z = 0; z<2; z++)
+ C[x][z] = A[index(x, y, z)] ^ ((~A[index(x + 1, y, z)]) & A[index(x + 2, y, z)]);
+ for (x = 0; x<5; x++)
+ for (z = 0; z<2; z++)
+ A[index(x, y, z)] = C[x][z];
+ }
+}
+
+static void iota(UInt32 *A, unsigned int indexRound)
+{
+ A[index(0, 0, 0)] ^= KeccakRoundConstants[indexRound][0];
+ A[index(0, 0, 1)] ^= KeccakRoundConstants[indexRound][1];
+}
+
+void KeccakP1600_PermutationOnWords(UInt32 *state, unsigned int nrRounds)
+{
+ for (unsigned int i = (24 - nrRounds); i < 24; i++)
+ {
+ theta(state);
+ rho(state);
+ pi(state);
+ chi(state);
+ iota(state, i);
+ }
+}
+
+void KeccakP1600_ExtractBytesInLane(const void *state, unsigned int lanePosition, unsigned char *data, unsigned int offset, unsigned int length)
+{
+ if ((lanePosition < 25) && (offset < 8) && (offset + length <= 8)) {
+ UInt32 *stateAsHalfLanes = (UInt32*)state;
+ UInt32 lane[2];
+ UInt8 laneAsBytes[8];
+ fromBitInterleaving(stateAsHalfLanes[lanePosition * 2], stateAsHalfLanes[lanePosition * 2 + 1], lane, lane + 1);
+ laneAsBytes[0] = lane[0] & 0xFF;
+ laneAsBytes[1] = (lane[0] >> 8) & 0xFF;
+ laneAsBytes[2] = (lane[0] >> 16) & 0xFF;
+ laneAsBytes[3] = (lane[0] >> 24) & 0xFF;
+ laneAsBytes[4] = lane[1] & 0xFF;
+ laneAsBytes[5] = (lane[1] >> 8) & 0xFF;
+ laneAsBytes[6] = (lane[1] >> 16) & 0xFF;
+ laneAsBytes[7] = (lane[1] >> 24) & 0xFF;
+ memcpy(data, laneAsBytes + offset, length);
+ }
+}
+
+void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length)
+{
+ unsigned int lanePosition = offset / 8;
+ unsigned int offsetInLane = offset % 8;
+
+ assert(offset < 200);
+ assert(offset + length <= 200);
+ while (length > 0) {
+ unsigned int bytesInLane = 8 - offsetInLane;
+ if (bytesInLane > length)
+ bytesInLane = length;
+ KeccakP1600_ExtractBytesInLane(state, lanePosition, data, offsetInLane, bytesInLane);
+ length -= bytesInLane;
+ lanePosition++;
+ offsetInLane = 0;
+ data += bytesInLane;
+ }
+}
+
+void KeccakP1600_Permute_24rounds(void *state)
+{
+ UInt32 *stateAsHalfLanes = (UInt32*)state;
+ {
+ UInt8 stateAsBytes[1600 / 8];
+ KeccakP1600_ExtractBytes(state, stateAsBytes, 0, 1600 / 8);
+ }
+ KeccakP1600_PermutationOnWords(stateAsHalfLanes, 24);
+ {
+ UInt8 stateAsBytes[1600 / 8];
+ KeccakP1600_ExtractBytes(state, stateAsBytes, 0, 1600 / 8);
+ }
+}
+#endif
+
+void SHA3Engine::updateImpl(const void* buffer_, std::size_t count)
+{
+ if (_context == NULL || buffer_ == NULL || count == 0) return;
+ HASHCONTEXT* pContext = (HASHCONTEXT*)_context;
+ size_t j;
+ unsigned int partialBlock;
+ unsigned int rateInBytes = (&pContext->sponge)->rate / 8;
+ if ((&pContext->sponge)->squeezing) return;
+ size_t i = 0;
+ const unsigned char *curData = (const unsigned char *)buffer_;
+ while (i < count) {
+ if (((&pContext->sponge)->byteIOIndex == 0) && (count >= (i + rateInBytes))) {
+ for (j = count - i; j >= rateInBytes; j -= rateInBytes) {
+ KeccakP1600_AddBytes((&pContext->sponge)->state, curData, 0, rateInBytes);
+ KeccakP1600_Permute_24rounds((&pContext->sponge)->state);
+ curData += rateInBytes;
+ }
+ i = count - j;
+ }
+ else {
+ partialBlock = (unsigned int)(count - i);
+ if (partialBlock + (&pContext->sponge)->byteIOIndex > rateInBytes)
+ partialBlock = rateInBytes - (&pContext->sponge)->byteIOIndex;
+ i += partialBlock;
+
+ KeccakP1600_AddBytes((&pContext->sponge)->state, curData, (&pContext->sponge)->byteIOIndex, partialBlock);
+ curData += partialBlock;
+ (&pContext->sponge)->byteIOIndex += partialBlock;
+ if ((&pContext->sponge)->byteIOIndex == rateInBytes) {
+ KeccakP1600_Permute_24rounds((&pContext->sponge)->state);
+ (&pContext->sponge)->byteIOIndex = 0;
+ }
+ }
+ }
+}
+
+std::size_t SHA3Engine::digestLength() const
+{
+ return (size_t)((int)_algorithm / 8);
+}
+
+int KeccakWidth1600_SpongeInitialize(KeccakWidth1600_SpongeInstance *instance, unsigned int rate, unsigned int capacity)
+{
+ if (rate + capacity != 1600) return 1;
+ if ((rate <= 0) || (rate > 1600) || ((rate % 8) != 0)) return 1;
+ memset(instance->state, 0, 1600 / 8);
+ instance->rate = rate;
+ instance->byteIOIndex = 0;
+ instance->squeezing = 0;
+ return 0;
+}
+
+void SHA3Engine::reset()
+{
+ if (_context != NULL) free(_context);
+ _context = calloc(1, sizeof(HASHCONTEXT));
+ HASHCONTEXT* pContext = (HASHCONTEXT*)_context;
+ switch (_algorithm)
+ {
+ case SHA3_224:
+ KeccakWidth1600_SpongeInitialize(&pContext->sponge, 1152, 448);
+ pContext->fixedOutputLength = 224;
+ pContext->delimitedSuffix = 0x06;
+ break;
+ case SHA3_256:
+ KeccakWidth1600_SpongeInitialize(&pContext->sponge, 1088, 512);
+ pContext->fixedOutputLength = 256;
+ pContext->delimitedSuffix = 0x06;
+ break;
+ case SHA3_384:
+ KeccakWidth1600_SpongeInitialize(&pContext->sponge, 832, 768);
+ pContext->fixedOutputLength = 384;
+ pContext->delimitedSuffix = 0x06;
+ break;
+ default:
+ case SHA3_512:
+ KeccakWidth1600_SpongeInitialize(&pContext->sponge, 576, 1024);
+ pContext->fixedOutputLength = 512;
+ pContext->delimitedSuffix = 0x06;
+ break;
+ }
+}
+
+int KeccakWidth1600_SpongeAbsorbLastFewBits(KeccakWidth1600_SpongeInstance *instance, unsigned char delimitedData)
+{
+ unsigned int rateInBytes = instance->rate / 8;
+
+ if (delimitedData == 0)
+ return 1;
+ if (instance->squeezing)
+ return 1; /* Too late for additional input */
+
+ /* Last few bits, whose delimiter coincides with first bit of padding */
+ KeccakP1600_AddByte(instance->state, delimitedData, instance->byteIOIndex);
+ /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
+ if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes - 1)))
+ KeccakP1600_Permute_24rounds(instance->state);
+ /* Second bit of padding */
+ KeccakP1600_AddByte(instance->state, 0x80, rateInBytes - 1);
+ KeccakP1600_Permute_24rounds(instance->state);
+ instance->byteIOIndex = 0;
+ instance->squeezing = 1;
+ return 0;
+}
+
+int SpongeAbsorbLastFewBits(KeccakWidth1600_SpongeInstance *instance, unsigned char delimitedData)
+{
+ unsigned int rateInBytes = instance->rate / 8;
+ if (delimitedData == 0) return 1;
+ if (instance->squeezing) return 1; /* Too late for additional input */
+ /* Last few bits, whose delimiter coincides with first bit of padding */
+ KeccakP1600_AddByte(instance->state, delimitedData, instance->byteIOIndex);
+ /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
+ if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes - 1)))
+ KeccakP1600_Permute_24rounds(instance->state);
+ /* Second bit of padding */
+ KeccakP1600_AddByte(instance->state, 0x80, rateInBytes - 1);
+ KeccakP1600_Permute_24rounds(instance->state);
+ instance->byteIOIndex = 0;
+ instance->squeezing = 1;
+ return 0;
+}
+
+int KeccakWidth1600_SpongeSqueeze(KeccakWidth1600_SpongeInstance *instance, unsigned char *data, size_t dataByteLen)
+{
+ size_t i, j;
+ unsigned int partialBlock;
+ unsigned int rateInBytes = instance->rate / 8;
+ unsigned char *curData;
+
+ if (!instance->squeezing)
+ SpongeAbsorbLastFewBits(instance, 0x01);
+
+ i = 0;
+ curData = data;
+ while (i < dataByteLen) {
+ if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) {
+ for (j = dataByteLen - i; j >= rateInBytes; j -= rateInBytes) {
+ KeccakP1600_Permute_24rounds(instance->state);
+ KeccakP1600_ExtractBytes(instance->state, curData, 0, rateInBytes);
+ curData += rateInBytes;
+ }
+ i = dataByteLen - j;
+ }
+ else {
+ /* normal lane: using the message queue */
+ if (instance->byteIOIndex == rateInBytes) {
+ KeccakP1600_Permute_24rounds(instance->state);
+ instance->byteIOIndex = 0;
+ }
+ partialBlock = (unsigned int)(dataByteLen - i);
+ if (partialBlock + instance->byteIOIndex > rateInBytes)
+ partialBlock = rateInBytes - instance->byteIOIndex;
+ i += partialBlock;
+
+ KeccakP1600_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
+ curData += partialBlock;
+ instance->byteIOIndex += partialBlock;
+ }
+ }
+ return 0;
+}
+
+const DigestEngine::Digest& SHA3Engine::digest()
+{
+ _digest.clear();
+ HASHCONTEXT* pContext = (HASHCONTEXT*)_context;
+ unsigned char hash[64];
+ memset(hash, 0, 64);
+ if (KeccakWidth1600_SpongeAbsorbLastFewBits(&pContext->sponge, pContext->delimitedSuffix) == 0)
+ KeccakWidth1600_SpongeSqueeze(&pContext->sponge, hash, pContext->fixedOutputLength / 8);
+ _digest.insert(_digest.begin(), hash, hash + digestLength());
+ reset();
+ return _digest;
+}
+
+} // namespace Poco
diff --git a/Foundation/testsuite/Makefile-Driver b/Foundation/testsuite/Makefile-Driver
index e107075ae..108b04e62 100644
--- a/Foundation/testsuite/Makefile-Driver
+++ b/Foundation/testsuite/Makefile-Driver
@@ -23,7 +23,7 @@ objects = ActiveMethodTest ActivityTest ActiveDispatcherTest \
PriorityNotificationQueueTest TimedNotificationQueueTest \
NotificationsTestSuite NullStreamTest NumberFormatterTest \
NumberParserTest PathTest PatternFormatterTest PBKDF2EngineTest RWLockTest \
- RandomStreamTest RandomTest RegularExpressionTest SHA1EngineTest SHA2EngineTest \
+ RandomStreamTest RandomTest RegularExpressionTest SHA1EngineTest SHA2EngineTest SHA3EngineTest BLAKE2EngineTest \
SemaphoreTest MutexTest ConditionTest SharedLibraryTest SharedLibraryTestSuite \
SimpleFileChannelTest StopwatchTest \
StreamConverterTest StreamCopierTest StreamTokenizerTest \
diff --git a/Foundation/testsuite/TestSuite.vxbuild b/Foundation/testsuite/TestSuite.vxbuild
index 19748f4be..c61967fc7 100644
--- a/Foundation/testsuite/TestSuite.vxbuild
+++ b/Foundation/testsuite/TestSuite.vxbuild
@@ -84,6 +84,8 @@ SOURCES="
RegularExpressionTest.cpp
SHA1EngineTest.cpp
SHA2EngineTest.cpp
+ SHA3EngineTest.cpp
+ BLAKE2EngineTest.cpp
SemaphoreTest.cpp
SharedLibraryTest.cpp
SharedLibraryTestSuite.cpp
diff --git a/Foundation/testsuite/TestSuite_CE_vs90.vcproj b/Foundation/testsuite/TestSuite_CE_vs90.vcproj
index 4fa2f97a2..7da533ca7 100644
--- a/Foundation/testsuite/TestSuite_CE_vs90.vcproj
+++ b/Foundation/testsuite/TestSuite_CE_vs90.vcproj
@@ -670,6 +670,10 @@
RelativePath=".\src\SHA1EngineTest.cpp"/>
+
+
@@ -693,6 +697,10 @@
RelativePath=".\src\SHA1EngineTest.h"/>
+
+
+
+
@@ -218,6 +220,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_WEC2013_vs110.vcxproj.filters b/Foundation/testsuite/TestSuite_WEC2013_vs110.vcxproj.filters
index 35900a77e..92a856548 100644
--- a/Foundation/testsuite/TestSuite_WEC2013_vs110.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_WEC2013_vs110.vcxproj.filters
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
diff --git a/Foundation/testsuite/TestSuite_WEC2013_vs120.vcxproj b/Foundation/testsuite/TestSuite_WEC2013_vs120.vcxproj
index 70dc34e13..1dd9a3b2c 100644
--- a/Foundation/testsuite/TestSuite_WEC2013_vs120.vcxproj
+++ b/Foundation/testsuite/TestSuite_WEC2013_vs120.vcxproj
@@ -52,6 +52,8 @@
+
+
@@ -218,6 +220,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_WEC2013_vs120.vcxproj.filters b/Foundation/testsuite/TestSuite_WEC2013_vs120.vcxproj.filters
index 28ff7e8bd..98c7add8a 100644
--- a/Foundation/testsuite/TestSuite_WEC2013_vs120.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_WEC2013_vs120.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
@@ -1023,4 +1035,4 @@
Dynamic\Header Files
-
\ No newline at end of file
+
diff --git a/Foundation/testsuite/TestSuite_vs100.vcxproj b/Foundation/testsuite/TestSuite_vs100.vcxproj
index 06b10a5aa..40c989e63 100644
--- a/Foundation/testsuite/TestSuite_vs100.vcxproj
+++ b/Foundation/testsuite/TestSuite_vs100.vcxproj
@@ -363,6 +363,8 @@
+
+
@@ -506,6 +508,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_vs100.vcxproj.filters b/Foundation/testsuite/TestSuite_vs100.vcxproj.filters
index 90ca70ecd..35a032172 100644
--- a/Foundation/testsuite/TestSuite_vs100.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_vs100.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
@@ -1023,4 +1035,4 @@
Dynamic\Header Files
-
\ No newline at end of file
+
diff --git a/Foundation/testsuite/TestSuite_vs110.vcxproj b/Foundation/testsuite/TestSuite_vs110.vcxproj
index 684571876..83b758e88 100644
--- a/Foundation/testsuite/TestSuite_vs110.vcxproj
+++ b/Foundation/testsuite/TestSuite_vs110.vcxproj
@@ -363,6 +363,8 @@
+
+
@@ -506,6 +508,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_vs110.vcxproj.filters b/Foundation/testsuite/TestSuite_vs110.vcxproj.filters
index b9dd868da..a77223606 100644
--- a/Foundation/testsuite/TestSuite_vs110.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_vs110.vcxproj.filters
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
diff --git a/Foundation/testsuite/TestSuite_vs120.vcxproj b/Foundation/testsuite/TestSuite_vs120.vcxproj
index fc6fd3669..23d92d079 100644
--- a/Foundation/testsuite/TestSuite_vs120.vcxproj
+++ b/Foundation/testsuite/TestSuite_vs120.vcxproj
@@ -358,6 +358,8 @@
+
+
@@ -501,6 +503,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_vs120.vcxproj.filters b/Foundation/testsuite/TestSuite_vs120.vcxproj.filters
index b9ee68cfd..5cff6adfd 100644
--- a/Foundation/testsuite/TestSuite_vs120.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_vs120.vcxproj.filters
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
diff --git a/Foundation/testsuite/TestSuite_vs140.vcxproj b/Foundation/testsuite/TestSuite_vs140.vcxproj
index 87384b95b..8d1617977 100644
--- a/Foundation/testsuite/TestSuite_vs140.vcxproj
+++ b/Foundation/testsuite/TestSuite_vs140.vcxproj
@@ -397,6 +397,8 @@
+
+
@@ -539,6 +541,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_vs140.vcxproj.filters b/Foundation/testsuite/TestSuite_vs140.vcxproj.filters
index 339ad14cf..511835784 100644
--- a/Foundation/testsuite/TestSuite_vs140.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_vs140.vcxproj.filters
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
diff --git a/Foundation/testsuite/TestSuite_vs150.vcxproj b/Foundation/testsuite/TestSuite_vs150.vcxproj
index 1ec61f0ce..b0da82663 100644
--- a/Foundation/testsuite/TestSuite_vs150.vcxproj
+++ b/Foundation/testsuite/TestSuite_vs150.vcxproj
@@ -397,6 +397,8 @@
+
+
@@ -539,6 +541,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_vs150.vcxproj.filters b/Foundation/testsuite/TestSuite_vs150.vcxproj.filters
index 339ad14cf..511835784 100644
--- a/Foundation/testsuite/TestSuite_vs150.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_vs150.vcxproj.filters
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
diff --git a/Foundation/testsuite/TestSuite_vs90.vcproj b/Foundation/testsuite/TestSuite_vs90.vcproj
index 27970d8ad..506d2fa17 100644
--- a/Foundation/testsuite/TestSuite_vs90.vcproj
+++ b/Foundation/testsuite/TestSuite_vs90.vcproj
@@ -651,6 +651,10 @@
RelativePath=".\src\SHA1EngineTest.cpp"/>
+
+
@@ -674,6 +678,10 @@
RelativePath=".\src\SHA1EngineTest.h"/>
+
+
+
+
@@ -506,6 +508,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs100.vcxproj.filters b/Foundation/testsuite/TestSuite_x64_vs100.vcxproj.filters
index 1ca4522e6..6000410e8 100644
--- a/Foundation/testsuite/TestSuite_x64_vs100.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_x64_vs100.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
@@ -1023,4 +1035,4 @@
Dynamic\Header Files
-
\ No newline at end of file
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs110.vcxproj b/Foundation/testsuite/TestSuite_x64_vs110.vcxproj
index 5dd227519..17bf36b0c 100644
--- a/Foundation/testsuite/TestSuite_x64_vs110.vcxproj
+++ b/Foundation/testsuite/TestSuite_x64_vs110.vcxproj
@@ -363,6 +363,8 @@
+
+
@@ -506,6 +508,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs110.vcxproj.filters b/Foundation/testsuite/TestSuite_x64_vs110.vcxproj.filters
index ac180f273..772b4ff8f 100644
--- a/Foundation/testsuite/TestSuite_x64_vs110.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_x64_vs110.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
@@ -1023,4 +1035,4 @@
Dynamic\Header Files
-
\ No newline at end of file
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs120.vcxproj b/Foundation/testsuite/TestSuite_x64_vs120.vcxproj
index b1f284e59..5b9a92343 100644
--- a/Foundation/testsuite/TestSuite_x64_vs120.vcxproj
+++ b/Foundation/testsuite/TestSuite_x64_vs120.vcxproj
@@ -360,6 +360,8 @@
+
+
@@ -503,6 +505,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs120.vcxproj.filters b/Foundation/testsuite/TestSuite_x64_vs120.vcxproj.filters
index 0e7762981..4a06d9449 100644
--- a/Foundation/testsuite/TestSuite_x64_vs120.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_x64_vs120.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
@@ -1023,4 +1035,4 @@
Dynamic\Header Files
-
\ No newline at end of file
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs140.vcxproj b/Foundation/testsuite/TestSuite_x64_vs140.vcxproj
index c9ad8ed62..f1d3e17c7 100644
--- a/Foundation/testsuite/TestSuite_x64_vs140.vcxproj
+++ b/Foundation/testsuite/TestSuite_x64_vs140.vcxproj
@@ -397,6 +397,8 @@
+
+
@@ -539,6 +541,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs140.vcxproj.filters b/Foundation/testsuite/TestSuite_x64_vs140.vcxproj.filters
index d4684c03c..033fd3cef 100644
--- a/Foundation/testsuite/TestSuite_x64_vs140.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_x64_vs140.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
@@ -1023,4 +1035,4 @@
Dynamic\Header Files
-
\ No newline at end of file
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs150.vcxproj b/Foundation/testsuite/TestSuite_x64_vs150.vcxproj
index 8f4026c9d..8f2cc0bfb 100644
--- a/Foundation/testsuite/TestSuite_x64_vs150.vcxproj
+++ b/Foundation/testsuite/TestSuite_x64_vs150.vcxproj
@@ -397,6 +397,8 @@
+
+
@@ -539,6 +541,8 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs150.vcxproj.filters b/Foundation/testsuite/TestSuite_x64_vs150.vcxproj.filters
index d4684c03c..033fd3cef 100644
--- a/Foundation/testsuite/TestSuite_x64_vs150.vcxproj.filters
+++ b/Foundation/testsuite/TestSuite_x64_vs150.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -333,6 +333,12 @@
Crypt\Source Files
+
+ Crypt\Source Files
+
+
+ Crypt\Source Files
+
Notifications\Source Files
@@ -758,6 +764,12 @@
Crypt\Header Files
+
+ Crypt\Header Files
+
+
+ Crypt\Header Files
+
Notifications\Header Files
@@ -1023,4 +1035,4 @@
Dynamic\Header Files
-
\ No newline at end of file
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs90.vcproj b/Foundation/testsuite/TestSuite_x64_vs90.vcproj
index 28495cd79..51ea0df2c 100644
--- a/Foundation/testsuite/TestSuite_x64_vs90.vcproj
+++ b/Foundation/testsuite/TestSuite_x64_vs90.vcproj
@@ -651,6 +651,10 @@
RelativePath=".\src\SHA1EngineTest.cpp"/>
+
+
@@ -674,6 +678,10 @@
RelativePath=".\src\SHA1EngineTest.h"/>
+
+
addTest(MD5EngineTest::suite());
pSuite->addTest(SHA1EngineTest::suite());
pSuite->addTest(SHA2EngineTest::suite());
+ pSuite->addTest(SHA3EngineTest::suite());
+ pSuite->addTest(BLAKE2EngineTest::suite());
pSuite->addTest(HMACEngineTest::suite());
pSuite->addTest(PBKDF2EngineTest::suite());
pSuite->addTest(DigestStreamTest::suite());
diff --git a/Foundation/testsuite/src/SHA3EngineTest.cpp b/Foundation/testsuite/src/SHA3EngineTest.cpp
new file mode 100644
index 000000000..484baef67
--- /dev/null
+++ b/Foundation/testsuite/src/SHA3EngineTest.cpp
@@ -0,0 +1,122 @@
+//
+// SHA3EngineTest.cpp
+//
+// $Id: //poco/1.4/Foundation/testsuite/src/SHA3EngineTest.cpp#1 $
+//
+// Code of the SHA3EngineTest class.
+//
+// test vectors from FIPS 180-1
+//
+// Copyright (c) 2017, Applied Informatics Software Engineering GmbH
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+#include "SHA3EngineTest.h"
+#include "Poco/CppUnit/TestCaller.h"
+#include "Poco/CppUnit/TestSuite.h"
+#include "Poco/SHA3Engine.h"
+
+using Poco::SHA3Engine;
+using Poco::DigestEngine;
+
+SHA3EngineTest::SHA3EngineTest(const std::string& rName): CppUnit::TestCase(rName)
+{
+}
+
+SHA3EngineTest::~SHA3EngineTest()
+{
+}
+
+void SHA3EngineTest::testSHA3_224()
+{
+ SHA3Engine engine(SHA3Engine::SHA3_224);
+
+ engine.update("abc");
+ assert(DigestEngine::digestToHex(engine.digest()) == "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf");
+
+ engine.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
+ assert(DigestEngine::digestToHex(engine.digest()) == "8a24108b154ada21c9fd5574494479ba5c7e7ab76ef264ead0fcce33");
+
+ engine.update("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
+ assert(DigestEngine::digestToHex(engine.digest()) == "543e6868e1666c1a643630df77367ae5a62a85070a51c14cbf665cbc");
+
+ for (int i = 0; i < 1000000; ++i)
+ engine.update('a');
+ assert(DigestEngine::digestToHex(engine.digest()) == "d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c");
+}
+
+void SHA3EngineTest::testSHA3_256()
+{
+ SHA3Engine engine(SHA3Engine::SHA3_256);
+
+ engine.update("abc");
+ assert(DigestEngine::digestToHex(engine.digest()) == "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532");
+
+ engine.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
+ assert(DigestEngine::digestToHex(engine.digest()) == "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376");
+
+ engine.update("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
+ assert(DigestEngine::digestToHex(engine.digest()) == "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18");
+
+ for (int i = 0; i < 1000000; ++i)
+ engine.update('a');
+ assert(DigestEngine::digestToHex(engine.digest()) == "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1");
+}
+
+void SHA3EngineTest::testSHA3_384()
+{
+ SHA3Engine engine(SHA3Engine::SHA3_384);
+
+ engine.update("abc");
+ assert(DigestEngine::digestToHex(engine.digest()) == "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25");
+
+ engine.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
+ assert(DigestEngine::digestToHex(engine.digest()) == "991c665755eb3a4b6bbdfb75c78a492e8c56a22c5c4d7e429bfdbc32b9d4ad5aa04a1f076e62fea19eef51acd0657c22");
+
+ engine.update("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
+ assert(DigestEngine::digestToHex(engine.digest()) == "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7");
+
+ for (int i = 0; i < 1000000; ++i)
+ engine.update('a');
+ assert(DigestEngine::digestToHex(engine.digest()) == "eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e76847aa0774ddb90a842190d2c558b4b8340");
+}
+
+void SHA3EngineTest::testSHA3_512()
+{
+ SHA3Engine engine(SHA3Engine::SHA3_512);
+
+ engine.update("abc");
+ assert(DigestEngine::digestToHex(engine.digest()) == "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0");
+
+ engine.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
+ assert(DigestEngine::digestToHex(engine.digest()) == "04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e");
+
+ engine.update("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
+ assert(DigestEngine::digestToHex(engine.digest()) == "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185");
+
+ for (int i = 0; i < 1000000; ++i)
+ engine.update('a');
+ assert(DigestEngine::digestToHex(engine.digest()) == "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87");
+}
+
+void SHA3EngineTest::setUp()
+{
+}
+
+void SHA3EngineTest::tearDown()
+{
+}
+
+CppUnit::Test* SHA3EngineTest::suite()
+{
+ CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SHA3EngineTest");
+
+ CppUnit_addTest(pSuite, SHA3EngineTest, testSHA3_224);
+ CppUnit_addTest(pSuite, SHA3EngineTest, testSHA3_256);
+ CppUnit_addTest(pSuite, SHA3EngineTest, testSHA3_384);
+ CppUnit_addTest(pSuite, SHA3EngineTest, testSHA3_512);
+
+ return pSuite;
+}
diff --git a/Foundation/testsuite/src/SHA3EngineTest.h b/Foundation/testsuite/src/SHA3EngineTest.h
new file mode 100644
index 000000000..94e3e888e
--- /dev/null
+++ b/Foundation/testsuite/src/SHA3EngineTest.h
@@ -0,0 +1,39 @@
+//
+// SHA3EngineTest.h
+//
+// $Id: //poco/1.4/Foundation/testsuite/src/SHA3EngineTest.h#1 $
+//
+// Definition of the SHA3EngineTest class.
+//
+// Copyright (c) 2017, Applied Informatics Software Engineering GmbH
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+#ifndef SHA3EngineTest_INCLUDED
+#define SHA3EngineTest_INCLUDED
+
+#include "Poco/Foundation.h"
+#include "Poco/CppUnit/TestCase.h"
+
+class SHA3EngineTest: public CppUnit::TestCase
+{
+public:
+ SHA3EngineTest(const std::string& name);
+ ~SHA3EngineTest();
+
+ void testSHA3_224();
+ void testSHA3_256();
+ void testSHA3_384();
+ void testSHA3_512();
+
+ void setUp();
+ void tearDown();
+
+ static CppUnit::Test* suite();
+
+private:
+};
+
+#endif // SHA3EngineTest_INCLUDED