diff --git a/configure.ac b/configure.ac index 22d95c05e..981ae79fa 100644 --- a/configure.ac +++ b/configure.ac @@ -167,6 +167,7 @@ then enable_ripemd=yes enable_sha512=yes enable_sha224=yes + enable_sha3=yes enable_sessioncerts=yes enable_keygen=yes enable_certgen=yes @@ -1758,6 +1759,37 @@ fi AM_CONDITIONAL([BUILD_SHA224], [test "x$ENABLED_SHA224" = "xyes"]) +# set sha3 default +SHA3_DEFAULT=no +if test "$host_cpu" = "x86_64" +then + if test "x$ENABLED_FIPS" = "xno" + then + SHA3_DEFAULT=yes + fi +fi + +# SHA3 +AC_ARG_ENABLE([sha3], + [AS_HELP_STRING([--enable-sha3],[Enable wolfSSL SHA-3 support (default: enabled on x86_64)])], + [ ENABLED_SHA3=$enableval ], + [ ENABLED_SHA3=$SHA3_DEFAULT ] + ) + +if test "$ENABLED_SHA3" = "small" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3_SMALL" + ENABLED_SHA3="yes" +fi + +if test "$ENABLED_SHA3" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3" +fi + +AM_CONDITIONAL([BUILD_SHA3], [test "x$ENABLED_SHA3" = "xyes"]) + + # set POLY1305 default POLY1305_DEFAULT=yes @@ -3658,6 +3690,7 @@ echo " * RIPEMD: $ENABLED_RIPEMD" echo " * SHA: $ENABLED_SHA" echo " * SHA-224: $ENABLED_SHA224" echo " * SHA-512: $ENABLED_SHA512" +echo " * SHA3: $ENABLED_SHA3" echo " * BLAKE2: $ENABLED_BLAKE2" echo " * CMAC: $ENABLED_CMAC" echo " * keygen: $ENABLED_KEYGEN" diff --git a/src/include.am b/src/include.am index b8dd4951d..be2e6ac9b 100644 --- a/src/include.am +++ b/src/include.am @@ -115,6 +115,10 @@ if BUILD_SHA512 src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512.c endif +if BUILD_SHA3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha3.c +endif + src_libwolfssl_la_SOURCES += \ wolfcrypt/src/logging.c \ wolfcrypt/src/wc_encrypt.c \ diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 27e605c7a..ea5c35cf1 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +209,10 @@ void bench_sha224(int); void bench_sha256(int); void bench_sha384(int); void bench_sha512(int); +void bench_sha3_224(int); +void bench_sha3_256(int); +void bench_sha3_384(int); +void bench_sha3_512(int); int bench_ripemd(void); void bench_cmac(void); void bench_scrypt(void); @@ -824,6 +829,32 @@ static void* benchmarks_do(void* args) bench_sha512(1); #endif #endif +#ifdef WOLFSSL_SHA3 + #ifndef NO_SW_BENCH + bench_sha3_224(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + bench_sha3_224(1); + #endif + #ifndef NO_SW_BENCH + bench_sha3_256(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + bench_sha3_256(1); + #endif + #ifndef NO_SW_BENCH + bench_sha3_384(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + bench_sha3_384(1); + #endif + #ifndef NO_SW_BENCH + bench_sha3_512(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + bench_sha3_512(1); + #endif +#endif #ifdef WOLFSSL_RIPEMD bench_ripemd(); #endif @@ -2084,6 +2115,302 @@ exit: } #endif + +#ifdef WOLFSSL_SHA3 +void bench_sha3_224(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA224_DIGEST_SIZE, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_224(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_224 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_224_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_224; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_224_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_224; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha3_224: + bench_stats_sym_finish("SHA3-224", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha3_224 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_224_Free(&hash[i]); + } +#endif + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); +} + +void bench_sha3_256(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_256_DIGEST_SIZE, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_256(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_256 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_256_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_256; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_256_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_256; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha3_256: + bench_stats_sym_finish("SHA3-256", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha3_256 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_256_Free(&hash[i]); + } +#endif + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); +} + +void bench_sha3_384(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_384_DIGEST_SIZE, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_384(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_384 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_384_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_384; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_384_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_384; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha3_384: + bench_stats_sym_finish("SHA3-384", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha3_384 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_384_Free(&hash[i]); + } +#endif + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); +} + +void bench_sha3_512(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_512_DIGEST_SIZE, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_512(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_512 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_512_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_512; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_512_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_512; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha3_512: + bench_stats_sym_finish("SHA3-512", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha3_512 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_512_Free(&hash[i]); + } +#endif + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); +} +#endif + + #ifdef WOLFSSL_RIPEMD int bench_ripemd(void) { diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 3b895934b..fd5c3ca47 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -40,7 +40,8 @@ EXTRA_DIST += \ wolfcrypt/src/fp_sqr_comba_8.i \ wolfcrypt/src/fp_sqr_comba_9.i \ wolfcrypt/src/fp_sqr_comba_small_set.i \ - wolfcrypt/src/fe_x25519_128.i + wolfcrypt/src/fe_x25519_128.i \ + wolfcrypt/src/sha3_long.i EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/ti/ti-des3.c \ diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c new file mode 100755 index 000000000..584f3ce99 --- /dev/null +++ b/wolfcrypt/src/sha3.c @@ -0,0 +1,710 @@ +/* sha3.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_SHA3 + +#include +#include + +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + + int wc_InitSha3_224(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_224_fips(sha); + } + int wc_Sha3_224_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_224_Update_fips(sha, data, len); + } + int wc_Sha3_224_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_224_Final_fips(sha, out); + } + void wc_Sha3_224_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + int wc_InitSha3_256(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_256_fips(sha); + } + int wc_Sha3_256_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_256_Update_fips(sha, data, len); + } + int wc_Sha3_256_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_256_Final_fips(sha, out); + } + void wc_Sha3_256_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + int wc_InitSha3_384(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_384_fips(sha); + } + int wc_Sha3_384_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_384_Update_fips(sha, data, len); + } + int wc_Sha3_384_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_384_Final_fips(sha, out); + } + void wc_Sha3_384_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + int wc_InitSha3_512(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_512_fips(sha); + } + int wc_Sha3_512_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_512_Update_fips(sha, data, len); + } + int wc_Sha3_512_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_512_Final_fips(sha, out); + } + void wc_Sha3_512_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + +#else /* else build without fips */ + + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef WOLFSSL_SHA3_SMALL +/** + * Rotate a 64-bit value left. + * + * @param [in] a The number to rotate left. + * @param [in] r The number od bits to rotate left. + * @return The rotated number. + */ +#define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) + +/** An array of values to XOR for block operation. */ +static const word64 hash_keccak_r[24] = +{ + 0x0000000000000001UL, 0x0000000000008082UL, + 0x800000000000808aUL, 0x8000000080008000UL, + 0x000000000000808bUL, 0x0000000080000001UL, + 0x8000000080008081UL, 0x8000000000008009UL, + 0x000000000000008aUL, 0x0000000000000088UL, + 0x0000000080008009UL, 0x000000008000000aUL, + 0x000000008000808bUL, 0x800000000000008bUL, + 0x8000000000008089UL, 0x8000000000008003UL, + 0x8000000000008002UL, 0x8000000000000080UL, + 0x000000000000800aUL, 0x800000008000000aUL, + 0x8000000080008081UL, 0x8000000000008080UL, + 0x0000000080000001UL, 0x8000000080008008UL +}; + +#define K_I_0 10 +#define K_I_1 7 +#define K_I_2 11 +#define K_I_3 17 +#define K_I_4 18 +#define K_I_5 3 +#define K_I_6 5 +#define K_I_7 16 +#define K_I_8 8 +#define K_I_9 21 +#define K_I_10 24 +#define K_I_11 4 +#define K_I_12 15 +#define K_I_13 23 +#define K_I_14 19 +#define K_I_15 13 +#define K_I_16 12 +#define K_I_17 2 +#define K_I_18 20 +#define K_I_19 14 +#define K_I_20 22 +#define K_I_21 9 +#define K_I_22 6 +#define K_I_23 1 + +#define K_R_0 1 +#define K_R_1 3 +#define K_R_2 6 +#define K_R_3 10 +#define K_R_4 15 +#define K_R_5 21 +#define K_R_6 28 +#define K_R_7 36 +#define K_R_8 45 +#define K_R_9 55 +#define K_R_10 2 +#define K_R_11 14 +#define K_R_12 27 +#define K_R_13 41 +#define K_R_14 56 +#define K_R_15 8 +#define K_R_16 25 +#define K_R_17 43 +#define K_R_18 62 +#define K_R_19 18 +#define K_R_20 39 +#define K_R_21 61 +#define K_R_22 20 +#define K_R_23 44 + +/** + * Swap and rotate left operation. + * + * @param [in] s The state. + * @param [in] t1 Temporary value. + * @param [in] t2 Second temporary value. + * @param [in] i The index of the loop. + */ +#define SWAP_ROTL(s, t1, t2, i) \ +do \ +{ \ + t2 = s[K_I_##i]; s[K_I_##i] = ROTL64(t1, K_R_##i); \ +} \ +while (0) + +/** + * Mix the XOR of the column's values into each number by column. + * + * @param [in] s The state. + * @param [in] b Temporary array of XORed column values. + * @param [in] x The index of the column. + * @param [in] t Temporary variable. + */ +#define COL_MIX(s, b, x, t) \ +do \ +{ \ + for (x = 0; x < 5; x++) \ + b[x] = s[x + 0] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20]; \ + for (x = 0; x < 5; x++) \ + { \ + t = b[(x + 4) % 5] ^ ROTL64(b[(x + 1) % 5], 1); \ + s[x + 0] ^= t; \ + s[x + 5] ^= t; \ + s[x + 10] ^= t; \ + s[x + 15] ^= t; \ + s[x + 20] ^= t; \ + } \ +} \ +while (0) + +#ifdef SHA3_BY_SPEC +/** + * Mix the row values. + * BMI1 has ANDN instruction ((~a) & b) - Haswell and above. + * + * @param [in] s The state. + * @param [in] b Temporary array of XORed row values. + * @param [in] y The index of the row to work on. + * @param [in] x The index of the column. + * @param [in] t0 Temporary variable. + * @param [in] t1 Temporary variable. + */ +#define ROW_MIX(s, b, y, x, t0, t1) \ +do \ +{ \ + for (y = 0; y < 5; y++) \ + { \ + for (x = 0; x < 5; x++) \ + b[x] = s[y * 5 + x]; \ + for (x = 0; x < 5; x++) \ + s[y * 5 + x] = b[x] ^ (~b[(x + 1) % 5] & b[(x + 2) % 5]); \ + } \ +} \ +while (0) +#else +/** + * Mix the row values. + * a ^ (~b & c) == a ^ (c & (b ^ c)) == (a ^ b) ^ (b | c) + * + * @param [in] s The state. + * @param [in] b Temporary array of XORed row values. + * @param [in] y The index of the row to work on. + * @param [in] x The index of the column. + * @param [in] t0 Temporary variable. + * @param [in] t1 Temporary variable. + */ +#define ROW_MIX(s, b, y, x, t12, t34) \ +do \ +{ \ + for (y = 0; y < 5; y++) \ + { \ + for (x = 0; x < 5; x++) \ + b[x] = s[y * 5 + x]; \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s[y * 5 + 0] = b[0] ^ (b[2] & t12); \ + s[y * 5 + 1] = t12 ^ (b[2] | b[3]); \ + s[y * 5 + 2] = b[2] ^ (b[4] & t34); \ + s[y * 5 + 3] = t34 ^ (b[4] | b[0]); \ + s[y * 5 + 4] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + } \ +} \ +while (0) +#endif + +/** + * The block operation performed on the state. + * + * @param [in] s The state. + */ +static void BlockSha3(word64 *s) +{ + byte i, x, y; + word64 t0, t1; + word64 b[5]; + + for (i = 0; i < 24; i++) + { + COL_MIX(s, b, x, t0); + + t0 = s[1]; + SWAP_ROTL(s, t0, t1, 0); + SWAP_ROTL(s, t1, t0, 1); + SWAP_ROTL(s, t0, t1, 2); + SWAP_ROTL(s, t1, t0, 3); + SWAP_ROTL(s, t0, t1, 4); + SWAP_ROTL(s, t1, t0, 5); + SWAP_ROTL(s, t0, t1, 6); + SWAP_ROTL(s, t1, t0, 7); + SWAP_ROTL(s, t0, t1, 8); + SWAP_ROTL(s, t1, t0, 9); + SWAP_ROTL(s, t0, t1, 10); + SWAP_ROTL(s, t1, t0, 11); + SWAP_ROTL(s, t0, t1, 12); + SWAP_ROTL(s, t1, t0, 13); + SWAP_ROTL(s, t0, t1, 14); + SWAP_ROTL(s, t1, t0, 15); + SWAP_ROTL(s, t0, t1, 16); + SWAP_ROTL(s, t1, t0, 17); + SWAP_ROTL(s, t0, t1, 18); + SWAP_ROTL(s, t1, t0, 19); + SWAP_ROTL(s, t0, t1, 20); + SWAP_ROTL(s, t1, t0, 21); + SWAP_ROTL(s, t0, t1, 22); + SWAP_ROTL(s, t1, t0, 23); + + ROW_MIX(s, b, y, x, t0, t1); + + s[0] ^= hash_keccak_r[i]; + } +} +#else +#include "sha3_long.i" +#endif + +static word64 Load64BitBigEndian(const byte* x) +{ +#if defined(BIG_ENDIAN_ORDER) + word64 r = 0; + int i; + + for (i = 0; i < 8; i++) + r |= (word64)x[i] << (8 * i); + + return r; +#else + return *(word64*)x; +#endif +} + +static int InitSha3(Sha3* sha3) +{ + int i; + + for (i = 0; i < 25; i++) + sha3->s[i] = 0; + sha3->i = 0; + + return 0; +} + +static int Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) +{ + byte i; + byte l; + byte *t; + + if (sha3->i > 0) + { + l = p * 8 - sha3->i; + if (l > len) + l = len; + + t = &sha3->t[sha3->i]; + for (i = 0; i < l; i++) + t[i] = data[i]; + data += i; + len -= i; + sha3->i += i; + + if (sha3->i == p * 8) + { + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); + BlockSha3(sha3->s); + sha3->i = 0; + } + } + while (len >= p * 8) + { + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(data + 8 * i); + BlockSha3(sha3->s); + len -= p * 8; + data += p * 8; + } + for (i = 0; i < len; i++) + sha3->t[i] = data[i]; + sha3->i += i; + + return 0; +} + +static int Sha3Final(Sha3* sha3, byte* hash, byte r, byte l) +{ + byte i; + byte *s8 = (byte *)sha3->s; + + sha3->t[r * 8 - 1] = 0x00; + sha3->t[ sha3->i] = 0x06; + sha3->t[r * 8 - 1] |= 0x80; + for (i=sha3->i + 1; i < r * 8 - 1; i++) + sha3->t[i] = 0; + for (i = 0; i < r; i++) + sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); + BlockSha3(sha3->s); + for (i = 0; i < l; i++) + hash[i] = s8[i]; +#if defined(BIG_ENDIAN_ORDER) + ByteReverseWords64((word64*)hash, (word64*)hash, l); +#endif + + return 0; +} + +static int wc_InitSha3(Sha3* sha3, void* heap, int devId) +{ + int ret = 0; + + if (sha3 == NULL) + return BAD_FUNC_ARG; + + sha3->heap = heap; + ret = InitSha3(sha3); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + ret = wolfAsync_DevCtxInit(&sha3->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA3, sha3->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +static int wc_Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) +{ + int ret = 0; + + if (sha3 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha3(&sha3->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + Sha3Update(sha3, data, len, p); + + return ret; +} + +static int wc_Sha3Final(Sha3* sha3, byte* hash, byte p, byte len) +{ + int ret; + + if (sha3 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha3(&sha3->asyncDev, hash, NULL, + SHA3_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha3Final(sha3, hash, p, len); + if (ret != 0) + return ret; + + return InitSha3(sha3); /* reset state */ +} + +static void wc_Sha3Free(Sha3* sha3) +{ + (void)sha3; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3 == NULL) + return; + + wolfAsync_DevCtxFree(&sha3->asyncDev, WOLFSSL_ASYNC_MARKER_SHA3); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} +#endif /* HAVE_FIPS */ + +static int wc_Sha3Copy(Sha3* src, Sha3* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha3)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif + + return ret; +} + +static int wc_Sha3GetHash(Sha3* sha3, byte* hash, byte p, byte l) +{ + int ret; + Sha3 tmpSha3; + + if (sha3 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha3Copy(sha3, &tmpSha3); + if (ret == 0) { + ret = wc_Sha3Final(&tmpSha3, hash, p, l); + } + return ret; +} + + +WOLFSSL_API int wc_InitSha3_224(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +WOLFSSL_API int wc_Sha3_224_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_224_COUNT); +} + +WOLFSSL_API int wc_Sha3_224_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_224_COUNT, SHA3_224_DIGEST_SIZE); +} + +WOLFSSL_API void wc_Sha3_224_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +WOLFSSL_API int wc_Sha3_224_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_224_COUNT, SHA3_224_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Sha3_224_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +WOLFSSL_API int wc_InitSha3_256(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +WOLFSSL_API int wc_Sha3_256_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_256_COUNT); +} + +WOLFSSL_API int wc_Sha3_256_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_256_COUNT, SHA3_256_DIGEST_SIZE); +} + +WOLFSSL_API void wc_Sha3_256_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +WOLFSSL_API int wc_Sha3_256_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_256_COUNT, SHA3_256_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Sha3_256_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +WOLFSSL_API int wc_InitSha3_384(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +WOLFSSL_API int wc_Sha3_384_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_384_COUNT); +} + +WOLFSSL_API int wc_Sha3_384_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_384_COUNT, SHA3_384_DIGEST_SIZE); +} + +WOLFSSL_API void wc_Sha3_384_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +WOLFSSL_API int wc_Sha3_384_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_384_COUNT, SHA3_384_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Sha3_384_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +WOLFSSL_API int wc_InitSha3_512(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +WOLFSSL_API int wc_Sha3_512_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_512_COUNT); +} + +WOLFSSL_API int wc_Sha3_512_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_512_COUNT, SHA3_512_DIGEST_SIZE); +} + +WOLFSSL_API void wc_Sha3_512_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +WOLFSSL_API int wc_Sha3_512_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_512_COUNT, SHA3_512_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Sha3_512_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + +#endif /* WOLFSSL_SHA3 */ diff --git a/wolfcrypt/src/sha3_long.i b/wolfcrypt/src/sha3_long.i new file mode 100644 index 000000000..bcf6c91ae --- /dev/null +++ b/wolfcrypt/src/sha3_long.i @@ -0,0 +1,2345 @@ +/* sha_long.i + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/** + * Rotate a 64-bit value left. + * + * @param [in] a The number to rotate left. + * @param [in] r The number od bits to rotate left. + * @return The rotated number. + */ +#define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) + +/** + * The block operation performed on the state. + * + * @param [in] s The state. + */ +static void BlockSha3(word64 *s) +{ + word64 b[5], t; + + /* Round 0. */ + /* Col Mix */ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + b[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + b[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + b[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + b[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[5]^=t; s[10]^=t; s[15]^=t; s[20]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[6]^=t; s[11]^=t; s[16]^=t; s[21]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[7]^=t; s[12]^=t; s[17]^=t; s[22]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[8]^=t; s[13]^=t; s[18]^=t; s[23]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[9]^=t; s[14]^=t; s[19]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[6], 44); + b[2] = ROTL64(s[12], 43); + b[3] = ROTL64(s[18], 21); + b[4] = ROTL64(s[24], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[3], 28); + b[1] = ROTL64(s[9], 20); + b[2] = ROTL64(s[10], 3); + b[3] = ROTL64(s[16], 45); + b[4] = ROTL64(s[22], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[3] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[1], 1); + b[1] = ROTL64(s[7], 6); + b[2] = ROTL64(s[13], 25); + b[3] = ROTL64(s[19], 8); + b[4] = ROTL64(s[20], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[1] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[4], 27); + b[1] = ROTL64(s[5], 36); + b[2] = ROTL64(s[11], 10); + b[3] = ROTL64(s[17], 15); + b[4] = ROTL64(s[23], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[4] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[2], 62); + b[1] = ROTL64(s[8], 55); + b[2] = ROTL64(s[14], 39); + b[3] = ROTL64(s[15], 41); + b[4] = ROTL64(s[21], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[2] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x1UL; + + /* Round 1. */ + /* Col Mix */ + b[0] = s[0] ^ s[1] ^ s[2] ^ s[3] ^ s[4]; + b[1] = s[5] ^ s[6] ^ s[7] ^ s[8] ^ s[9]; + b[2] = s[10] ^ s[11] ^ s[12] ^ s[13] ^ s[14]; + b[3] = s[15] ^ s[16] ^ s[17] ^ s[18] ^ s[19]; + b[4] = s[20] ^ s[21] ^ s[22] ^ s[23] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[1]^=t; s[2]^=t; s[3]^=t; s[4]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[5]^=t; s[6]^=t; s[7]^=t; s[8]^=t; s[9]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[10]^=t; s[11]^=t; s[12]^=t; s[13]^=t; s[14]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[15]^=t; s[16]^=t; s[17]^=t; s[18]^=t; s[19]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[20]^=t; s[21]^=t; s[22]^=t; s[23]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[9], 44); + b[2] = ROTL64(s[13], 43); + b[3] = ROTL64(s[17], 21); + b[4] = ROTL64(s[21], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[18], 28); + b[1] = ROTL64(s[22], 20); + b[2] = ROTL64(s[1], 3); + b[3] = ROTL64(s[5], 45); + b[4] = ROTL64(s[14], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[18] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[6], 1); + b[1] = ROTL64(s[10], 6); + b[2] = ROTL64(s[19], 25); + b[3] = ROTL64(s[23], 8); + b[4] = ROTL64(s[2], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[6] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[24], 27); + b[1] = ROTL64(s[3], 36); + b[2] = ROTL64(s[7], 10); + b[3] = ROTL64(s[11], 15); + b[4] = ROTL64(s[15], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[24] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[12], 62); + b[1] = ROTL64(s[16], 55); + b[2] = ROTL64(s[20], 39); + b[3] = ROTL64(s[4], 41); + b[4] = ROTL64(s[8], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[12] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8082UL; + + /* Round 2. */ + /* Col Mix */ + b[0] = s[0] ^ s[6] ^ s[12] ^ s[18] ^ s[24]; + b[1] = s[3] ^ s[9] ^ s[10] ^ s[16] ^ s[22]; + b[2] = s[1] ^ s[7] ^ s[13] ^ s[19] ^ s[20]; + b[3] = s[4] ^ s[5] ^ s[11] ^ s[17] ^ s[23]; + b[4] = s[2] ^ s[8] ^ s[14] ^ s[15] ^ s[21]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[6]^=t; s[12]^=t; s[18]^=t; s[24]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[9]^=t; s[10]^=t; s[16]^=t; s[22]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[7]^=t; s[13]^=t; s[19]^=t; s[20]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[5]^=t; s[11]^=t; s[17]^=t; s[23]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[8]^=t; s[14]^=t; s[15]^=t; s[21]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[22], 44); + b[2] = ROTL64(s[19], 43); + b[3] = ROTL64(s[11], 21); + b[4] = ROTL64(s[8], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[17], 28); + b[1] = ROTL64(s[14], 20); + b[2] = ROTL64(s[6], 3); + b[3] = ROTL64(s[3], 45); + b[4] = ROTL64(s[20], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[17] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[9], 1); + b[1] = ROTL64(s[1], 6); + b[2] = ROTL64(s[23], 25); + b[3] = ROTL64(s[15], 8); + b[4] = ROTL64(s[12], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[9] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[21], 27); + b[1] = ROTL64(s[18], 36); + b[2] = ROTL64(s[10], 10); + b[3] = ROTL64(s[7], 15); + b[4] = ROTL64(s[4], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[21] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[13], 62); + b[1] = ROTL64(s[5], 55); + b[2] = ROTL64(s[2], 39); + b[3] = ROTL64(s[24], 41); + b[4] = ROTL64(s[16], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[13] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x800000000000808aUL; + + /* Round 3. */ + /* Col Mix */ + b[0] = s[0] ^ s[9] ^ s[13] ^ s[17] ^ s[21]; + b[1] = s[1] ^ s[5] ^ s[14] ^ s[18] ^ s[22]; + b[2] = s[2] ^ s[6] ^ s[10] ^ s[19] ^ s[23]; + b[3] = s[3] ^ s[7] ^ s[11] ^ s[15] ^ s[24]; + b[4] = s[4] ^ s[8] ^ s[12] ^ s[16] ^ s[20]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[9]^=t; s[13]^=t; s[17]^=t; s[21]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[5]^=t; s[14]^=t; s[18]^=t; s[22]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[6]^=t; s[10]^=t; s[19]^=t; s[23]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[7]^=t; s[11]^=t; s[15]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[8]^=t; s[12]^=t; s[16]^=t; s[20]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[14], 44); + b[2] = ROTL64(s[23], 43); + b[3] = ROTL64(s[7], 21); + b[4] = ROTL64(s[16], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[11], 28); + b[1] = ROTL64(s[20], 20); + b[2] = ROTL64(s[9], 3); + b[3] = ROTL64(s[18], 45); + b[4] = ROTL64(s[2], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[11] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[22], 1); + b[1] = ROTL64(s[6], 6); + b[2] = ROTL64(s[15], 25); + b[3] = ROTL64(s[4], 8); + b[4] = ROTL64(s[13], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[22] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[8], 27); + b[1] = ROTL64(s[17], 36); + b[2] = ROTL64(s[1], 10); + b[3] = ROTL64(s[10], 15); + b[4] = ROTL64(s[24], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[8] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[19], 62); + b[1] = ROTL64(s[3], 55); + b[2] = ROTL64(s[12], 39); + b[3] = ROTL64(s[21], 41); + b[4] = ROTL64(s[5], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[19] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000080008000UL; + + /* Round 4. */ + /* Col Mix */ + b[0] = s[0] ^ s[8] ^ s[11] ^ s[19] ^ s[22]; + b[1] = s[3] ^ s[6] ^ s[14] ^ s[17] ^ s[20]; + b[2] = s[1] ^ s[9] ^ s[12] ^ s[15] ^ s[23]; + b[3] = s[4] ^ s[7] ^ s[10] ^ s[18] ^ s[21]; + b[4] = s[2] ^ s[5] ^ s[13] ^ s[16] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[8]^=t; s[11]^=t; s[19]^=t; s[22]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[6]^=t; s[14]^=t; s[17]^=t; s[20]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[9]^=t; s[12]^=t; s[15]^=t; s[23]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[7]^=t; s[10]^=t; s[18]^=t; s[21]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[5]^=t; s[13]^=t; s[16]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[20], 44); + b[2] = ROTL64(s[15], 43); + b[3] = ROTL64(s[10], 21); + b[4] = ROTL64(s[5], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[7], 28); + b[1] = ROTL64(s[2], 20); + b[2] = ROTL64(s[22], 3); + b[3] = ROTL64(s[17], 45); + b[4] = ROTL64(s[12], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[7] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[14], 1); + b[1] = ROTL64(s[9], 6); + b[2] = ROTL64(s[4], 25); + b[3] = ROTL64(s[24], 8); + b[4] = ROTL64(s[19], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[14] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[16], 27); + b[1] = ROTL64(s[11], 36); + b[2] = ROTL64(s[6], 10); + b[3] = ROTL64(s[1], 15); + b[4] = ROTL64(s[21], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[16] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[23], 62); + b[1] = ROTL64(s[18], 55); + b[2] = ROTL64(s[13], 39); + b[3] = ROTL64(s[8], 41); + b[4] = ROTL64(s[3], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[23] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x808bUL; + + /* Round 5. */ + /* Col Mix */ + b[0] = s[0] ^ s[7] ^ s[14] ^ s[16] ^ s[23]; + b[1] = s[2] ^ s[9] ^ s[11] ^ s[18] ^ s[20]; + b[2] = s[4] ^ s[6] ^ s[13] ^ s[15] ^ s[22]; + b[3] = s[1] ^ s[8] ^ s[10] ^ s[17] ^ s[24]; + b[4] = s[3] ^ s[5] ^ s[12] ^ s[19] ^ s[21]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[7]^=t; s[14]^=t; s[16]^=t; s[23]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[9]^=t; s[11]^=t; s[18]^=t; s[20]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[6]^=t; s[13]^=t; s[15]^=t; s[22]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[8]^=t; s[10]^=t; s[17]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[5]^=t; s[12]^=t; s[19]^=t; s[21]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[2], 44); + b[2] = ROTL64(s[4], 43); + b[3] = ROTL64(s[1], 21); + b[4] = ROTL64(s[3], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[10], 28); + b[1] = ROTL64(s[12], 20); + b[2] = ROTL64(s[14], 3); + b[3] = ROTL64(s[11], 45); + b[4] = ROTL64(s[13], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[10] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[20], 1); + b[1] = ROTL64(s[22], 6); + b[2] = ROTL64(s[24], 25); + b[3] = ROTL64(s[21], 8); + b[4] = ROTL64(s[23], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[20] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[5], 27); + b[1] = ROTL64(s[7], 36); + b[2] = ROTL64(s[9], 10); + b[3] = ROTL64(s[6], 15); + b[4] = ROTL64(s[8], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[5] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[15], 62); + b[1] = ROTL64(s[17], 55); + b[2] = ROTL64(s[19], 39); + b[3] = ROTL64(s[16], 41); + b[4] = ROTL64(s[18], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[15] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x80000001UL; + + /* Round 6. */ + /* Col Mix */ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + b[1] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + b[2] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + b[3] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + b[4] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[5]^=t; s[10]^=t; s[15]^=t; s[20]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[7]^=t; s[12]^=t; s[17]^=t; s[22]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[9]^=t; s[14]^=t; s[19]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[6]^=t; s[11]^=t; s[16]^=t; s[21]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[8]^=t; s[13]^=t; s[18]^=t; s[23]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[12], 44); + b[2] = ROTL64(s[24], 43); + b[3] = ROTL64(s[6], 21); + b[4] = ROTL64(s[18], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[1], 28); + b[1] = ROTL64(s[13], 20); + b[2] = ROTL64(s[20], 3); + b[3] = ROTL64(s[7], 45); + b[4] = ROTL64(s[19], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[1] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[2], 1); + b[1] = ROTL64(s[14], 6); + b[2] = ROTL64(s[21], 25); + b[3] = ROTL64(s[8], 8); + b[4] = ROTL64(s[15], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[2] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[3], 27); + b[1] = ROTL64(s[10], 36); + b[2] = ROTL64(s[22], 10); + b[3] = ROTL64(s[9], 15); + b[4] = ROTL64(s[16], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[3] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[4], 62); + b[1] = ROTL64(s[11], 55); + b[2] = ROTL64(s[23], 39); + b[3] = ROTL64(s[5], 41); + b[4] = ROTL64(s[17], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[4] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000080008081UL; + + /* Round 7. */ + /* Col Mix */ + b[0] = s[0] ^ s[1] ^ s[2] ^ s[3] ^ s[4]; + b[1] = s[10] ^ s[11] ^ s[12] ^ s[13] ^ s[14]; + b[2] = s[20] ^ s[21] ^ s[22] ^ s[23] ^ s[24]; + b[3] = s[5] ^ s[6] ^ s[7] ^ s[8] ^ s[9]; + b[4] = s[15] ^ s[16] ^ s[17] ^ s[18] ^ s[19]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[1]^=t; s[2]^=t; s[3]^=t; s[4]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[10]^=t; s[11]^=t; s[12]^=t; s[13]^=t; s[14]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[20]^=t; s[21]^=t; s[22]^=t; s[23]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[5]^=t; s[6]^=t; s[7]^=t; s[8]^=t; s[9]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[15]^=t; s[16]^=t; s[17]^=t; s[18]^=t; s[19]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[13], 44); + b[2] = ROTL64(s[21], 43); + b[3] = ROTL64(s[9], 21); + b[4] = ROTL64(s[17], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[6], 28); + b[1] = ROTL64(s[19], 20); + b[2] = ROTL64(s[2], 3); + b[3] = ROTL64(s[10], 45); + b[4] = ROTL64(s[23], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[6] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[12], 1); + b[1] = ROTL64(s[20], 6); + b[2] = ROTL64(s[8], 25); + b[3] = ROTL64(s[16], 8); + b[4] = ROTL64(s[4], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[12] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[18], 27); + b[1] = ROTL64(s[1], 36); + b[2] = ROTL64(s[14], 10); + b[3] = ROTL64(s[22], 15); + b[4] = ROTL64(s[5], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[18] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[24], 62); + b[1] = ROTL64(s[7], 55); + b[2] = ROTL64(s[15], 39); + b[3] = ROTL64(s[3], 41); + b[4] = ROTL64(s[11], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[24] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008009UL; + + /* Round 8. */ + /* Col Mix */ + b[0] = s[0] ^ s[6] ^ s[12] ^ s[18] ^ s[24]; + b[1] = s[1] ^ s[7] ^ s[13] ^ s[19] ^ s[20]; + b[2] = s[2] ^ s[8] ^ s[14] ^ s[15] ^ s[21]; + b[3] = s[3] ^ s[9] ^ s[10] ^ s[16] ^ s[22]; + b[4] = s[4] ^ s[5] ^ s[11] ^ s[17] ^ s[23]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[6]^=t; s[12]^=t; s[18]^=t; s[24]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[7]^=t; s[13]^=t; s[19]^=t; s[20]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[8]^=t; s[14]^=t; s[15]^=t; s[21]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[9]^=t; s[10]^=t; s[16]^=t; s[22]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[5]^=t; s[11]^=t; s[17]^=t; s[23]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[19], 44); + b[2] = ROTL64(s[8], 43); + b[3] = ROTL64(s[22], 21); + b[4] = ROTL64(s[11], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[9], 28); + b[1] = ROTL64(s[23], 20); + b[2] = ROTL64(s[12], 3); + b[3] = ROTL64(s[1], 45); + b[4] = ROTL64(s[15], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[9] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[13], 1); + b[1] = ROTL64(s[2], 6); + b[2] = ROTL64(s[16], 25); + b[3] = ROTL64(s[5], 8); + b[4] = ROTL64(s[24], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[13] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[17], 27); + b[1] = ROTL64(s[6], 36); + b[2] = ROTL64(s[20], 10); + b[3] = ROTL64(s[14], 15); + b[4] = ROTL64(s[3], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[17] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[21], 62); + b[1] = ROTL64(s[10], 55); + b[2] = ROTL64(s[4], 39); + b[3] = ROTL64(s[18], 41); + b[4] = ROTL64(s[7], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[21] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8aUL; + + /* Round 9. */ + /* Col Mix */ + b[0] = s[0] ^ s[9] ^ s[13] ^ s[17] ^ s[21]; + b[1] = s[2] ^ s[6] ^ s[10] ^ s[19] ^ s[23]; + b[2] = s[4] ^ s[8] ^ s[12] ^ s[16] ^ s[20]; + b[3] = s[1] ^ s[5] ^ s[14] ^ s[18] ^ s[22]; + b[4] = s[3] ^ s[7] ^ s[11] ^ s[15] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[9]^=t; s[13]^=t; s[17]^=t; s[21]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[6]^=t; s[10]^=t; s[19]^=t; s[23]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[8]^=t; s[12]^=t; s[16]^=t; s[20]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[5]^=t; s[14]^=t; s[18]^=t; s[22]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[7]^=t; s[11]^=t; s[15]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[23], 44); + b[2] = ROTL64(s[16], 43); + b[3] = ROTL64(s[14], 21); + b[4] = ROTL64(s[7], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[22], 28); + b[1] = ROTL64(s[15], 20); + b[2] = ROTL64(s[13], 3); + b[3] = ROTL64(s[6], 45); + b[4] = ROTL64(s[4], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[22] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[19], 1); + b[1] = ROTL64(s[12], 6); + b[2] = ROTL64(s[5], 25); + b[3] = ROTL64(s[3], 8); + b[4] = ROTL64(s[21], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[19] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[11], 27); + b[1] = ROTL64(s[9], 36); + b[2] = ROTL64(s[2], 10); + b[3] = ROTL64(s[20], 15); + b[4] = ROTL64(s[18], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[11] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[8], 62); + b[1] = ROTL64(s[1], 55); + b[2] = ROTL64(s[24], 39); + b[3] = ROTL64(s[17], 41); + b[4] = ROTL64(s[10], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[8] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x88UL; + + /* Round 10. */ + /* Col Mix */ + b[0] = s[0] ^ s[8] ^ s[11] ^ s[19] ^ s[22]; + b[1] = s[1] ^ s[9] ^ s[12] ^ s[15] ^ s[23]; + b[2] = s[2] ^ s[5] ^ s[13] ^ s[16] ^ s[24]; + b[3] = s[3] ^ s[6] ^ s[14] ^ s[17] ^ s[20]; + b[4] = s[4] ^ s[7] ^ s[10] ^ s[18] ^ s[21]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[8]^=t; s[11]^=t; s[19]^=t; s[22]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[9]^=t; s[12]^=t; s[15]^=t; s[23]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[5]^=t; s[13]^=t; s[16]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[6]^=t; s[14]^=t; s[17]^=t; s[20]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[7]^=t; s[10]^=t; s[18]^=t; s[21]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[15], 44); + b[2] = ROTL64(s[5], 43); + b[3] = ROTL64(s[20], 21); + b[4] = ROTL64(s[10], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[14], 28); + b[1] = ROTL64(s[4], 20); + b[2] = ROTL64(s[19], 3); + b[3] = ROTL64(s[9], 45); + b[4] = ROTL64(s[24], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[14] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[23], 1); + b[1] = ROTL64(s[13], 6); + b[2] = ROTL64(s[3], 25); + b[3] = ROTL64(s[18], 8); + b[4] = ROTL64(s[8], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[23] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[7], 27); + b[1] = ROTL64(s[22], 36); + b[2] = ROTL64(s[12], 10); + b[3] = ROTL64(s[2], 15); + b[4] = ROTL64(s[17], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[7] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[16], 62); + b[1] = ROTL64(s[6], 55); + b[2] = ROTL64(s[21], 39); + b[3] = ROTL64(s[11], 41); + b[4] = ROTL64(s[1], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[16] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x80008009UL; + + /* Round 11. */ + /* Col Mix */ + b[0] = s[0] ^ s[7] ^ s[14] ^ s[16] ^ s[23]; + b[1] = s[4] ^ s[6] ^ s[13] ^ s[15] ^ s[22]; + b[2] = s[3] ^ s[5] ^ s[12] ^ s[19] ^ s[21]; + b[3] = s[2] ^ s[9] ^ s[11] ^ s[18] ^ s[20]; + b[4] = s[1] ^ s[8] ^ s[10] ^ s[17] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[7]^=t; s[14]^=t; s[16]^=t; s[23]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[6]^=t; s[13]^=t; s[15]^=t; s[22]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[5]^=t; s[12]^=t; s[19]^=t; s[21]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[9]^=t; s[11]^=t; s[18]^=t; s[20]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[8]^=t; s[10]^=t; s[17]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[4], 44); + b[2] = ROTL64(s[3], 43); + b[3] = ROTL64(s[2], 21); + b[4] = ROTL64(s[1], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[20], 28); + b[1] = ROTL64(s[24], 20); + b[2] = ROTL64(s[23], 3); + b[3] = ROTL64(s[22], 45); + b[4] = ROTL64(s[21], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[20] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[15], 1); + b[1] = ROTL64(s[19], 6); + b[2] = ROTL64(s[18], 25); + b[3] = ROTL64(s[17], 8); + b[4] = ROTL64(s[16], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[15] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[10], 27); + b[1] = ROTL64(s[14], 36); + b[2] = ROTL64(s[13], 10); + b[3] = ROTL64(s[12], 15); + b[4] = ROTL64(s[11], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[10] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[5], 62); + b[1] = ROTL64(s[9], 55); + b[2] = ROTL64(s[8], 39); + b[3] = ROTL64(s[7], 41); + b[4] = ROTL64(s[6], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[5] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000aUL; + + /* Round 12. */ + /* Col Mix */ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + b[1] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + b[2] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + b[3] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + b[4] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[5]^=t; s[10]^=t; s[15]^=t; s[20]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[9]^=t; s[14]^=t; s[19]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[8]^=t; s[13]^=t; s[18]^=t; s[23]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[7]^=t; s[12]^=t; s[17]^=t; s[22]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[6]^=t; s[11]^=t; s[16]^=t; s[21]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[24], 44); + b[2] = ROTL64(s[18], 43); + b[3] = ROTL64(s[12], 21); + b[4] = ROTL64(s[6], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[2], 28); + b[1] = ROTL64(s[21], 20); + b[2] = ROTL64(s[15], 3); + b[3] = ROTL64(s[14], 45); + b[4] = ROTL64(s[8], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[2] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[4], 1); + b[1] = ROTL64(s[23], 6); + b[2] = ROTL64(s[17], 25); + b[3] = ROTL64(s[11], 8); + b[4] = ROTL64(s[5], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[4] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[1], 27); + b[1] = ROTL64(s[20], 36); + b[2] = ROTL64(s[19], 10); + b[3] = ROTL64(s[13], 15); + b[4] = ROTL64(s[7], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[1] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[3], 62); + b[1] = ROTL64(s[22], 55); + b[2] = ROTL64(s[16], 39); + b[3] = ROTL64(s[10], 41); + b[4] = ROTL64(s[9], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[3] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000808bUL; + + /* Round 13. */ + /* Col Mix */ + b[0] = s[0] ^ s[1] ^ s[2] ^ s[3] ^ s[4]; + b[1] = s[20] ^ s[21] ^ s[22] ^ s[23] ^ s[24]; + b[2] = s[15] ^ s[16] ^ s[17] ^ s[18] ^ s[19]; + b[3] = s[10] ^ s[11] ^ s[12] ^ s[13] ^ s[14]; + b[4] = s[5] ^ s[6] ^ s[7] ^ s[8] ^ s[9]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[1]^=t; s[2]^=t; s[3]^=t; s[4]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[20]^=t; s[21]^=t; s[22]^=t; s[23]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[15]^=t; s[16]^=t; s[17]^=t; s[18]^=t; s[19]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[10]^=t; s[11]^=t; s[12]^=t; s[13]^=t; s[14]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[5]^=t; s[6]^=t; s[7]^=t; s[8]^=t; s[9]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[21], 44); + b[2] = ROTL64(s[17], 43); + b[3] = ROTL64(s[13], 21); + b[4] = ROTL64(s[9], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[12], 28); + b[1] = ROTL64(s[8], 20); + b[2] = ROTL64(s[4], 3); + b[3] = ROTL64(s[20], 45); + b[4] = ROTL64(s[16], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[12] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[24], 1); + b[1] = ROTL64(s[15], 6); + b[2] = ROTL64(s[11], 25); + b[3] = ROTL64(s[7], 8); + b[4] = ROTL64(s[3], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[24] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[6], 27); + b[1] = ROTL64(s[2], 36); + b[2] = ROTL64(s[23], 10); + b[3] = ROTL64(s[19], 15); + b[4] = ROTL64(s[10], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[6] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[18], 62); + b[1] = ROTL64(s[14], 55); + b[2] = ROTL64(s[5], 39); + b[3] = ROTL64(s[1], 41); + b[4] = ROTL64(s[22], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[18] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x800000000000008bUL; + + /* Round 14. */ + /* Col Mix */ + b[0] = s[0] ^ s[6] ^ s[12] ^ s[18] ^ s[24]; + b[1] = s[2] ^ s[8] ^ s[14] ^ s[15] ^ s[21]; + b[2] = s[4] ^ s[5] ^ s[11] ^ s[17] ^ s[23]; + b[3] = s[1] ^ s[7] ^ s[13] ^ s[19] ^ s[20]; + b[4] = s[3] ^ s[9] ^ s[10] ^ s[16] ^ s[22]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[6]^=t; s[12]^=t; s[18]^=t; s[24]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[8]^=t; s[14]^=t; s[15]^=t; s[21]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[5]^=t; s[11]^=t; s[17]^=t; s[23]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[7]^=t; s[13]^=t; s[19]^=t; s[20]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[9]^=t; s[10]^=t; s[16]^=t; s[22]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[8], 44); + b[2] = ROTL64(s[11], 43); + b[3] = ROTL64(s[19], 21); + b[4] = ROTL64(s[22], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[13], 28); + b[1] = ROTL64(s[16], 20); + b[2] = ROTL64(s[24], 3); + b[3] = ROTL64(s[2], 45); + b[4] = ROTL64(s[5], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[13] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[21], 1); + b[1] = ROTL64(s[4], 6); + b[2] = ROTL64(s[7], 25); + b[3] = ROTL64(s[10], 8); + b[4] = ROTL64(s[18], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[21] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[9], 27); + b[1] = ROTL64(s[12], 36); + b[2] = ROTL64(s[15], 10); + b[3] = ROTL64(s[23], 15); + b[4] = ROTL64(s[1], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[9] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[17], 62); + b[1] = ROTL64(s[20], 55); + b[2] = ROTL64(s[3], 39); + b[3] = ROTL64(s[6], 41); + b[4] = ROTL64(s[14], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[17] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008089UL; + + /* Round 15. */ + /* Col Mix */ + b[0] = s[0] ^ s[9] ^ s[13] ^ s[17] ^ s[21]; + b[1] = s[4] ^ s[8] ^ s[12] ^ s[16] ^ s[20]; + b[2] = s[3] ^ s[7] ^ s[11] ^ s[15] ^ s[24]; + b[3] = s[2] ^ s[6] ^ s[10] ^ s[19] ^ s[23]; + b[4] = s[1] ^ s[5] ^ s[14] ^ s[18] ^ s[22]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[9]^=t; s[13]^=t; s[17]^=t; s[21]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[8]^=t; s[12]^=t; s[16]^=t; s[20]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[7]^=t; s[11]^=t; s[15]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[6]^=t; s[10]^=t; s[19]^=t; s[23]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[5]^=t; s[14]^=t; s[18]^=t; s[22]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[16], 44); + b[2] = ROTL64(s[7], 43); + b[3] = ROTL64(s[23], 21); + b[4] = ROTL64(s[14], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[19], 28); + b[1] = ROTL64(s[5], 20); + b[2] = ROTL64(s[21], 3); + b[3] = ROTL64(s[12], 45); + b[4] = ROTL64(s[3], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[19] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[8], 1); + b[1] = ROTL64(s[24], 6); + b[2] = ROTL64(s[10], 25); + b[3] = ROTL64(s[1], 8); + b[4] = ROTL64(s[17], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[8] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[22], 27); + b[1] = ROTL64(s[13], 36); + b[2] = ROTL64(s[4], 10); + b[3] = ROTL64(s[15], 15); + b[4] = ROTL64(s[6], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[22] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[11], 62); + b[1] = ROTL64(s[2], 55); + b[2] = ROTL64(s[18], 39); + b[3] = ROTL64(s[9], 41); + b[4] = ROTL64(s[20], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[11] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008003UL; + + /* Round 16. */ + /* Col Mix */ + b[0] = s[0] ^ s[8] ^ s[11] ^ s[19] ^ s[22]; + b[1] = s[2] ^ s[5] ^ s[13] ^ s[16] ^ s[24]; + b[2] = s[4] ^ s[7] ^ s[10] ^ s[18] ^ s[21]; + b[3] = s[1] ^ s[9] ^ s[12] ^ s[15] ^ s[23]; + b[4] = s[3] ^ s[6] ^ s[14] ^ s[17] ^ s[20]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[8]^=t; s[11]^=t; s[19]^=t; s[22]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[5]^=t; s[13]^=t; s[16]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[7]^=t; s[10]^=t; s[18]^=t; s[21]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[9]^=t; s[12]^=t; s[15]^=t; s[23]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[6]^=t; s[14]^=t; s[17]^=t; s[20]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[5], 44); + b[2] = ROTL64(s[10], 43); + b[3] = ROTL64(s[15], 21); + b[4] = ROTL64(s[20], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[23], 28); + b[1] = ROTL64(s[3], 20); + b[2] = ROTL64(s[8], 3); + b[3] = ROTL64(s[13], 45); + b[4] = ROTL64(s[18], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[23] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[16], 1); + b[1] = ROTL64(s[21], 6); + b[2] = ROTL64(s[1], 25); + b[3] = ROTL64(s[6], 8); + b[4] = ROTL64(s[11], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[16] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[14], 27); + b[1] = ROTL64(s[19], 36); + b[2] = ROTL64(s[24], 10); + b[3] = ROTL64(s[4], 15); + b[4] = ROTL64(s[9], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[14] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[7], 62); + b[1] = ROTL64(s[12], 55); + b[2] = ROTL64(s[17], 39); + b[3] = ROTL64(s[22], 41); + b[4] = ROTL64(s[2], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[7] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008002UL; + + /* Round 17. */ + /* Col Mix */ + b[0] = s[0] ^ s[7] ^ s[14] ^ s[16] ^ s[23]; + b[1] = s[3] ^ s[5] ^ s[12] ^ s[19] ^ s[21]; + b[2] = s[1] ^ s[8] ^ s[10] ^ s[17] ^ s[24]; + b[3] = s[4] ^ s[6] ^ s[13] ^ s[15] ^ s[22]; + b[4] = s[2] ^ s[9] ^ s[11] ^ s[18] ^ s[20]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[7]^=t; s[14]^=t; s[16]^=t; s[23]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[5]^=t; s[12]^=t; s[19]^=t; s[21]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[8]^=t; s[10]^=t; s[17]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[6]^=t; s[13]^=t; s[15]^=t; s[22]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[9]^=t; s[11]^=t; s[18]^=t; s[20]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[3], 44); + b[2] = ROTL64(s[1], 43); + b[3] = ROTL64(s[4], 21); + b[4] = ROTL64(s[2], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[15], 28); + b[1] = ROTL64(s[18], 20); + b[2] = ROTL64(s[16], 3); + b[3] = ROTL64(s[19], 45); + b[4] = ROTL64(s[17], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[15] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[5], 1); + b[1] = ROTL64(s[8], 6); + b[2] = ROTL64(s[6], 25); + b[3] = ROTL64(s[9], 8); + b[4] = ROTL64(s[7], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[5] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[20], 27); + b[1] = ROTL64(s[23], 36); + b[2] = ROTL64(s[21], 10); + b[3] = ROTL64(s[24], 15); + b[4] = ROTL64(s[22], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[20] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[10], 62); + b[1] = ROTL64(s[13], 55); + b[2] = ROTL64(s[11], 39); + b[3] = ROTL64(s[14], 41); + b[4] = ROTL64(s[12], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[10] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000000080UL; + + /* Round 18. */ + /* Col Mix */ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + b[1] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + b[2] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + b[3] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + b[4] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[5]^=t; s[10]^=t; s[15]^=t; s[20]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[8]^=t; s[13]^=t; s[18]^=t; s[23]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[6]^=t; s[11]^=t; s[16]^=t; s[21]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[9]^=t; s[14]^=t; s[19]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[7]^=t; s[12]^=t; s[17]^=t; s[22]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[18], 44); + b[2] = ROTL64(s[6], 43); + b[3] = ROTL64(s[24], 21); + b[4] = ROTL64(s[12], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[4], 28); + b[1] = ROTL64(s[17], 20); + b[2] = ROTL64(s[5], 3); + b[3] = ROTL64(s[23], 45); + b[4] = ROTL64(s[11], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[4] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[3], 1); + b[1] = ROTL64(s[16], 6); + b[2] = ROTL64(s[9], 25); + b[3] = ROTL64(s[22], 8); + b[4] = ROTL64(s[10], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[3] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[2], 27); + b[1] = ROTL64(s[15], 36); + b[2] = ROTL64(s[8], 10); + b[3] = ROTL64(s[21], 15); + b[4] = ROTL64(s[14], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[2] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[1], 62); + b[1] = ROTL64(s[19], 55); + b[2] = ROTL64(s[7], 39); + b[3] = ROTL64(s[20], 41); + b[4] = ROTL64(s[13], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[1] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x800aUL; + + /* Round 19. */ + /* Col Mix */ + b[0] = s[0] ^ s[1] ^ s[2] ^ s[3] ^ s[4]; + b[1] = s[15] ^ s[16] ^ s[17] ^ s[18] ^ s[19]; + b[2] = s[5] ^ s[6] ^ s[7] ^ s[8] ^ s[9]; + b[3] = s[20] ^ s[21] ^ s[22] ^ s[23] ^ s[24]; + b[4] = s[10] ^ s[11] ^ s[12] ^ s[13] ^ s[14]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[1]^=t; s[2]^=t; s[3]^=t; s[4]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[15]^=t; s[16]^=t; s[17]^=t; s[18]^=t; s[19]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[5]^=t; s[6]^=t; s[7]^=t; s[8]^=t; s[9]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[20]^=t; s[21]^=t; s[22]^=t; s[23]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[10]^=t; s[11]^=t; s[12]^=t; s[13]^=t; s[14]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[17], 44); + b[2] = ROTL64(s[9], 43); + b[3] = ROTL64(s[21], 21); + b[4] = ROTL64(s[13], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[24], 28); + b[1] = ROTL64(s[11], 20); + b[2] = ROTL64(s[3], 3); + b[3] = ROTL64(s[15], 45); + b[4] = ROTL64(s[7], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[24] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[18], 1); + b[1] = ROTL64(s[5], 6); + b[2] = ROTL64(s[22], 25); + b[3] = ROTL64(s[14], 8); + b[4] = ROTL64(s[1], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[18] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[12], 27); + b[1] = ROTL64(s[4], 36); + b[2] = ROTL64(s[16], 10); + b[3] = ROTL64(s[8], 15); + b[4] = ROTL64(s[20], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[12] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[6], 62); + b[1] = ROTL64(s[23], 55); + b[2] = ROTL64(s[10], 39); + b[3] = ROTL64(s[2], 41); + b[4] = ROTL64(s[19], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[6] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x800000008000000aUL; + + /* Round 20. */ + /* Col Mix */ + b[0] = s[0] ^ s[6] ^ s[12] ^ s[18] ^ s[24]; + b[1] = s[4] ^ s[5] ^ s[11] ^ s[17] ^ s[23]; + b[2] = s[3] ^ s[9] ^ s[10] ^ s[16] ^ s[22]; + b[3] = s[2] ^ s[8] ^ s[14] ^ s[15] ^ s[21]; + b[4] = s[1] ^ s[7] ^ s[13] ^ s[19] ^ s[20]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[6]^=t; s[12]^=t; s[18]^=t; s[24]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[5]^=t; s[11]^=t; s[17]^=t; s[23]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[9]^=t; s[10]^=t; s[16]^=t; s[22]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[8]^=t; s[14]^=t; s[15]^=t; s[21]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[7]^=t; s[13]^=t; s[19]^=t; s[20]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[11], 44); + b[2] = ROTL64(s[22], 43); + b[3] = ROTL64(s[8], 21); + b[4] = ROTL64(s[19], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[21], 28); + b[1] = ROTL64(s[7], 20); + b[2] = ROTL64(s[18], 3); + b[3] = ROTL64(s[4], 45); + b[4] = ROTL64(s[10], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[21] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[17], 1); + b[1] = ROTL64(s[3], 6); + b[2] = ROTL64(s[14], 25); + b[3] = ROTL64(s[20], 8); + b[4] = ROTL64(s[6], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[17] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[13], 27); + b[1] = ROTL64(s[24], 36); + b[2] = ROTL64(s[5], 10); + b[3] = ROTL64(s[16], 15); + b[4] = ROTL64(s[2], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[13] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[9], 62); + b[1] = ROTL64(s[15], 55); + b[2] = ROTL64(s[1], 39); + b[3] = ROTL64(s[12], 41); + b[4] = ROTL64(s[23], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[9] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000080008081UL; + + /* Round 21. */ + /* Col Mix */ + b[0] = s[0] ^ s[9] ^ s[13] ^ s[17] ^ s[21]; + b[1] = s[3] ^ s[7] ^ s[11] ^ s[15] ^ s[24]; + b[2] = s[1] ^ s[5] ^ s[14] ^ s[18] ^ s[22]; + b[3] = s[4] ^ s[8] ^ s[12] ^ s[16] ^ s[20]; + b[4] = s[2] ^ s[6] ^ s[10] ^ s[19] ^ s[23]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[9]^=t; s[13]^=t; s[17]^=t; s[21]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[7]^=t; s[11]^=t; s[15]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[5]^=t; s[14]^=t; s[18]^=t; s[22]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[8]^=t; s[12]^=t; s[16]^=t; s[20]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[6]^=t; s[10]^=t; s[19]^=t; s[23]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[7], 44); + b[2] = ROTL64(s[14], 43); + b[3] = ROTL64(s[16], 21); + b[4] = ROTL64(s[23], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[8], 28); + b[1] = ROTL64(s[10], 20); + b[2] = ROTL64(s[17], 3); + b[3] = ROTL64(s[24], 45); + b[4] = ROTL64(s[1], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[8] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[11], 1); + b[1] = ROTL64(s[18], 6); + b[2] = ROTL64(s[20], 25); + b[3] = ROTL64(s[2], 8); + b[4] = ROTL64(s[9], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[11] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[19], 27); + b[1] = ROTL64(s[21], 36); + b[2] = ROTL64(s[3], 10); + b[3] = ROTL64(s[5], 15); + b[4] = ROTL64(s[12], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[19] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[22], 62); + b[1] = ROTL64(s[4], 55); + b[2] = ROTL64(s[6], 39); + b[3] = ROTL64(s[13], 41); + b[4] = ROTL64(s[15], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[22] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008080UL; + + /* Round 22. */ + /* Col Mix */ + b[0] = s[0] ^ s[8] ^ s[11] ^ s[19] ^ s[22]; + b[1] = s[4] ^ s[7] ^ s[10] ^ s[18] ^ s[21]; + b[2] = s[3] ^ s[6] ^ s[14] ^ s[17] ^ s[20]; + b[3] = s[2] ^ s[5] ^ s[13] ^ s[16] ^ s[24]; + b[4] = s[1] ^ s[9] ^ s[12] ^ s[15] ^ s[23]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[8]^=t; s[11]^=t; s[19]^=t; s[22]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[7]^=t; s[10]^=t; s[18]^=t; s[21]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[6]^=t; s[14]^=t; s[17]^=t; s[20]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[5]^=t; s[13]^=t; s[16]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[9]^=t; s[12]^=t; s[15]^=t; s[23]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[10], 44); + b[2] = ROTL64(s[20], 43); + b[3] = ROTL64(s[5], 21); + b[4] = ROTL64(s[15], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[16], 28); + b[1] = ROTL64(s[1], 20); + b[2] = ROTL64(s[11], 3); + b[3] = ROTL64(s[21], 45); + b[4] = ROTL64(s[6], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[16] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[7], 1); + b[1] = ROTL64(s[17], 6); + b[2] = ROTL64(s[2], 25); + b[3] = ROTL64(s[12], 8); + b[4] = ROTL64(s[22], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[7] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[23], 27); + b[1] = ROTL64(s[8], 36); + b[2] = ROTL64(s[18], 10); + b[3] = ROTL64(s[3], 15); + b[4] = ROTL64(s[13], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[23] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[14], 62); + b[1] = ROTL64(s[24], 55); + b[2] = ROTL64(s[9], 39); + b[3] = ROTL64(s[19], 41); + b[4] = ROTL64(s[4], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[14] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x80000001UL; + + /* Round 23. */ + /* Col Mix */ + b[0] = s[0] ^ s[7] ^ s[14] ^ s[16] ^ s[23]; + b[1] = s[1] ^ s[8] ^ s[10] ^ s[17] ^ s[24]; + b[2] = s[2] ^ s[9] ^ s[11] ^ s[18] ^ s[20]; + b[3] = s[3] ^ s[5] ^ s[12] ^ s[19] ^ s[21]; + b[4] = s[4] ^ s[6] ^ s[13] ^ s[15] ^ s[22]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[7]^=t; s[14]^=t; s[16]^=t; s[23]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[8]^=t; s[10]^=t; s[17]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[9]^=t; s[11]^=t; s[18]^=t; s[20]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[5]^=t; s[12]^=t; s[19]^=t; s[21]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[6]^=t; s[13]^=t; s[15]^=t; s[22]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[1], 44); + b[2] = ROTL64(s[2], 43); + b[3] = ROTL64(s[3], 21); + b[4] = ROTL64(s[4], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[5], 28); + b[1] = ROTL64(s[6], 20); + b[2] = ROTL64(s[7], 3); + b[3] = ROTL64(s[8], 45); + b[4] = ROTL64(s[9], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[5] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[10], 1); + b[1] = ROTL64(s[11], 6); + b[2] = ROTL64(s[12], 25); + b[3] = ROTL64(s[13], 8); + b[4] = ROTL64(s[14], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[10] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[15], 27); + b[1] = ROTL64(s[16], 36); + b[2] = ROTL64(s[17], 10); + b[3] = ROTL64(s[18], 15); + b[4] = ROTL64(s[19], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[15] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[20], 62); + b[1] = ROTL64(s[21], 55); + b[2] = ROTL64(s[22], 39); + b[3] = ROTL64(s[23], 41); + b[4] = ROTL64(s[24], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[20] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000080008008UL; +} + diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index db6ce9fbc..7739f4245 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -95,6 +95,9 @@ #ifdef HAVE_BLAKE2 #include #endif +#ifdef WOLFSSL_SHA3 + #include +#endif #ifdef HAVE_LIBZ #include #endif @@ -209,6 +212,7 @@ int sha224_test(void); int sha256_test(void); int sha512_test(void); int sha384_test(void); +int sha3_test(void); int hash_test(void); int hmac_md5_test(void); int hmac_sha_test(void); @@ -479,6 +483,13 @@ int wolfcrypt_test(void* args) printf( "SHA-512 test passed!\n"); #endif +#ifdef WOLFSSL_SHA3 + if ( (ret = sha3_test()) != 0) + return err_sys("SHA-3 test failed!\n", ret); + else + printf( "SHA-3 test passed!\n"); +#endif + if ( (ret = hash_test()) != 0) return err_sys("Hash test failed!\n", ret); else @@ -1760,6 +1771,245 @@ int sha384_test(void) } #endif /* WOLFSSL_SHA384 */ +#ifdef WOLFSSL_SHA3 +static int sha3_224_test(void) +{ + Sha3 sha; + byte hash[SHA3_224_DIGEST_SIZE]; + byte hashcopy[SHA3_224_DIGEST_SIZE]; + + testVector a, b; + testVector test_sha[2]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = "abc"; + a.output = "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76" + "\x6f\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_224_DIGEST_SIZE; + + b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + b.output = "\x8a\x24\x10\x8b\x15\x4a\xda\x21\xc9\xfd\x55\x74\x49\x44\x79" + "\xba\x5c\x7e\x7a\xb7\x6e\xf2\x64\xea\xd0\xfc\xce\x33"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_224_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + + ret = wc_InitSha3_224(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2000; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_224_Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + if (ret != 0) + return -2010 - i; + ret = wc_Sha3_224_GetHash(&sha, hashcopy); + if (ret != 0) + return -2020 - i; + ret = wc_Sha3_224_Final(&sha, hash); + if (ret != 0) + return -2030 - i; + + if (XMEMCMP(hash, test_sha[i].output, SHA3_224_DIGEST_SIZE) != 0) + return -2040 - i; + + if (XMEMCMP(hash, hashcopy, SHA3_224_DIGEST_SIZE) != 0) + return -2050 - i; + } + wc_Sha3_224_Free(&sha); + + return 0; +} + +static int sha3_256_test(void) +{ + Sha3 sha; + byte hash[SHA3_256_DIGEST_SIZE]; + byte hashcopy[SHA3_256_DIGEST_SIZE]; + + testVector a, b; + testVector test_sha[2]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = "abc"; + a.output = "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90" + "\xbd\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43" + "\x15\x32"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_256_DIGEST_SIZE; + + b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + b.output = "\x41\xc0\xdb\xa2\xa9\xd6\x24\x08\x49\x10\x03\x76\xa8\x23\x5e" + "\x2c\x82\xe1\xb9\x99\x8a\x99\x9e\x21\xdb\x32\xdd\x97\x49\x6d" + "\x33\x76"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_256_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + + ret = wc_InitSha3_256(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2100; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_256_Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + if (ret != 0) + return -2110 - i; + ret = wc_Sha3_256_GetHash(&sha, hashcopy); + if (ret != 0) + return -2120 - i; + ret = wc_Sha3_256_Final(&sha, hash); + if (ret != 0) + return -2130 - i; + + if (XMEMCMP(hash, test_sha[i].output, SHA3_256_DIGEST_SIZE) != 0) + return -2140 - i; + + if (XMEMCMP(hash, hashcopy, SHA3_256_DIGEST_SIZE) != 0) + return -2150 - i; + } + wc_Sha3_256_Free(&sha); + + return 0; +} + +static int sha3_384_test(void) +{ + Sha3 sha; + byte hash[SHA3_384_DIGEST_SIZE]; + byte hashcopy[SHA3_384_DIGEST_SIZE]; + + testVector a, b; + testVector test_sha[2]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = "abc"; + a.output = "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad" + "\x8d\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b" + "\xe4\xb2\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28" + "\x37\x6d\x25"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_384_DIGEST_SIZE; + + b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + b.output = "\x99\x1c\x66\x57\x55\xeb\x3a\x4b\x6b\xbd\xfb\x75\xc7\x8a\x49" + "\x2e\x8c\x56\xa2\x2c\x5c\x4d\x7e\x42\x9b\xfd\xbc\x32\xb9\xd4" + "\xad\x5a\xa0\x4a\x1f\x07\x6e\x62\xfe\xa1\x9e\xef\x51\xac\xd0" + "\x65\x7c\x22"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_384_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + + ret = wc_InitSha3_384(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2200; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_384_Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + if (ret != 0) + return -2210 - i; + ret = wc_Sha3_384_GetHash(&sha, hashcopy); + if (ret != 0) + return -2220 - i; + ret = wc_Sha3_384_Final(&sha, hash); + if (ret != 0) + return -2230 - i; + + if (XMEMCMP(hash, test_sha[i].output, SHA3_384_DIGEST_SIZE) != 0) + return -2240 - i; + + if (XMEMCMP(hash, hashcopy, SHA3_384_DIGEST_SIZE) != 0) + return -2250 - i; + } + wc_Sha3_384_Free(&sha); + + return 0; +} + +static int sha3_512_test(void) +{ + Sha3 sha; + byte hash[SHA3_512_DIGEST_SIZE]; + byte hashcopy[SHA3_512_DIGEST_SIZE]; + + testVector a, b; + testVector test_sha[2]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = "abc"; + a.output = "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09" + "\x6e\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2" + "\x71\x2e\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47" + "\xe3\x93\x40\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27" + "\x4e\xec\x53\xf0"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_512_DIGEST_SIZE; + + b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + b.output = "\x04\xa3\x71\xe8\x4e\xcf\xb5\xb8\xb7\x7c\xb4\x86\x10\xfc\xa8" + "\x18\x2d\xd4\x57\xce\x6f\x32\x6a\x0f\xd3\xd7\xec\x2f\x1e\x91" + "\x63\x6d\xee\x69\x1f\xbe\x0c\x98\x53\x02\xba\x1b\x0d\x8d\xc7" + "\x8c\x08\x63\x46\xb5\x33\xb4\x9c\x03\x0d\x99\xa2\x7d\xaf\x11" + "\x39\xd6\xe7\x5e"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_512_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + + ret = wc_InitSha3_512(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2300; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_512_Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + if (ret != 0) + return -2310 - i; + ret = wc_Sha3_512_GetHash(&sha, hashcopy); + if (ret != 0) + return -2320 - i; + ret = wc_Sha3_512_Final(&sha, hash); + if (ret != 0) + return -2330 - i; + + if (XMEMCMP(hash, test_sha[i].output, SHA3_512_DIGEST_SIZE) != 0) + return -2340 - i; + + if (XMEMCMP(hash, hashcopy, SHA3_512_DIGEST_SIZE) != 0) + return -2350 - i; + } + wc_Sha3_512_Free(&sha); + + return 0; +} + +int sha3_test(void) +{ + int ret; + + if ((ret = sha3_224_test()) != 0) + return ret; + if ((ret = sha3_256_test()) != 0) + return ret; + if ((ret = sha3_384_test()) != 0) + return ret; + if ((ret = sha3_512_test()) != 0) + return ret; + + return 0; +} +#endif + + int hash_test(void) { wc_HashAlg hash; diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 92307a2b8..66115c932 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -59,7 +59,8 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/mem_track.h \ wolfssl/wolfcrypt/wolfevent.h \ wolfssl/wolfcrypt/pkcs12.h \ - wolfssl/wolfcrypt/wolfmath.h + wolfssl/wolfcrypt/wolfmath.h \ + wolfssl/wolfcrypt/sha3.h noinst_HEADERS+= \ wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ diff --git a/wolfssl/wolfcrypt/sha3.h b/wolfssl/wolfcrypt/sha3.h new file mode 100644 index 000000000..09d1b161f --- /dev/null +++ b/wolfssl/wolfcrypt/sha3.h @@ -0,0 +1,119 @@ +/* sha3.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* code submitted by raphael.huck@efixo.com */ + +#ifndef WOLF_CRYPT_SHA3_H +#define WOLF_CRYPT_SHA3_H + +#include + +#ifdef WOLFSSL_SHA3 + +#ifdef HAVE_FIPS + /* for fips @wc_fips */ + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefinition of structs */ + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +/* in bytes */ +enum { + SHA3_224 = 10, /* hash type unique */ + SHA3_224_DIGEST_SIZE = 28, + SHA3_224_COUNT = 18, + + SHA3_256 = 11, /* hash type unique */ + SHA3_256_DIGEST_SIZE = 32, + SHA3_256_COUNT = 17, + + SHA3_384 = 12, /* hash type unique */ + SHA3_384_DIGEST_SIZE = 48, + SHA3_384_COUNT = 13, + + SHA3_512 = 13, /* hash type unique */ + SHA3_512_DIGEST_SIZE = 64, + SHA3_512_COUNT = 9 +}; + + +/* Sha3 digest */ +typedef struct Sha3 { + /* State data that is processed for each block. */ + word64 s[25]; + /* Unprocessed message data. */ + byte t[200]; + /* Index into unprocessed data to place next message byte. */ + byte i; + + void* heap; + +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +} Sha3; + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha3_224(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_224_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_224_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_224_Free(Sha3*); +WOLFSSL_API int wc_Sha3_224_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_224_Copy(Sha3* src, Sha3* dst); + +WOLFSSL_API int wc_InitSha3_256(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_256_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_256_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_256_Free(Sha3*); +WOLFSSL_API int wc_Sha3_256_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_256_Copy(Sha3* src, Sha3* dst); + +WOLFSSL_API int wc_InitSha3_384(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_384_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_384_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_384_Free(Sha3*); +WOLFSSL_API int wc_Sha3_384_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_384_Copy(Sha3* src, Sha3* dst); + +WOLFSSL_API int wc_InitSha3_512(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_512_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_512_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_512_Free(Sha3*); +WOLFSSL_API int wc_Sha3_512_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_512_Copy(Sha3* src, Sha3* dst); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_SHA3 */ +#endif /* WOLF_CRYPT_SHA3_H */ +