diff --git a/configure.ac b/configure.ac index e248005e0b..2536531238 100644 --- a/configure.ac +++ b/configure.ac @@ -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 -DWC_SHA3_HARDEN" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CHECK_SIG_FAULTS -DWOLFSSL_CHECK_VER_FAULTS -DWC_SHA3_FAULT_HARDEN -DWC_MLKEM_FAULT_HARDEN -DWC_MLDSA_FAULT_HARDEN" fi AC_ARG_ENABLE([compileharden], diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index 86e92113c1..07ce18c2eb 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -8138,6 +8138,9 @@ static int dilithium_sign_with_seed_mu(dilithium_key* key, sword32* ct0 = NULL; byte priv_rand_seed[DILITHIUM_Y_SEED_SZ]; byte* h = sig + params->lambda / 4 + params->zEncSz; +#ifdef WC_MLDSA_FAULT_HARDEN + sword32* y_check; +#endif /* Check the signature buffer isn't too small. */ if (*sigLen < params->sigSz) { @@ -8202,6 +8205,9 @@ static int dilithium_sign_with_seed_mu(dilithium_key* key, ret = MEMORY_E; } else { + #ifdef WC_MLDSA_FAULT_HARDEN + y_check = y; + #endif w0 = y + params->s1Sz / sizeof(*y); w1 = w0 + params->s2Sz / sizeof(*w0); c = w1 + params->s2Sz / sizeof(*w1); @@ -8270,6 +8276,12 @@ static int dilithium_sign_with_seed_mu(dilithium_key* key, { /* Step 13: NTT-1(A o NTT(y)) */ XMEMCPY(y_ntt, y, params->s1Sz); + #ifdef WC_MLDSA_FAULT_HARDEN + if (y_check != y) { + valid = 0; + ret = BAD_COND_E; + } + #endif dilithium_vec_ntt_full(y_ntt, params->l); dilithium_matrix_mul(w, a, y_ntt, params->k, params->l); dilithium_vec_invntt_full(w, params->k); @@ -8411,6 +8423,9 @@ static int dilithium_sign_with_seed_mu(dilithium_key* key, byte maxK = (byte)min(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A, params->k); #endif +#ifdef WC_MLDSA_FAULT_HARDEN + sword32* y_check; +#endif /* Check the signature buffer isn't too small. */ if ((ret == 0) && (*sigLen < params->sigSz)) { @@ -8442,6 +8457,9 @@ static int dilithium_sign_with_seed_mu(dilithium_key* key, ret = MEMORY_E; } else { + #ifdef WC_MLDSA_FAULT_HARDEN + y_check = y; + #endif w0 = y + params->s1Sz / sizeof(*y_ntt); w1 = w0 + params->s2Sz / sizeof(*w0); blocks = (byte*)(w1 + params->s2Sz / sizeof(*w1)); @@ -8557,6 +8575,16 @@ static int dilithium_sign_with_seed_mu(dilithium_key* key, #else sword32* y_ntt_t = y_ntt; #endif + #ifdef WC_MLDSA_FAULT_HARDEN + sword32* yt_check = yt; + #endif + #ifdef WC_MLDSA_FAULT_HARDEN + if (y_check != y) { + valid = 0; + ret = BAD_COND_E; + break; + } + #endif /* Put r/i into buffer to be hashed. */ aseed[DILITHIUM_PUB_SEED_SZ + 1] = r; @@ -8571,6 +8599,12 @@ static int dilithium_sign_with_seed_mu(dilithium_key* key, break; } XMEMCPY(y_ntt_t, yt, DILITHIUM_POLY_SIZE); + #ifdef WC_MLDSA_FAULT_HARDEN + if (yt_check + s * DILITHIUM_N != yt) { + ret = BAD_COND_E; + break; + } + #endif dilithium_ntt_full(y_ntt_t); /* Matrix multiply. */ #ifndef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 @@ -8669,6 +8703,9 @@ static int dilithium_sign_with_seed_mu(dilithium_key* key, /* Next polynomial. */ yt += DILITHIUM_N; } + if (ret != 0) { + break; + } #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 for (e = 0; e < DILITHIUM_N; e++) { wt[e] = dilithium_mont_red(t64[e]); diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c index 8fbca30b2d..c344f6ddb0 100644 --- a/wolfcrypt/src/sha3.c +++ b/wolfcrypt/src/sha3.c @@ -595,7 +595,7 @@ static word64 Load64BitLittleEndian(const byte* a) return n; } -#elif defined(WC_SHA3_HARDEN) +#elif defined(WC_SHA3_FAULT_HARDEN) static WC_INLINE word64 Load64Unaligned(const unsigned char *a) { #ifdef WC_64BIT_CPU @@ -712,9 +712,9 @@ 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; +#ifdef WC_SHA3_FAULT_HARDEN + word32 check = 0; + word32 total_check = 0; #endif #if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(USE_INTEL_SPEEDUP) @@ -732,11 +732,11 @@ 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 + #ifdef WC_SHA3_FAULT_HARDEN check++; #endif } - #ifdef WC_SHA3_HARDEN + #ifdef WC_SHA3_FAULT_HARDEN if (check != l) { return BAD_COND_E; } @@ -747,16 +747,16 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) sha3->i = (byte)(sha3->i + i); if (sha3->i == p * 8) { - #if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_HARDEN) + #if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_FAULT_HARDEN) xorbuf(sha3->s, sha3->t, (word32)(p * 8)); #else for (i = 0; i < p; i++) { sha3->s[i] ^= Load64BitLittleEndian(sha3->t + 8 * i); - #ifdef WC_SHA3_HARDEN + #ifdef WC_SHA3_FAULT_HARDEN check++; #endif } - #ifdef WC_SHA3_HARDEN + #ifdef WC_SHA3_FAULT_HARDEN if (check != p + l) { return BAD_COND_E; } @@ -780,20 +780,20 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) blocks = 0; } #endif -#ifdef WC_SHA3_HARDEN +#ifdef WC_SHA3_FAULT_HARDEN total_check += blocks * p; #endif for (; blocks > 0; blocks--) { -#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_HARDEN) +#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_FAULT_HARDEN) xorbuf(sha3->s, data, (word32)(p * 8)); #else for (i = 0; i < p; i++) { sha3->s[i] ^= Load64Unaligned(data + 8 * i); - #ifdef WC_SHA3_HARDEN + #ifdef WC_SHA3_FAULT_HARDEN check++; #endif } - #ifdef WC_SHA3_HARDEN + #ifdef WC_SHA3_FAULT_HARDEN if (check != total_check - ((blocks - 1) * p)) { return BAD_COND_E; } @@ -807,7 +807,7 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) len -= p * 8U; data += p * 8U; } -#ifdef WC_SHA3_HARDEN +#ifdef WC_SHA3_FAULT_HARDEN if (check != total_check) { return BAD_COND_E; } @@ -837,14 +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) || defined(WC_SHA3_HARDEN) +#if defined(BIG_ENDIAN_ORDER) || defined(WC_SHA3_FAULT_HARDEN) word32 i; #endif -#ifdef WC_SHA3_HARDEN +#ifdef WC_SHA3_FAULT_HARDEN int check = 0; #endif -#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_HARDEN) +#if !defined(BIG_ENDIAN_ORDER) && !defined(WC_SHA3_FAULT_HARDEN) xorbuf(sha3->s, sha3->t, sha3->i); #ifdef WOLFSSL_HASH_FLAGS if ((p == WC_SHA3_256_COUNT) && (sha3->flags & WC_HASH_SHA3_KECCAK256)) { @@ -867,11 +867,11 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l) } for (i = 0; i < p; i++) { sha3->s[i] ^= Load64BitLittleEndian(sha3->t + 8 * i); - #ifdef WC_SHA3_HARDEN + #ifdef WC_SHA3_FAULT_HARDEN check++; #endif } -#ifdef WC_SHA3_HARDEN +#ifdef WC_SHA3_FAULT_HARDEN if (check != p) { return BAD_COND_E; } diff --git a/wolfcrypt/src/wc_mlkem.c b/wolfcrypt/src/wc_mlkem.c index 6cd325888a..d4cf03c6bc 100644 --- a/wolfcrypt/src/wc_mlkem.c +++ b/wolfcrypt/src/wc_mlkem.c @@ -434,7 +434,11 @@ int wc_MlKemKey_MakeKeyWithRandom(MlKemKey* key, const unsigned char* rand, { byte buf[2 * WC_ML_KEM_SYM_SZ + 1]; byte* rho = buf; +#ifndef WC_MLKEM_FAULT_HARDEN byte* sigma = buf + WC_ML_KEM_SYM_SZ; +#else + byte sigma[WC_ML_KEM_SYM_SZ + 1]; +#endif #ifndef WOLFSSL_NO_MALLOC sword16* e = NULL; #else @@ -565,6 +569,17 @@ int wc_MlKemKey_MakeKeyWithRandom(MlKemKey* key, const unsigned char* rand, } #endif } +#ifdef WC_MLKEM_FAULT_HARDEN + if (ret == 0) { + XMEMCPY(sigma, buf + WC_ML_KEM_SYM_SZ, WC_ML_KEM_SYM_SZ); + if (XMEMCMP(sigma, rho, WC_ML_KEM_SYM_SZ) == 0) { + ret = BAD_COND_E; + } + if (XMEMCMP(sigma, rho + WC_ML_KEM_SYM_SZ, WC_ML_KEM_SYM_SZ) != 0) { + ret = BAD_COND_E; + } + } +#endif if (ret == 0) { const byte* z = rand + WC_ML_KEM_SYM_SZ; s = key->priv;