mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-06 17:40:50 +02:00
Merge pull request #9734 from SparkiDev/mlkem_mldsa_harden
ML-KEM/ML-DSA: harden against fault attacks
This commit is contained in:
+1
-1
@@ -2818,7 +2818,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],
|
||||
|
||||
@@ -8139,6 +8139,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) {
|
||||
@@ -8203,6 +8206,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);
|
||||
@@ -8271,6 +8277,14 @@ 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;
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
#endif
|
||||
dilithium_vec_ntt_full(y_ntt, params->l);
|
||||
dilithium_matrix_mul(w, a, y_ntt, params->k, params->l);
|
||||
#ifdef WOLFSSL_DILITHIUM_SMALL
|
||||
@@ -8415,6 +8429,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)) {
|
||||
@@ -8446,6 +8463,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));
|
||||
@@ -8564,6 +8584,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;
|
||||
@@ -8578,6 +8608,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
|
||||
@@ -8676,6 +8712,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]);
|
||||
|
||||
+23
-23
@@ -595,18 +595,18 @@ 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
|
||||
return *(word64*)a;
|
||||
#elif defined(WC_32BIT_CPU)
|
||||
return (((word64)((word32*)a)[1]) << 32) ||
|
||||
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) ||
|
||||
return (((word64)((word16*)a)[3]) << 48) |
|
||||
(((word64)((word16*)a)[2]) << 32) |
|
||||
(((word64)((word16*)a)[1]) << 16) |
|
||||
((word16*)a)[0];
|
||||
#endif
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user