Skip to content

Commit 0f6c5cc

Browse files
committed
SHA-3: harden against glitch attack
Check loop counts to ensure glitching didn't change number of times loop was performed.
1 parent a631611 commit 0f6c5cc

File tree

2 files changed

+143
-69
lines changed

2 files changed

+143
-69
lines changed

.wolfssl_known_macro_extras

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,7 @@ WC_RSA_NONBLOCK
637637
WC_RSA_NONBLOCK_TIME
638638
WC_RSA_NO_FERMAT_CHECK
639639
WC_RWLOCK_OPS_INLINE
640+
WC_SHA3_HARDEN
640641
WC_SHA384
641642
WC_SHA384_DIGEST_SIZE
642643
WC_SHA512

wolfcrypt/src/sha3.c

Lines changed: 142 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ static WC_INLINE word64 Load64Unaligned(const unsigned char *a)
585585
* a Array of bytes.
586586
* returns a 64-bit integer.
587587
*/
588-
static word64 Load64BitBigEndian(const byte* a)
588+
static word64 Load64BitLittleEndian(const byte* a)
589589
{
590590
word64 n = 0;
591591
int i;
@@ -595,6 +595,31 @@ static word64 Load64BitBigEndian(const byte* a)
595595

596596
return n;
597597
}
598+
#elif defined(WC_SHA3_HARDEN)
599+
static WC_INLINE word64 Load64Unaligned(const unsigned char *a)
600+
{
601+
#ifdef WC_64BIT_CPU
602+
return *(word64*)a;
603+
#elif defined(WC_32BIT_CPU)
604+
return (((word64)((word32*)a)[1]) << 32) ||
605+
((word32*)a)[0];
606+
#else
607+
return (((word64)((word16*)a)[3]) << 48) ||
608+
(((word64)((word16*)a)[2]) << 32) ||
609+
(((word64)((word16*)a)[1]) << 16) ||
610+
((word16*)a)[0];
611+
#endif
612+
}
613+
614+
/* Convert the array of bytes, in little-endian order, to a 64-bit integer.
615+
*
616+
* a Array of bytes.
617+
* returns a 64-bit integer.
618+
*/
619+
static word64 Load64BitLittleEndian(const byte* a)
620+
{
621+
return Load64Unaligned(a);
622+
}
598623
#endif
599624

