Skip to content
44 changes: 44 additions & 0 deletions tests/api/test_sha512.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,32 @@ int test_wc_Sha512Transform(void)
"\x68\x75\xde\x70\x09\x4d\xcd\xfe"
"\xbe\x11\x20\xd6\xe7\x7c\x49\xd3"
"\x5b\xd7\x07\x75\x19\xc9\x8a\xfa");
#if !defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)
/* Transform must not modify the caller's block (v5/v6 modules do). */
ExpectBufEQ(abcData, abcSha512Data, WC_SHA512_BLOCK_SIZE);
/* Transform must keep input pending from an earlier Update. */
{
wc_Sha512 shaA;
wc_Sha512 shaB;
byte hashA[WC_SHA512_DIGEST_SIZE];
byte hashB[WC_SHA512_DIGEST_SIZE];

XMEMSET(&shaA, 0, sizeof(shaA));
XMEMSET(&shaB, 0, sizeof(shaB));
ExpectIntEQ(wc_InitSha512(&shaA), 0);
ExpectIntEQ(wc_Sha512Update(&shaA, (const byte*)"ab", 2), 0);
ExpectIntEQ(wc_Sha512Transform(&shaA, abcData), 0);
ExpectIntEQ(wc_Sha512Update(&shaA, (const byte*)"c", 1), 0);
ExpectIntEQ(wc_Sha512Final(&shaA, hashA), 0);
ExpectIntEQ(wc_InitSha512(&shaB), 0);
ExpectIntEQ(wc_Sha512Transform(&shaB, abcData), 0);
ExpectIntEQ(wc_Sha512Update(&shaB, (const byte*)"abc", 3), 0);
ExpectIntEQ(wc_Sha512Final(&shaB, hashB), 0);
ExpectBufEQ(hashA, hashB, WC_SHA512_DIGEST_SIZE);
wc_Sha512Free(&shaA);
wc_Sha512Free(&shaB);
}
#endif
#endif
return EXPECT_RESULT();
}
Expand Down Expand Up @@ -342,6 +368,24 @@ int test_wc_Sha512_224FinalRaw(void)
"\x73\xe1\x99\x66\x89\xdc\xd4\xd6"
"\x1d\xfa\xb7\xae\x32\xff\x9c\x82"
"\x67\x9d\xd5\x14");
{
/* Hashing continues after FinalRaw: "ab", raw read, "c" is "abc". */
wc_Sha512 raw;
byte rawHash[WC_SHA512_224_DIGEST_SIZE];

XMEMSET(&raw, 0, sizeof(raw));
ExpectIntEQ(wc_InitSha512_224(&raw), 0);
ExpectIntEQ(wc_Sha512_224Update(&raw, (const byte*)"ab", 2), 0);
ExpectIntEQ(wc_Sha512_224FinalRaw(&raw, rawHash), 0);
ExpectIntEQ(wc_Sha512_224Update(&raw, (const byte*)"c", 1), 0);
ExpectIntEQ(wc_Sha512_224Final(&raw, rawHash), 0);
ExpectBufEQ(rawHash,
"\x46\x34\x27\x0f\x70\x7b\x6a\x54"
"\xda\xae\x75\x30\x46\x08\x42\xe2"
"\x0e\x37\xed\x26\x5c\xee\xe9\xa4"
"\x3e\x89\x24\xaa", WC_SHA512_224_DIGEST_SIZE);
wc_Sha512_224Free(&raw);
}
#endif
return EXPECT_RESULT();
} /* END test_wc_Sha512_224Final */
Expand Down
53 changes: 34 additions & 19 deletions wolfcrypt/src/sha512.c
Original file line number Diff line number Diff line change
Expand Up @@ -2716,9 +2716,18 @@ static int Sha512FinalRaw(wc_Sha512* sha512, byte* hash, word32 digestSz)
if ((digestSz & 0x7) == 0)
ByteReverseWords64((word64 *)hash, sha512->digest, digestSz);
else {
ByteReverseWords64(sha512->digest, sha512->digest,
WC_SHA512_DIGEST_SIZE);
XMEMCPY(hash, sha512->digest, digestSz);
/* Reverse into a copy so the state is never left reversed. */
word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)];

