mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-02-04 04:15:05 +01:00
SHA-3: harden against glitch attack
Check loop counts to ensure glitching didn't change number of times loop was performed.
This commit is contained in:
@@ -637,6 +637,7 @@ WC_RSA_NONBLOCK
|
||||
WC_RSA_NONBLOCK_TIME
|
||||
WC_RSA_NO_FERMAT_CHECK
|
||||
WC_RWLOCK_OPS_INLINE
|
||||
WC_SHA3_HARDEN
|
||||
WC_SHA384
|
||||
WC_SHA384_DIGEST_SIZE
|
||||
WC_SHA512
|
||||
|
||||
@@ -2726,7 +2726,7 @@ AC_ARG_ENABLE([faultharden],
|
||||
|
||||
if test "$ENABLED_FAULTHARDEN" = "yes"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CHECK_SIG_FAULTS -DWOLFSSL_CHECK_VER_FAULTS"
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CHECK_SIG_FAULTS -DWOLFSSL_CHECK_VER_FAULTS -DWC_SHA3_HARDEN"
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([compileharden],
|
||||
|
||||
@@ -585,7 +585,7 @@ static WC_INLINE word64 Load64Unaligned(const unsigned char *a)
|
||||
* a Array of bytes.
|
||||
* returns a 64-bit integer.
|
||||
*/
|
||||
static word64 Load64BitBigEndian(const byte* a)
|
||||
static word64 Load64BitLittleEndian(const byte* a)
|
||||
{
|
||||
word64 n = 0;
|
||||
int i;
|
||||
@@ -595,6 +595,31 @@ static word64 Load64BitBigEndian(const byte* a)
|
||||
|
||||
return n;
|
||||
}
|
||||
#elif defined(WC_SHA3_HARDEN)
|
||||
static WC_INLINE word64 Load64Unaligned(const unsigned char *a)
|
||||
{
|
||||
#ifdef WC_64BIT_CPU
|
||||
return *(word64*)a;
|
||||
#elif defined(WC_32BIT_CPU)
|
||||
return (((word64)((word32*)a)[1]) << 32) ||
|
||||
((word32*)a)[0];
|
||||
#else
|
||||
return (((word64)((word16*)a)[3]) << 48) ||
|
||||
(((word64)((word16*)a)[2]) << 32) ||
|
||||
(((word64)((word16*)a)[1]) << 16) ||
|
||||
((word16*)a)[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert the array of bytes, in little-endian order, to a 64-bit integer.
|
||||
*
|
||||
* a Array of bytes.
|
||||
* returns a 64-bit integer.
|
||||
*/
|
||||
static word64 Load64BitLittleEndian(const byte* a)
|
||||
{
|
||||
return Load64Unaligned(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the state for a SHA3-224 hash operation.
|
||||
@@ -687,6 +712,10 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
|
||||
{
|
||||
word32 i;
|
||||
word32 blocks;
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
byte check = 0;
|
||||
byte total_check = 0;
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(USE_INTEL_SPEEDUP)
|
||||
if (SHA3_BLOCK == sha3_block_avx2) {
|
||||
@@ -703,19 +732,37 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
|
||||
t = &sha3->t[sha3->i];
|
||||
for (i = 0; i < l; i++) {
|
||||
t[i] = data[i];
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
check++;
|
||||
#endif
|
||||
}
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
if (check != l) {
|
||||
return BAD_COND_E;
|
||||
}
|
||||
total_check += l;
|
||||
#endif
|
||||
data += i;
|
||||
len -= i;
|
||||
sha3->i = (byte)(sha3->i + i);
|
||||
|
||||
if (sha3->i == p * 8) {
|
||||
#if !defined(BIG_ENDIAN_ORDER)
|
||||
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_HARDEN)
|
||||
xorbuf(sha3->s, sha3->t, (word32)(p * 8));
|
||||
#else
|
||||
#else
|
||||
for (i = 0; i < p; i++) {
|
||||
sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i);
|
||||
sha3->s[i] ^= Load64BitLittleEndian(sha3->t + 8 * i);
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
check++;
|
||||
#endif
|
||||
}
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
if (check != p + l) {
|
||||
return BAD_COND_E;
|
||||
}
|
||||
total_check += p;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SHA3_FUNC_PTR
|
||||
(*SHA3_BLOCK)(sha3->s);
|
||||
#else
|
||||
@@ -733,14 +780,25 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
|
||||
blocks = 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
total_check += blocks * p;
|
||||
#endif
|
||||
for (; blocks > 0; blocks--) {
|
||||
#if !defined(BIG_ENDIAN_ORDER)
|
||||
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_HARDEN)
|
||||
xorbuf(sha3->s, data, (word32)(p * 8));
|
||||
#else
|
||||
#else
|
||||
for (i = 0; i < p; i++) {
|
||||
sha3->s[i] ^= Load64Unaligned(data + 8 * i);
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
check++;
|
||||
#endif
|
||||
}
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
if (check != total_check - ((blocks - 1) * p)) {
|
||||
return BAD_COND_E;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SHA3_FUNC_PTR
|
||||
(*SHA3_BLOCK)(sha3->s);
|
||||
#else
|
||||
@@ -749,6 +807,11 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
|
||||
len -= p * 8U;
|
||||
data += p * 8U;
|
||||
}
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
if (check != total_check) {
|
||||
return BAD_COND_E;
|
||||
}
|
||||
#endif
|
||||
#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(USE_INTEL_SPEEDUP)
|
||||
if (SHA3_BLOCK == sha3_block_avx2) {
|
||||
RESTORE_VECTOR_REGISTERS();
|
||||
@@ -774,11 +837,14 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l)
|
||||
{
|
||||
word32 rate = p * 8U;
|
||||
word32 j;
|
||||
#if defined(BIG_ENDIAN_ORDER)
|
||||
#if defined(BIG_ENDIAN_ORDER) || defined(WC_SHA3_HARDEN)
|
||||
word32 i;
|
||||
#endif
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
int check = 0;
|
||||
#endif
|
||||
|
||||
#if !defined(BIG_ENDIAN_ORDER)
|
||||
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_HARDEN)
|
||||
xorbuf(sha3->s, sha3->t, sha3->i);
|
||||
#ifdef WOLFSSL_HASH_FLAGS
|
||||
if ((p == WC_SHA3_256_COUNT) && (sha3->flags & WC_HASH_SHA3_KECCAK256)) {
|
||||
@@ -800,8 +866,16 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l)
|
||||
XMEMSET(sha3->t + sha3->i + 1, 0, rate - 1U - (sha3->i + 1U));
|
||||
}
|
||||
for (i = 0; i < p; i++) {
|
||||
sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i);
|
||||
sha3->s[i] ^= Load64BitLittleEndian(sha3->t + 8 * i);
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
check++;
|
||||
#endif
|
||||
}
|
||||
#ifdef WC_SHA3_HARDEN
|
||||
if (check != p) {
|
||||
return BAD_COND_E;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(USE_INTEL_SPEEDUP)
|
||||
@@ -843,80 +917,79 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l)
|
||||
#endif
|
||||
#if defined(STM32_HASH_SHA3)
|
||||
|
||||
/* Supports CubeMX HAL or Standard Peripheral Library */
|
||||
/* Supports CubeMX HAL or Standard Peripheral Library */
|
||||
|
||||
static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId)
|
||||
{
|
||||
if (sha3 == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId)
|
||||
{
|
||||
if (sha3 == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
(void)devId;
|
||||
(void)heap;
|
||||
(void)devId;
|
||||
(void)heap;
|
||||
|
||||
XMEMSET(sha3, 0, sizeof(wc_Sha3));
|
||||
wc_Stm32_Hash_Init(&sha3->stmCtx);
|
||||
XMEMSET(sha3, 0, sizeof(wc_Sha3));
|
||||
wc_Stm32_Hash_Init(&sha3->stmCtx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Stm32GetAlgo(byte p)
|
||||
{
|
||||
switch(p) {
|
||||
case WC_SHA3_224_COUNT:
|
||||
return HASH_ALGOSELECTION_SHA3_224;
|
||||
case WC_SHA3_256_COUNT:
|
||||
return HASH_ALGOSELECTION_SHA3_256;
|
||||
case WC_SHA3_384_COUNT:
|
||||
return HASH_ALGOSELECTION_SHA3_384;
|
||||
case WC_SHA3_512_COUNT:
|
||||
return HASH_ALGOSELECTION_SHA3_512;
|
||||
}
|
||||
/* Should never get here */
|
||||
return WC_SHA3_224_COUNT;
|
||||
}
|
||||
|
||||
static int wc_Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (sha3 == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (data == NULL && len == 0) {
|
||||
/* valid, but do nothing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Stm32GetAlgo(byte p)
|
||||
{
|
||||
switch(p) {
|
||||
case WC_SHA3_224_COUNT:
|
||||
return HASH_ALGOSELECTION_SHA3_224;
|
||||
case WC_SHA3_256_COUNT:
|
||||
return HASH_ALGOSELECTION_SHA3_256;
|
||||
case WC_SHA3_384_COUNT:
|
||||
return HASH_ALGOSELECTION_SHA3_384;
|
||||
case WC_SHA3_512_COUNT:
|
||||
return HASH_ALGOSELECTION_SHA3_512;
|
||||
}
|
||||
/* Should never get here */
|
||||
return WC_SHA3_224_COUNT;
|
||||
if (data == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
static int wc_Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = wolfSSL_CryptHwMutexLock();
|
||||
if (ret == 0) {
|
||||
ret = wc_Stm32_Hash_Update(&sha3->stmCtx, Stm32GetAlgo(p), data, len,
|
||||
p * 8);
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sha3 == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (data == NULL && len == 0) {
|
||||
/* valid, but do nothing */
|
||||
return 0;
|
||||
}
|
||||
if (data == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = wolfSSL_CryptHwMutexLock();
|
||||
if (ret == 0) {
|
||||
ret = wc_Stm32_Hash_Update(&sha3->stmCtx,
|
||||
Stm32GetAlgo(p), data, len, p * 8);
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
}
|
||||
return ret;
|
||||
if (sha3 == NULL || hash == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (sha3 == NULL || hash == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
ret = wolfSSL_CryptHwMutexLock();
|
||||
if (ret == 0) {
|
||||
ret = wc_Stm32_Hash_Final(&sha3->stmCtx,
|
||||
Stm32GetAlgo(p), hash, len);
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
}
|
||||
|
||||
(void)wc_InitSha3(sha3, NULL, 0); /* reset state */
|
||||
|
||||
return ret;
|
||||
ret = wolfSSL_CryptHwMutexLock();
|
||||
if (ret == 0) {
|
||||
ret = wc_Stm32_Hash_Final(&sha3->stmCtx, Stm32GetAlgo(p), hash, len);
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
}
|
||||
|
||||
(void)wc_InitSha3(sha3, NULL, 0); /* reset state */
|
||||
|
||||
return ret;
|
||||
}
|
||||
#elif defined(PSOC6_HASH_SHA3)
|
||||
|
||||
static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId)
|
||||
|
||||
Reference in New Issue
Block a user