600625
/* 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)
687712
{
688713
word32 i;
689714
word32 blocks;
715+
#ifdef WC_SHA3_HARDEN
716+
byte check = 0;
717+
byte total_check = 0;
718+
#endif
690719

691720
#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(USE_INTEL_SPEEDUP)
692721
if (SHA3_BLOCK == sha3_block_avx2) {
@@ -703,19 +732,37 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
703732
t = &sha3->t[sha3->i];
704733
for (i = 0; i < l; i++) {
705734
t[i] = data[i];
735+
#ifdef WC_SHA3_HARDEN
736+
check++;
737+
#endif
706738
}
739+
#ifdef WC_SHA3_HARDEN
740+
if (check != l) {
741+
return BAD_COND_E;
742+
}
743+
total_check += l;
744+
#endif
707745
data += i;
708746
len -= i;
709747
sha3->i = (byte)(sha3->i + i);
710748

711749
if (sha3->i == p * 8) {
712-
#if !defined(BIG_ENDIAN_ORDER)
750+
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_HARDEN)
713751
xorbuf(sha3->s, sha3->t, (word32)(p * 8));
714-
#else
752+
#else
715753
for (i = 0; i < p; i++) {
716-
sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i);
754+
sha3->s[i] ^= Load64BitLittleEndian(sha3->t + 8 * i);
755+
#ifdef WC_SHA3_HARDEN
756+
check++;
757+
#endif
758+
}
759+
#ifdef WC_SHA3_HARDEN
760+
if (check != p + l) {
761+
return BAD_COND_E;
717762
}
763+
total_check += p;
718764
#endif
765+
#endif
719766
#ifdef SHA3_FUNC_PTR
720767
(*SHA3_BLOCK)(sha3->s);
721768
#else
@@ -733,14 +780,25 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
733780
blocks = 0;
734781
}
735782
#endif
783+
#ifdef WC_SHA3_HARDEN
784+
total_check += blocks * p;
785+
#endif
736786
for (; blocks > 0; blocks--) {
737-
#if !defined(BIG_ENDIAN_ORDER)
787+
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_HARDEN)
738788
xorbuf(sha3->s, data, (word32)(p * 8));
739-
#else
789+
#else
740790
for (i = 0; i < p; i++) {
741791
sha3->s[i] ^= Load64Unaligned(data + 8 * i);
792+
#ifdef WC_SHA3_HARDEN
793+
check++;
794+
#endif
795+
}
796+
#ifdef WC_SHA3_HARDEN
797+
if (check != total_check - ((blocks - 1) * p)) {
798+
return BAD_COND_E;
742799
}
743800
#endif
801+
#endif
744802
#ifdef SHA3_FUNC_PTR
745803
(*SHA3_BLOCK)(sha3->s);
746804
#else
@@ -749,6 +807,11 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
749807
len -= p * 8U;
750808
data += p * 8U;
751809
}
810+
#ifdef WC_SHA3_HARDEN
811+
if (check != total_check) {
812+
return BAD_COND_E;
813+
}
814+
#endif
752815
#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(USE_INTEL_SPEEDUP)
753816
if (SHA3_BLOCK == sha3_block_avx2) {
754817
RESTORE_VECTOR_REGISTERS();
@@ -774,11 +837,14 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l)
774837
{
775838
word32 rate = p * 8U;
776839
word32 j;
777-
#if defined(BIG_ENDIAN_ORDER)
840+
#if defined(BIG_ENDIAN_ORDER) || defined(WC_SHA3_HARDEN)
778841
word32 i;
779842
#endif
843+
#ifdef WC_SHA3_HARDEN
844+
int check = 0;
845+
#endif
780846

781-
#if !defined(BIG_ENDIAN_ORDER)
847+
#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_HARDEN)
782848
xorbuf(sha3->s, sha3->t, sha3->i);
783849
#ifdef WOLFSSL_HASH_FLAGS
784850
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)
800866
XMEMSET(sha3->t + sha3->i + 1, 0, rate - 1U - (sha3->i + 1U));
801867
}
802868
for (i = 0; i < p; i++) {
803-
sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i);
869+
sha3->s[i] ^= Load64BitLittleEndian(sha3->t + 8 * i);
870+
#ifdef WC_SHA3_HARDEN
871+
check++;
872+
#endif
804873
}
874+
#ifdef WC_SHA3_HARDEN
875+
if (check != p) {
876+
return BAD_COND_E;
877+
}
878+
#endif
805879
#endif
806880

807881
#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)
843917
#endif
844918
#if defined(STM32_HASH_SHA3)
845919

846-
/* Supports CubeMX HAL or Standard Peripheral Library */
920+
/* Supports CubeMX HAL or Standard Peripheral Library */
847921

848-
static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId)
849-
{
850-
if (sha3 == NULL)
851-
return BAD_FUNC_ARG;
922+
static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId)
923+
{
924+
if (sha3 == NULL)
925+
return BAD_FUNC_ARG;
852926

853-
(void)devId;
854-
(void)heap;
927+
(void)devId;
928+
(void)heap;
855929

856-
XMEMSET(sha3, 0, sizeof(wc_Sha3));
857-
wc_Stm32_Hash_Init(&sha3->stmCtx);
858-
return 0;
859-
}
930+
XMEMSET(sha3, 0, sizeof(wc_Sha3));
931+
wc_Stm32_Hash_Init(&sha3->stmCtx);
932+
return 0;
933+
}
860934