ByteReverseWords64(digest, sha512->digest, WC_SHA512_DIGEST_SIZE);
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("Sha512FinalRaw digest", digest, sizeof(digest));
#endif
XMEMCPY(hash, digest, digestSz);
ForceZero(digest, sizeof(digest));
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Check(digest, sizeof(digest));
#endif
Comment thread
kaleb-himes marked this conversation as resolved.
Resolved
}
#else
XMEMCPY(hash, sha512->digest, digestSz);
Expand Down Expand Up @@ -2877,7 +2886,7 @@ void wc_Sha512Free(wc_Sha512* sha512)
int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data)
{
int ret;
/* back up buffer */
/* aligned copy of data, or backup of sha->buffer */
WC_DECLARE_VAR(buffer, word64, WC_SHA512_BLOCK_SIZE / sizeof(word64),
0);

Expand Down Expand Up @@ -2907,28 +2916,34 @@ int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data)
wc_MemZero_Add("wc_Sha512Transform buffer", buffer, WC_SHA512_BLOCK_SIZE);
#endif

/* data is const: never modify the caller's block. */
#if (defined(WOLFSSL_ARMASM) && defined(WOLFSSL_ARM_ARCH) && \
(WOLFSSL_ARM_ARCH < 6)) || \
(defined(WOLFSSL_RISCV_ASM) && defined(WOLFSSL_RISCV_VECTOR_CRYPTO_ASM))
/* ARMv5 LDR and RISC-V vl8re64.v loads need an aligned copy. */
XMEMCPY(buffer, data, WC_SHA512_BLOCK_SIZE);
ret = Transform_Sha512(sha, (const byte*)buffer);
#elif defined(WOLFSSL_ARMASM) && defined(__aarch64__)
/* The C CPU step writes sha->buffer, which may hold pending input. */
XMEMCPY(buffer, sha->buffer, WC_SHA512_BLOCK_SIZE);
ret = Transform_Sha512(sha, data);
XMEMCPY(sha->buffer, buffer, WC_SHA512_BLOCK_SIZE);
#elif defined(WOLFSSL_ARMASM) || defined(WOLFSSL_RISCV_ASM) || \
defined(WOLFSSL_PPC64_ASM) || defined(WOLFSSL_PPC32_ASM)
/* The asm reads data as Sha512Update passes it: unreversed. */
ret = Transform_Sha512(sha, data);
Comment thread
kaleb-himes marked this conversation as resolved.
Resolved
Comment thread
kaleb-himes marked this conversation as resolved.
Resolved
#else
XMEMCPY(buffer, sha->buffer, WC_SHA512_BLOCK_SIZE);
XMEMCPY(sha->buffer, data, WC_SHA512_BLOCK_SIZE);
#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))
if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
#endif
{
ByteReverseWords64((word64*)data, (word64*)data,
WC_SHA512_BLOCK_SIZE);
ByteReverseWords64(sha->buffer, sha->buffer, WC_SHA512_BLOCK_SIZE);
}
#endif /* LITTLE_ENDIAN_ORDER && !WC_SHA512_RAW_BE_BUFFER */

#if defined(WOLFSSL_ARMASM) || defined(WOLFSSL_RISCV_ASM)
ByteReverseWords64(buffer, (word64*)data, WC_SHA512_BLOCK_SIZE);
ret = Transform_Sha512(sha, (const byte*)buffer);
#elif defined(WOLFSSL_PPC64_ASM) || defined(WOLFSSL_PPC32_ASM)
/* PPC assembly uses the (sha, data) form and reads the block directly
* (big-endian native - any little-endian reversal was done above). */
(void)buffer;
ret = Transform_Sha512(sha, data);
#else
XMEMCPY(buffer, sha->buffer, WC_SHA512_BLOCK_SIZE);
XMEMCPY(sha->buffer, data, WC_SHA512_BLOCK_SIZE);
#endif

ret = Transform_Sha512(sha);

Expand Down
Loading