sha: octet-correct SHA-1/SHA-2 byte I/O and 32-bit split Keccak permutation for CHAR_BIT != 8

This commit is contained in:
David Garske
2026-08-06 16:55:52 -07:00
parent b6be0c878d
commit 5371237eb8
4 changed files with 351 additions and 17 deletions
+48 -3
View File
@@ -698,7 +698,14 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
if (esp_sha_need_byte_reversal(&sha->ctx))
#endif
{
#ifdef WOLFSSL_WIDE_BYTE
/* CHAR_BIT != 8: pack the 16 big-endian schedule words
* octet-wise rather than reversing whole cells. */
WordsFromBytesBE32(sha->buffer, (const byte*)sha->buffer,
WC_SHA_BLOCK_SIZE / 4);
#else
ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
#endif
}
#endif
@@ -782,7 +789,12 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
if (esp_sha_need_byte_reversal(&sha->ctx))
#endif
{
#ifdef WOLFSSL_WIDE_BYTE
WordsFromBytesBE32(local32, (const byte*)local32,
WC_SHA_BLOCK_SIZE / 4);
#else
ByteReverseWords(local32, local32, WC_SHA_BLOCK_SIZE);
#endif
}
#endif
@@ -819,7 +831,11 @@ int wc_ShaFinalRaw(wc_Sha* sha, byte* hash)
return BAD_FUNC_ARG;
}
#ifdef LITTLE_ENDIAN_ORDER
#if defined(WOLFSSL_WIDE_BYTE)
/* CHAR_BIT != 8: write the digest words as big-endian octets. */
BytesFromWordsBE32(hash, sha->digest, WC_SHA_DIGEST_SIZE);
(void)digest;
#elif defined(LITTLE_ENDIAN_ORDER)
#if ( defined(CONFIG_IDF_TARGET_ESP32C2) || \
defined(CONFIG_IDF_TARGET_ESP8684) || \
defined(CONFIG_IDF_TARGET_ESP32C3) || \
@@ -910,7 +926,12 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
if (esp_sha_need_byte_reversal(&sha->ctx))
#endif
{
#ifdef WOLFSSL_WIDE_BYTE
WordsFromBytesBE32(sha->buffer, (const byte*)sha->buffer,
WC_SHA_BLOCK_SIZE / 4);
#else
ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
#endif
}
#endif
@@ -944,7 +965,10 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
}
#endif
#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
/* WOLFSSL_WIDE_BYTE packs the whole final block (including the length
* words) octet-wise below, so skip the in-place word reversal here. */
#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) && \
!defined(WOLFSSL_WIDE_BYTE)
#if ( defined(CONFIG_IDF_TARGET_ESP32C2) || \
defined(CONFIG_IDF_TARGET_ESP8684) || \
defined(CONFIG_IDF_TARGET_ESP32C3) || \
@@ -963,12 +987,28 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
/* store lengths */
/* put lengths in bits */
sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + (sha->hiLen << 3);
sha->hiLen = (sha->loLen >> (CHAR_BIT*sizeof(sha->loLen) - 3)) +
(sha->hiLen << 3);
sha->loLen = sha->loLen << 3;
/* ! length ordering dependent on digest endian type ! */
#ifdef WOLFSSL_WIDE_BYTE
/* CHAR_BIT != 8: place the 64-bit length as 8 big-endian octets, then pack
* all 16 big-endian schedule words octet-wise (covers the length words). */
local[WC_SHA_PAD_SIZE + 0] = (byte)((sha->hiLen >> 24) & 0xFF);
local[WC_SHA_PAD_SIZE + 1] = (byte)((sha->hiLen >> 16) & 0xFF);
local[WC_SHA_PAD_SIZE + 2] = (byte)((sha->hiLen >> 8) & 0xFF);
local[WC_SHA_PAD_SIZE + 3] = (byte)((sha->hiLen ) & 0xFF);
local[WC_SHA_PAD_SIZE + 4] = (byte)((sha->loLen >> 24) & 0xFF);
local[WC_SHA_PAD_SIZE + 5] = (byte)((sha->loLen >> 16) & 0xFF);
local[WC_SHA_PAD_SIZE + 6] = (byte)((sha->loLen >> 8) & 0xFF);
local[WC_SHA_PAD_SIZE + 7] = (byte)((sha->loLen ) & 0xFF);
WordsFromBytesBE32(sha->buffer, (const byte*)sha->buffer,
WC_SHA_BLOCK_SIZE / 4);
#else
XMEMCPY(&local[WC_SHA_PAD_SIZE], &sha->hiLen, sizeof(word32));
XMEMCPY(&local[WC_SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32));
#endif
#if defined(FREESCALE_MMCAU_SHA)
/* Kinetis requires only these bytes reversed */
@@ -1017,6 +1057,10 @@ if (sha->ctx.mode == ESP32_SHA_HW) {
ret = XTRANSFORM(sha, (const byte*)local);
#endif
#if defined(WOLFSSL_WIDE_BYTE)
/* CHAR_BIT != 8: write the digest words as big-endian octets. */
BytesFromWordsBE32(hash, sha->digest, WC_SHA_DIGEST_SIZE);
#else
#ifdef LITTLE_ENDIAN_ORDER
#if ( defined(CONFIG_IDF_TARGET_ESP32C2) || \
defined(CONFIG_IDF_TARGET_ESP8684) || \
@@ -1034,6 +1078,7 @@ if (sha->ctx.mode == ESP32_SHA_HW) {
#endif
XMEMCPY(hash, (byte *)&sha->digest[0], WC_SHA_DIGEST_SIZE);
#endif
/* we'll always reset state upon exit and return the error code from above,
* which may cause fall back to SW if HW is busy. we do not return result
+54 -4
View File
@@ -233,7 +233,7 @@ on the specific device platform.
#endif
#endif
#ifndef SHA256_REV_BYTES
#if defined(LITTLE_ENDIAN_ORDER)
#if defined(LITTLE_ENDIAN_ORDER) || defined(WOLFSSL_WIDE_BYTE)
#define SHA256_REV_BYTES(ctx) 1
#else
#define SHA256_REV_BYTES(ctx) 0
@@ -281,7 +281,6 @@ on the specific device platform.
#define SHA256_UPDATE_REV_BYTES(ctx) SHA256_REV_BYTES(ctx)
#endif
#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \
(!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH) || \
defined(WOLFSSL_QNX_CAAM)) && \
@@ -1893,8 +1892,14 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
#endif
if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) {
#ifdef WOLFSSL_WIDE_BYTE
/* CHAR_BIT != 8: pack 16 big-endian schedule words octet-wise */
WordsFromBytesBE32(sha256->buffer, (const byte*)sha256->buffer,
WC_SHA256_BLOCK_SIZE / 4);
#else
ByteReverseWords(sha256->buffer, sha256->buffer,
WC_SHA256_BLOCK_SIZE);
#endif
}
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
@@ -1997,7 +2002,12 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
#endif
if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) {
#ifdef WOLFSSL_WIDE_BYTE
WordsFromBytesBE32(local32, (const byte*)local32,
WC_SHA256_BLOCK_SIZE / 4);
#else
ByteReverseWords(local32, local32, WC_SHA256_BLOCK_SIZE);
#endif
}
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
@@ -2099,8 +2109,13 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
#endif
if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) {
#ifdef WOLFSSL_WIDE_BYTE
WordsFromBytesBE32(sha256->buffer, (const byte*)sha256->buffer,
WC_SHA256_BLOCK_SIZE / 4);
#else
ByteReverseWords(sha256->buffer, sha256->buffer,
WC_SHA256_BLOCK_SIZE);
#endif
}
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
@@ -2126,7 +2141,8 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
WC_SHA256_PAD_SIZE - sha256->buffLen);
/* put 64 bit length in separate 32 bit parts */
sha256->hiLen = (sha256->loLen >> (8 * sizeof(sha256->loLen) - 3)) +
sha256->hiLen = (sha256->loLen >>
(CHAR_BIT * sizeof(sha256->loLen) - 3)) +
(sha256->hiLen << 3);
sha256->loLen = sha256->loLen << 3;
@@ -2138,14 +2154,34 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
#endif
/* store lengths */
#ifdef WOLFSSL_WIDE_BYTE
/* CHAR_BIT != 8: 'local' indexes octet cells, so place the 64-bit
* bit-length as 8 big-endian octets (W[14]=hiLen, W[15]=loLen). */
local[WC_SHA256_PAD_SIZE + 0] = (byte)((sha256->hiLen >> 24) & 0xFF);
local[WC_SHA256_PAD_SIZE + 1] = (byte)((sha256->hiLen >> 16) & 0xFF);
local[WC_SHA256_PAD_SIZE + 2] = (byte)((sha256->hiLen >> 8) & 0xFF);
local[WC_SHA256_PAD_SIZE + 3] = (byte)((sha256->hiLen ) & 0xFF);
local[WC_SHA256_PAD_SIZE + 4] = (byte)((sha256->loLen >> 24) & 0xFF);
local[WC_SHA256_PAD_SIZE + 5] = (byte)((sha256->loLen >> 16) & 0xFF);
local[WC_SHA256_PAD_SIZE + 6] = (byte)((sha256->loLen >> 8) & 0xFF);
local[WC_SHA256_PAD_SIZE + 7] = (byte)((sha256->loLen ) & 0xFF);
#endif
if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) {
#ifdef WOLFSSL_WIDE_BYTE
/* pack all 16 big-endian schedule words octet-wise (incl. length) */
WordsFromBytesBE32(sha256->buffer, (const byte*)sha256->buffer,
WC_SHA256_BLOCK_SIZE / 4);
#else
ByteReverseWords(sha256->buffer, sha256->buffer,
WC_SHA256_PAD_SIZE);
#endif
}
#ifndef WOLFSSL_WIDE_BYTE
/* ! 64-bit length ordering dependent on digest endian type ! */
XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));
XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,
sizeof(word32));
#endif
/* Only the ESP32-C3 with HW enabled may need pad size byte order reversal
* depending on HW or SW mode */
@@ -2246,7 +2282,11 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
return BAD_FUNC_ARG;
}
#ifdef LITTLE_ENDIAN_ORDER
#if defined(WOLFSSL_WIDE_BYTE)
/* CHAR_BIT != 8: store digest words as big-endian octets. */
BytesFromWordsBE32(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
(void)digest;
#elif defined(LITTLE_ENDIAN_ORDER)
if (SHA256_REV_BYTES(&sha256->ctx)) {
ByteReverseWords((word32*)digest, (word32*)sha256->digest,
WC_SHA256_DIGEST_SIZE);
@@ -2294,6 +2334,10 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
return ret;
}
#if defined(WOLFSSL_WIDE_BYTE)
/* CHAR_BIT != 8: store digest words as big-endian octets. */
BytesFromWordsBE32(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
#else
#if defined(LITTLE_ENDIAN_ORDER)
if (SHA256_REV_BYTES(&sha256->ctx)) {
ByteReverseWords(sha256->digest, sha256->digest,
@@ -2301,6 +2345,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
}
#endif
XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
#endif
return InitSha256(sha256); /* reset state */
}
@@ -2835,6 +2880,10 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
if (ret != 0)
return ret;
#if defined(WOLFSSL_WIDE_BYTE)
/* CHAR_BIT != 8: store digest words as big-endian octets. */
BytesFromWordsBE32(hash, sha224->digest, WC_SHA224_DIGEST_SIZE);
#else
#if defined(LITTLE_ENDIAN_ORDER)
if (SHA256_REV_BYTES(&sha224->ctx)) {
ByteReverseWords(sha224->digest,
@@ -2843,6 +2892,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
}
#endif
XMEMCPY(hash, sha224->digest, WC_SHA224_DIGEST_SIZE);
#endif
return InitSha224(sha224); /* reset state */
}
+189 -6
View File
@@ -30,6 +30,12 @@
* SHA3_BY_SPEC: Use specification Keccak-f order default: off
* WC_SHA3_NO_ASM: Disable SHA-3 assembly optimizations default: off
* WC_SHA3_FAULT_HARDEN: Harden SHA-3 against fault attacks default: off
* WC_SHA3_SPLIT64: Run the Keccak permutation on 32-bit halves of each
* 64-bit lane so a compiler that lowers 64-bit bitwise
* ops to out-of-line helper calls (e.g. cl2000 on TI
* C28x) emits native 32-bit ops instead. Auto-enabled
* for little-endian WC_16BIT_CPU; the default
* permutation is otherwise unchanged. default: off
*
* Hardware Acceleration (SHA-3-specific):
* WC_ASYNC_ENABLE_SHA3: Enable async SHA-3 operations default: off
@@ -604,6 +610,153 @@ while (0)
*
* s The state.
*/
/* WC_16BIT_CPU (e.g. TI C28x) lowers every 64-bit ^, | and & to an out-of-line
* runtime-helper call (cl2000: __c28xabi_xorll / _orll / _andll), which
* dominates the Keccak permutation. Auto-select a BlockSha3 that runs on
* 32-bit halves so the compiler emits native 32-bit ops; external state stays
* word64 s[25]. Auto-enabled only for WOLFSSL_WIDE_BYTE (the hardware-validated
* targets); other little-endian 16-bit ports keep the long-tested generic
* permutation but can opt in by defining WC_SHA3_SPLIT64. Little-endian word
* layout assumed (lo half first). */
#if !defined(WC_SHA3_SPLIT64) && defined(WOLFSSL_WIDE_BYTE) && \
!defined(BIG_ENDIAN_ORDER)
#define WC_SHA3_SPLIT64
#endif
#ifdef WC_SHA3_SPLIT64
/* Rotate the 64-bit value (sl=low, sh=high) left by compile-time constant r in
* 1..63, r != 32, into (dl, dh). r is always a Keccak rho offset (never 0 or
* 32; r==32 would need a plain half-swap), so that case never occurs. The & 31
* keeps the shift count in range in the dead (compile-time-eliminated) branch
* so there is no undefined shift. */
#define WC_SHA3_RL(dl, dh, sl, sh, r) \
do { \
word32 _l = (sl), _h = (sh); \
if ((r) < 32) { \
(dl) = (word32)((_l << ((r) & 31)) | (_h >> ((32 - (r)) & 31))); \
(dh) = (word32)((_h << ((r) & 31)) | (_l >> ((32 - (r)) & 31))); \
} \
else { \
(dl) = (word32)((_h << (((r) - 32) & 31)) | \
(_l >> ((64 - (r)) & 31))); \
(dh) = (word32)((_l << (((r) - 32) & 31)) | \
(_h >> ((64 - (r)) & 31))); \
} \
} while (0)
/* Chi over the rotated row held in bl[0..4]/bh[0..4], writing five output lanes
* at (DL,DH)[k..k+4]. a ^ (~b & c) == (a ^ b) ^ (b | c) per half. */
#define WC_SHA3_CHI(DL, DH, k) \
do { \
word32 al = bl[1] ^ bl[2], ah = bh[1] ^ bh[2]; \
word32 cl = bl[3] ^ bl[4], ch = bh[3] ^ bh[4]; \
(DL)[(k)+0] = bl[0] ^ (bl[2] & al); \
(DH)[(k)+0] = bh[0] ^ (bh[2] & ah); \
(DL)[(k)+1] = al ^ (bl[2] | bl[3]); \
(DH)[(k)+1] = ah ^ (bh[2] | bh[3]); \
(DL)[(k)+2] = bl[2] ^ (bl[4] & cl); \
(DH)[(k)+2] = bh[2] ^ (bh[4] & ch); \
(DL)[(k)+3] = cl ^ (bl[4] | bl[0]); \
(DH)[(k)+3] = ch ^ (bh[4] | bh[0]); \
(DL)[(k)+4] = bl[4] ^ (bl[1] & (bl[0] ^ bl[1])); \
(DH)[(k)+4] = bh[4] ^ (bh[1] & (bh[0] ^ bh[1])); \
} while (0)
/* Theta: mix the column parities into split state L (low) / H (high). */
#define WC_SHA3_THETA(L, H) \
do { \
int c; \
for (c = 0; c < 5; c++) { \
bl[c] = (L)[c]^(L)[c+5]^(L)[c+10]^(L)[c+15]^(L)[c+20]; \
bh[c] = (H)[c]^(H)[c+5]^(H)[c+10]^(H)[c+15]^(H)[c+20]; \
} \
for (c = 0; c < 5; c++) { \
int d = (c + 1) % 5, e = (c + 4) % 5; \
word32 xl = bl[e] ^ (word32)((bl[d] << 1) | (bh[d] >> 31)); \
word32 xh = bh[e] ^ (word32)((bh[d] << 1) | (bl[d] >> 31)); \
(L)[c] ^= xl; (H)[c] ^= xh; (L)[c+5] ^= xl; (H)[c+5] ^= xh; \
(L)[c+10]^= xl; (H)[c+10]^= xh; (L)[c+15] ^= xl; (H)[c+15] ^= xh; \
(L)[c+20]^= xl; (H)[c+20]^= xh; \
} \
} while (0)
/* Rho + pi + chi: rotate/permute split state SL/SH into DL/DH. */
#define WC_SHA3_ROWMIX(DL, DH, SL, SH) \
do { \
bl[0] = (SL)[0]; bh[0] = (SH)[0]; \
WC_SHA3_RL(bl[1],bh[1], (SL)[KI_0], (SH)[KI_0], KR_0); \
WC_SHA3_RL(bl[2],bh[2], (SL)[KI_1], (SH)[KI_1], KR_1); \
WC_SHA3_RL(bl[3],bh[3], (SL)[KI_2], (SH)[KI_2], KR_2); \
WC_SHA3_RL(bl[4],bh[4], (SL)[KI_3], (SH)[KI_3], KR_3); \
WC_SHA3_CHI(DL, DH, 0); \
WC_SHA3_RL(bl[0],bh[0], (SL)[KI_4], (SH)[KI_4], KR_4); \
WC_SHA3_RL(bl[1],bh[1], (SL)[KI_5], (SH)[KI_5], KR_5); \
WC_SHA3_RL(bl[2],bh[2], (SL)[KI_6], (SH)[KI_6], KR_6); \
WC_SHA3_RL(bl[3],bh[3], (SL)[KI_7], (SH)[KI_7], KR_7); \
WC_SHA3_RL(bl[4],bh[4], (SL)[KI_8], (SH)[KI_8], KR_8); \
WC_SHA3_CHI(DL, DH, 5); \
WC_SHA3_RL(bl[0],bh[0], (SL)[KI_9], (SH)[KI_9], KR_9); \
WC_SHA3_RL(bl[1],bh[1], (SL)[KI_10],(SH)[KI_10], KR_10); \
WC_SHA3_RL(bl[2],bh[2], (SL)[KI_11],(SH)[KI_11], KR_11); \
WC_SHA3_RL(bl[3],bh[3], (SL)[KI_12],(SH)[KI_12], KR_12); \
WC_SHA3_RL(bl[4],bh[4], (SL)[KI_13],(SH)[KI_13], KR_13); \
WC_SHA3_CHI(DL, DH, 10); \
WC_SHA3_RL(bl[0],bh[0], (SL)[KI_14],(SH)[KI_14], KR_14); \
WC_SHA3_RL(bl[1],bh[1], (SL)[KI_15],(SH)[KI_15], KR_15); \
WC_SHA3_RL(bl[2],bh[2], (SL)[KI_16],(SH)[KI_16], KR_16); \
WC_SHA3_RL(bl[3],bh[3], (SL)[KI_17],(SH)[KI_17], KR_17); \
WC_SHA3_RL(bl[4],bh[4], (SL)[KI_18],(SH)[KI_18], KR_18); \
WC_SHA3_CHI(DL, DH, 15); \
WC_SHA3_RL(bl[0],bh[0], (SL)[KI_19],(SH)[KI_19], KR_19); \
WC_SHA3_RL(bl[1],bh[1], (SL)[KI_20],(SH)[KI_20], KR_20); \
WC_SHA3_RL(bl[2],bh[2], (SL)[KI_21],(SH)[KI_21], KR_21); \
WC_SHA3_RL(bl[3],bh[3], (SL)[KI_22],(SH)[KI_22], KR_22); \
WC_SHA3_RL(bl[4],bh[4], (SL)[KI_23],(SH)[KI_23], KR_23); \
WC_SHA3_CHI(DL, DH, 20); \
} while (0)
void BlockSha3(word64* s)
{
/* Process the 25 little-endian lanes as 32-bit halves to avoid 64-bit
* helper calls. XMEMCPY in/out (aliasing s through word32* is strict-
* aliasing UB); st[2k] is lane k's low half, st[2k+1] the high half.
* Round constants are split with shifts for the same reason. */
word32 st[50];
word32 sl[25], sh[25], nl[25], nh[25], bl[5], bh[5];
word32 i, k;
word64 rc;
XMEMCPY(st, s, sizeof(st));
for (k = 0; k < 25; k++) {
sl[k] = st[2 * k];
sh[k] = st[2 * k + 1];
}
for (i = 0; i < 24; i += 2) {
WC_SHA3_THETA(sl, sh);
WC_SHA3_ROWMIX(nl, nh, sl, sh);
rc = hash_keccak_r[i];
nl[0] ^= (word32)rc; nh[0] ^= (word32)(rc >> 32);
WC_SHA3_THETA(nl, nh);
WC_SHA3_ROWMIX(sl, sh, nl, nh);
rc = hash_keccak_r[i + 1];
sl[0] ^= (word32)rc; sh[0] ^= (word32)(rc >> 32);
}
for (k = 0; k < 25; k++) {
st[2 * k] = sl[k];
st[2 * k + 1] = sh[k];
}
XMEMCPY(s, st, sizeof(st));
}
#undef WC_SHA3_RL
#undef WC_SHA3_CHI
#undef WC_SHA3_THETA
#undef WC_SHA3_ROWMIX
#else /* !WC_SHA3_SPLIT64 */
void BlockSha3(word64* s)
{
word64 n[25];
@@ -625,6 +778,8 @@ void BlockSha3(word64* s)
s[0] ^= hash_keccak_r[i+1];
}
}
#endif /* WC_SHA3_SPLIT64 */
#endif /* WC_SHA3_SW_KECCAK */
#endif /* !WOLFSSL_SHA3_SMALL */
#endif /* !WOLFSSL_ARMASM && !WOLFSSL_RISCV_ASM && !WOLFSSL_PPC64_ASM &&
@@ -675,7 +830,7 @@ void BlockSha3(word64* s)
* wolfcrypt/src/port/ppc32/ppc32-sha3-asm.S), so nothing is needed here. */
#ifdef WC_SHA3_SW_KECCAK
#if defined(BIG_ENDIAN_ORDER)
#if defined(BIG_ENDIAN_ORDER) || defined(WOLFSSL_WIDE_BYTE)
static WC_INLINE word64 Load64Unaligned(const unsigned char *a)
{
return ((word64)a[0] << 0) |
@@ -879,7 +1034,8 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, word32 p)
sha3->i += i;
if (sha3->i == p * 8) {
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_FAULT_HARDEN)
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_FAULT_HARDEN) && \
!defined(WOLFSSL_WIDE_BYTE)
xorbuf(sha3->s, sha3->t, (word32)(p * 8));
#else
for (i = 0; i < p; i++) {
@@ -917,7 +1073,8 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, word32 p)
total_check += blocks * p;
#endif
for (; blocks > 0; blocks--) {
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_FAULT_HARDEN)
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_FAULT_HARDEN) && \
!defined(WOLFSSL_WIDE_BYTE)
xorbuf(sha3->s, data, (word32)(p * 8));
#else
for (i = 0; i < p; i++) {
@@ -974,11 +1131,26 @@ out:
* len Number of bytes in output.
* returns 0 on success.
*/
#ifdef WOLFSSL_WIDE_BYTE
/* Squeeze len output bytes from the Keccak state, extracting each octet from
* the 64-bit lanes (little-endian within a lane). Used where a C 'byte' is
* wider than 8 bits (CHAR_BIT != 8) so the state cannot be copied as an octet
* stream. */
static void Sha3SqueezeBytes(byte* out, const word64* s, word32 len)
{
word32 k;
for (k = 0; k < len; k++) {
out[k] = (byte)((s[k >> 3] >> (8 * (k & 7))) & 0xFF);
}
}
#endif
static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, word32 p, word32 l)
{
word32 rate = p * 8U;
word32 j;
#if defined(BIG_ENDIAN_ORDER) || defined(WC_SHA3_FAULT_HARDEN)
#if defined(BIG_ENDIAN_ORDER) || defined(WC_SHA3_FAULT_HARDEN) || \
defined(WOLFSSL_WIDE_BYTE)
word32 i;
#endif
#ifdef WC_SHA3_FAULT_HARDEN
@@ -993,7 +1165,8 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, word32 p, word32 l
if (sha3->i >= rate)
return BAD_STATE_E;
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_FAULT_HARDEN)
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_FAULT_HARDEN) && \
!defined(WOLFSSL_WIDE_BYTE)
xorbuf(sha3->s, sha3->t, sha3->i);
#ifdef WOLFSSL_HASH_FLAGS
if ((p == WC_SHA3_256_COUNT) && (sha3->flags & WC_HASH_SHA3_KECCAK256)) {
@@ -1048,6 +1221,8 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, word32 p, word32 l
#endif
#if defined(BIG_ENDIAN_ORDER)
ByteReverseWords64((word64*)(hash + j), sha3->s, rate);
#elif defined(WOLFSSL_WIDE_BYTE)
Sha3SqueezeBytes(hash + j, sha3->s, rate);
#else
XMEMCPY(hash + j, sha3->s, rate);
#endif
@@ -1060,8 +1235,12 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, word32 p, word32 l
#endif
#if defined(BIG_ENDIAN_ORDER)
ByteReverseWords64(sha3->s, sha3->s, rate);
#endif
XMEMCPY(hash + j, sha3->s, l - j);
#elif defined(WOLFSSL_WIDE_BYTE)
Sha3SqueezeBytes(hash + j, sha3->s, l - j);
#else
XMEMCPY(hash + j, sha3->s, l - j);
#endif
}
#ifdef USE_INTEL_SPEEDUP
if (SHA3_BLOCK_VREGS(sha3_block)) {
@@ -2093,6 +2272,8 @@ int wc_Shake128_SqueezeBlocks(wc_Shake* shake, byte* out, word32 blockCnt)
#endif
#if defined(BIG_ENDIAN_ORDER)
ByteReverseWords64((word64*)out, shake->s, WC_SHA3_128_COUNT * 8);
#elif defined(WOLFSSL_WIDE_BYTE)
Sha3SqueezeBytes(out, shake->s, WC_SHA3_128_COUNT * 8);
#else
XMEMCPY(out, shake->s, WC_SHA3_128_COUNT * 8);
#endif
@@ -2383,6 +2564,8 @@ int wc_Shake256_SqueezeBlocks(wc_Shake* shake, byte* out, word32 blockCnt)
#endif
#if defined(BIG_ENDIAN_ORDER)
ByteReverseWords64((word64*)out, shake->s, WC_SHA3_256_COUNT * 8);
#elif defined(WOLFSSL_WIDE_BYTE)
Sha3SqueezeBytes(out, shake->s, WC_SHA3_256_COUNT * 8);
#else
XMEMCPY(out, shake->s, WC_SHA3_256_COUNT * 8);
#endif
+60 -4
View File
@@ -2039,8 +2039,13 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le
if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
#endif
{
#ifdef WOLFSSL_WIDE_BYTE
WordsFromBytesBE64(sha512->buffer,
(const byte*)sha512->buffer, WC_SHA512_BLOCK_SIZE / 8);
#else
ByteReverseWords64(sha512->buffer, sha512->buffer,
WC_SHA512_BLOCK_SIZE);
#endif
}
#endif
#if defined(WOLFSSL_ARMASM) || defined(WOLFSSL_PPC64_ASM) || \
@@ -2145,8 +2150,13 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le
#if !defined(WOLFSSL_ESP32_CRYPT) || \
defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \
defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512)
#ifdef WOLFSSL_WIDE_BYTE
WordsFromBytesBE64(sha512->buffer, (const byte*)sha512->buffer,
WC_SHA512_BLOCK_SIZE / 8);
#else
ByteReverseWords64(sha512->buffer, sha512->buffer,
WC_SHA512_BLOCK_SIZE);
#endif
#endif
#if !defined(WOLFSSL_ESP32_CRYPT) || \
defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \
@@ -2275,8 +2285,13 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512)
defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512)) && \
!defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_PPC64_ASM) && \
!defined(WOLFSSL_RISCV_ASM)
#ifdef WOLFSSL_WIDE_BYTE
WordsFromBytesBE64(sha512->buffer, (const byte*)sha512->buffer,
WC_SHA512_BLOCK_SIZE / 8);
#else
ByteReverseWords64(sha512->buffer,sha512->buffer,
WC_SHA512_BLOCK_SIZE);
#endif
#endif
}
@@ -2314,11 +2329,37 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512)
XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_PAD_SIZE - sha512->buffLen);
/* put lengths in bits */
sha512->hiLen = (sha512->loLen >> (8 * sizeof(sha512->loLen) - 3)) +
sha512->hiLen = (sha512->loLen >>
(CHAR_BIT * sizeof(sha512->loLen) - 3)) +
(sha512->hiLen << 3);
sha512->loLen = sha512->loLen << 3;
/* store lengths */
#ifdef WOLFSSL_WIDE_BYTE
/* CHAR_BIT != 8: 'local' indexes octet cells, not the word64 layout (the
* buffer[BLOCK/sizeof(word64) - 2/-1] indices assume 16 words per block,
* which is wrong when sizeof(word64) != 8). Place the 128-bit bit-length
* as 16 big-endian octets at the pad offset, then load all 16 big-endian
* schedule words octet-wise. */
local[WC_SHA512_PAD_SIZE + 0] = (byte)((sha512->hiLen >> 56) & 0xFF);
local[WC_SHA512_PAD_SIZE + 1] = (byte)((sha512->hiLen >> 48) & 0xFF);
local[WC_SHA512_PAD_SIZE + 2] = (byte)((sha512->hiLen >> 40) & 0xFF);
local[WC_SHA512_PAD_SIZE + 3] = (byte)((sha512->hiLen >> 32) & 0xFF);
local[WC_SHA512_PAD_SIZE + 4] = (byte)((sha512->hiLen >> 24) & 0xFF);
local[WC_SHA512_PAD_SIZE + 5] = (byte)((sha512->hiLen >> 16) & 0xFF);
local[WC_SHA512_PAD_SIZE + 6] = (byte)((sha512->hiLen >> 8) & 0xFF);
local[WC_SHA512_PAD_SIZE + 7] = (byte)((sha512->hiLen ) & 0xFF);
local[WC_SHA512_PAD_SIZE + 8] = (byte)((sha512->loLen >> 56) & 0xFF);
local[WC_SHA512_PAD_SIZE + 9] = (byte)((sha512->loLen >> 48) & 0xFF);
local[WC_SHA512_PAD_SIZE + 10] = (byte)((sha512->loLen >> 40) & 0xFF);
local[WC_SHA512_PAD_SIZE + 11] = (byte)((sha512->loLen >> 32) & 0xFF);
local[WC_SHA512_PAD_SIZE + 12] = (byte)((sha512->loLen >> 24) & 0xFF);
local[WC_SHA512_PAD_SIZE + 13] = (byte)((sha512->loLen >> 16) & 0xFF);
local[WC_SHA512_PAD_SIZE + 14] = (byte)((sha512->loLen >> 8) & 0xFF);
local[WC_SHA512_PAD_SIZE + 15] = (byte)((sha512->loLen ) & 0xFF);
WordsFromBytesBE64(sha512->buffer, (const byte*)sha512->buffer,
WC_SHA512_BLOCK_SIZE / 8);
#else
#if defined(LITTLE_ENDIAN_ORDER) && !defined(WC_SHA512_RAW_BE_BUFFER)
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
@@ -2340,6 +2381,7 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512)
sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
#endif
#endif /* WOLFSSL_WIDE_BYTE */
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
@@ -2406,7 +2448,9 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512)
return ret;
#endif
#ifdef LITTLE_ENDIAN_ORDER
/* CHAR_BIT != 8: leave digest in host word order; the *Final functions
* emit big-endian octets via BytesFromWordsBE64 (no in-place reverse). */
#if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_WIDE_BYTE)
ByteReverseWords64(sha512->digest, sha512->digest,
WC_SHA512_DIGEST_SIZE);
#endif
@@ -2440,7 +2484,9 @@ static int Sha512FinalRaw(wc_Sha512* sha512, byte* hash, word32 digestSz)
return BAD_FUNC_ARG;
}
#ifdef LITTLE_ENDIAN_ORDER
#if defined(WOLFSSL_WIDE_BYTE)
BytesFromWordsBE64(hash, sha512->digest, digestSz);
#elif defined(LITTLE_ENDIAN_ORDER)
if ((digestSz & 0x7) == 0)
ByteReverseWords64((word64 *)hash, sha512->digest, digestSz);
else {
@@ -2493,7 +2539,11 @@ static int Sha512_Family_Final(wc_Sha512* sha512, byte* hash, size_t digestSz,
if (ret != 0)
return ret;
#ifdef WOLFSSL_WIDE_BYTE
BytesFromWordsBE64(hash, sha512->digest, (word32)digestSz);
#else
XMEMCPY(hash, sha512->digest, digestSz);
#endif
/* initialize Sha512 structure for the next use */
return initfp(sha512);
@@ -2887,7 +2937,9 @@ int wc_Sha384FinalRaw(wc_Sha384* sha384, byte* hash)
return BAD_FUNC_ARG;
}
#ifdef LITTLE_ENDIAN_ORDER
#if defined(WOLFSSL_WIDE_BYTE)
BytesFromWordsBE64(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
#elif defined(LITTLE_ENDIAN_ORDER)
ByteReverseWords64((word64 *)hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
#else
XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
@@ -2928,7 +2980,11 @@ int wc_Sha384Final(wc_Sha384* sha384, byte* hash)
if (ret != 0)
return ret;
#ifdef WOLFSSL_WIDE_BYTE
BytesFromWordsBE64(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
#else
XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
#endif
return InitSha384(sha384); /* reset state */
}