861-
static int Stm32GetAlgo(byte p)
862-
{
863-
switch(p) {
864-
case WC_SHA3_224_COUNT:
865-
return HASH_ALGOSELECTION_SHA3_224;
866-
case WC_SHA3_256_COUNT:
867-
return HASH_ALGOSELECTION_SHA3_256;
868-
case WC_SHA3_384_COUNT:
869-
return HASH_ALGOSELECTION_SHA3_384;
870-
case WC_SHA3_512_COUNT:
871-
return HASH_ALGOSELECTION_SHA3_512;
872-
}
873-
/* Should never get here */
874-
return WC_SHA3_224_COUNT;
935+
static int Stm32GetAlgo(byte p)
936+
{
937+
switch(p) {
938+
case WC_SHA3_224_COUNT:
939+
return HASH_ALGOSELECTION_SHA3_224;
940+
case WC_SHA3_256_COUNT:
941+
return HASH_ALGOSELECTION_SHA3_256;
942+
case WC_SHA3_384_COUNT:
943+
return HASH_ALGOSELECTION_SHA3_384;
944+
case WC_SHA3_512_COUNT:
945+
return HASH_ALGOSELECTION_SHA3_512;
875946
}
947+
/* Should never get here */
948+
return WC_SHA3_224_COUNT;
949+
}
876950

877-
static int wc_Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
878-
{
879-
int ret = 0;
951+
static int wc_Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
952+
{
953+
int ret = 0;
880954

881-
if (sha3 == NULL) {
882-
return BAD_FUNC_ARG;
883-
}
884-
if (data == NULL && len == 0) {
885-
/* valid, but do nothing */
886-
return 0;
887-
}
888-
if (data == NULL) {
889-
return BAD_FUNC_ARG;
890-
}
955+
if (sha3 == NULL) {
956+
return BAD_FUNC_ARG;
957+
}
958+
if (data == NULL && len == 0) {
959+
/* valid, but do nothing */
960+
return 0;
961+
}
962+
if (data == NULL) {
963+
return BAD_FUNC_ARG;
964+
}
891965

892-
ret = wolfSSL_CryptHwMutexLock();
893-
if (ret == 0) {
894-
ret = wc_Stm32_Hash_Update(&sha3->stmCtx,
895-
Stm32GetAlgo(p), data, len, p * 8);
896-
wolfSSL_CryptHwMutexUnLock();
897-
}
898-
return ret;
966+
ret = wolfSSL_CryptHwMutexLock();
967+
if (ret == 0) {
968+
ret = wc_Stm32_Hash_Update(&sha3->stmCtx, Stm32GetAlgo(p), data, len,
969+
p * 8);
970+
wolfSSL_CryptHwMutexUnLock();
899971
}
972+
return ret;
973+
}
900974

901-
static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len)
902-
{
903-
int ret = 0;
975+
static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len)
976+
{
977+
int ret = 0;
904978

905-
if (sha3 == NULL || hash == NULL) {
906-
return BAD_FUNC_ARG;
907-
}
979+
if (sha3 == NULL || hash == NULL) {
980+
return BAD_FUNC_ARG;
981+
}
908982

909-
ret = wolfSSL_CryptHwMutexLock();
910-
if (ret == 0) {
911-
ret = wc_Stm32_Hash_Final(&sha3->stmCtx,
912-
Stm32GetAlgo(p), hash, len);
913-
wolfSSL_CryptHwMutexUnLock();
914-
}
983+
ret = wolfSSL_CryptHwMutexLock();
984+
if (ret == 0) {
985+
ret = wc_Stm32_Hash_Final(&sha3->stmCtx, Stm32GetAlgo(p), hash, len);
986+
wolfSSL_CryptHwMutexUnLock();
987+
}
915988

916-
(void)wc_InitSha3(sha3, NULL, 0); /* reset state */
989+
(void)wc_InitSha3(sha3, NULL, 0); /* reset state */
917990

918-
return ret;
919-
}
991+
return ret;
992+
}
920993
#elif defined(PSOC6_HASH_SHA3)
921994

922995
static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId)

0 commit comments

Comments
 (0)