diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c index 74375640f..dacbc0df6 100644 --- a/wolfcrypt/src/sha3.c +++ b/wolfcrypt/src/sha3.c @@ -636,30 +636,47 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) * len Number of bytes in output. * returns 0 on success. */ -static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, byte l) +static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l) { +#if defined(BIG_ENDIAN_ORDER) + word32 q = (l + 7) / 8; +#endif + word32 k, rate = p * 8; byte i; byte *state = (byte *)sha3->s; - sha3->t[p * 8 - 1] = 0x00; + sha3->t[rate - 1] = 0x00; #ifdef WOLFSSL_HASH_FLAGS if (p == WC_SHA3_256_COUNT && sha3->flags & WC_HASH_SHA3_KECCAK256) { padChar = 0x01; } #endif sha3->t[ sha3->i] = padChar; - sha3->t[p * 8 - 1] |= 0x80; - for (i=sha3->i + 1; i < p * 8 - 1; i++) + sha3->t[rate - 1] |= 0x80; + for (i=sha3->i + 1; i < rate - 1; i++) sha3->t[i] = 0; for (i = 0; i < p; i++) sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); BlockSha3(sha3->s); #if defined(BIG_ENDIAN_ORDER) - ByteReverseWords64(sha3->s, sha3->s, ((l+7)/8)*8); + ByteReverseWords64(sha3->s, sha3->s, (q > p) ? rate : q * 8); #endif - for (i = 0; i < l; i++) - hash[i] = state[i]; - + i = 0; + for (k = 0; k < l; k++) + { + if (i == rate) + { + i = 0; +#if defined(BIG_ENDIAN_ORDER) + ByteReverseWords64(sha3->s, sha3->s, rate); + BlockSha3(sha3->s); + ByteReverseWords64(sha3->s, sha3->s, rate); +#else + BlockSha3(sha3->s); +#endif + } + hash[k] = state[i++]; + } return 0; } @@ -763,7 +780,7 @@ static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len) } #endif /* WOLFSSL_ASYNC_CRYPT */ - ret = Sha3Final(sha3, 0x06, hash, p, len); + ret = Sha3Final(sha3, 0x06, hash, p, (word32)len); if (ret != 0) return ret; @@ -1193,7 +1210,7 @@ int wc_Shake256_Final(wc_Shake* shake, byte* hash, word32 hashLen) return BAD_FUNC_ARG; } - ret = Sha3Final(shake, 0x1f, hash, WC_SHA3_256_COUNT, (byte)hashLen); + ret = Sha3Final(shake, 0x1f, hash, WC_SHA3_256_COUNT, hashLen); if (ret != 0) return ret;