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