add option for additional sanity checks

This commit is contained in:
JacobBarthelmeh
2024-12-13 14:39:11 -07:00
parent 42afede3fc
commit f0f50f1837
4 changed files with 157 additions and 0 deletions

View File

@ -2357,6 +2357,16 @@ else
AM_CFLAGS="$AM_CFLAGS -DWC_NO_HARDEN -DWC_NO_CACHE_RESISTANT" AM_CFLAGS="$AM_CFLAGS -DWC_NO_HARDEN -DWC_NO_CACHE_RESISTANT"
fi fi
# Fault protection hardening
AC_ARG_ENABLE([faultharden],
[AS_HELP_STRING([--enable-faultharden],[Enable Fault Hardened build (default: disabled)])],
[ENABLED_FAULTHARDEN=$enableval],
[ENABLED_FAULTHARDEN=yes])
if test "$ENABLED_FAULTHARDEN" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CHECK_SIG_FAULTS -DWOLFSSL_CHECK_VER_FAULTS"
fi
# IPv6 Test Apps # IPv6 Test Apps
AC_ARG_ENABLE([ipv6], AC_ARG_ENABLE([ipv6],

View File

@ -104,6 +104,9 @@ Possible ECC enable options:
* unmasked copy is computed and stored each time it is * unmasked copy is computed and stored each time it is
* needed. * needed.
* default: off * default: off
* WOLFSSL_CHECK_VER_FAULTS
* Sanity check on verification steps in case of faults.
* default: off
*/ */
/* /*
@ -8970,13 +8973,28 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
#endif #endif
if (err == MP_OKAY) { if (err == MP_OKAY) {
#ifdef WOLFSSL_CHECK_VER_FAULTS
u1 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
u2 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
if (u1 == NULL || u2 == NULL)
err = MEMORY_E;
#else
u1 = e; u1 = e;
u2 = w; u2 = w;
#endif
v = w; v = w;
} }
if (err == MP_OKAY) { if (err == MP_OKAY) {
err = INIT_MP_INT_SIZE(w, ECC_KEY_MAX_BITS_NONULLCHECK(key)); err = INIT_MP_INT_SIZE(w, ECC_KEY_MAX_BITS_NONULLCHECK(key));
} }
#ifdef WOLFSSL_CHECK_VER_FAULTS
if (err == MP_OKAY) {
err = INIT_MP_INT_SIZE(u1, ECC_KEY_MAX_BITS_NONULLCHECK(key));
}
if (err == MP_OKAY) {
err = INIT_MP_INT_SIZE(u2, ECC_KEY_MAX_BITS_NONULLCHECK(key));
}
#endif
/* allocate points */ /* allocate points */
if (err == MP_OKAY) { if (err == MP_OKAY) {
@ -9000,10 +9018,22 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_mulmod(e, w, curve->order, u1); err = mp_mulmod(e, w, curve->order, u1);
#ifdef WOLFSSL_CHECK_VER_FAULTS
if (err == MP_OKAY && mp_iszero(e) != MP_YES && mp_cmp(u1, e) == MP_EQ) {
err = BAD_STATE_E;
}
#endif
/* u2 = rw */ /* u2 = rw */
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_mulmod(r, w, curve->order, u2); err = mp_mulmod(r, w, curve->order, u2);
#ifdef WOLFSSL_CHECK_VER_FAULTS
if (err == MP_OKAY && mp_cmp(u2, w) == MP_EQ) {
err = BAD_STATE_E;
}
#endif
/* find mG and mQ */ /* find mG and mQ */
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy(curve->Gx, mG->x); err = mp_copy(curve->Gx, mG->x);
@ -9031,16 +9061,35 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
#ifndef ECC_SHAMIR #ifndef ECC_SHAMIR
if (err == MP_OKAY) if (err == MP_OKAY)
{ {
#ifdef WOLFSSL_CHECK_VER_FAULTS
ecc_point mG1, mQ1;
wc_ecc_copy_point(mQ, &mQ1);
wc_ecc_copy_point(mG, &mG1);
#endif
mp_digit mp = 0; mp_digit mp = 0;
if (!mp_iszero((MP_INT_SIZE*)u1)) { if (!mp_iszero((MP_INT_SIZE*)u1)) {
/* compute u1*mG + u2*mQ = mG */ /* compute u1*mG + u2*mQ = mG */
err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0,
key->heap); key->heap);
#ifdef WOLFSSL_CHECK_VER_FAULTS
if (err == MP_OKAY && wc_ecc_cmp_point(mG, &mG1) == MP_EQ) {
err = BAD_STATE_E;
}
/* store new value for comparing with after add operation */
wc_ecc_copy_point(mG, &mG1);
#endif
if (err == MP_OKAY) { if (err == MP_OKAY) {
err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0,
key->heap); key->heap);
} }
#ifdef WOLFSSL_CHECK_VER_FAULTS
if (err == MP_OKAY && wc_ecc_cmp_point(mQ, &mQ1) == MP_EQ) {
err = BAD_STATE_E;
}
#endif
/* find the montgomery mp */ /* find the montgomery mp */
if (err == MP_OKAY) if (err == MP_OKAY)
@ -9050,6 +9099,14 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
if (err == MP_OKAY) if (err == MP_OKAY)
err = ecc_projective_add_point_safe(mQ, mG, mG, curve->Af, err = ecc_projective_add_point_safe(mQ, mG, mG, curve->Af,
curve->prime, mp, NULL); curve->prime, mp, NULL);
#ifdef WOLFSSL_CHECK_VER_FAULTS
if (err == MP_OKAY && wc_ecc_cmp_point(mG, &mG1) == MP_EQ) {
err = BAD_STATE_E;
}
if (err == MP_OKAY && wc_ecc_cmp_point(mG, mQ) == MP_EQ) {
err = BAD_STATE_E;
}
#endif
} }
else { else {
/* compute 0*mG + u2*mQ = mG */ /* compute 0*mG + u2*mQ = mG */
@ -9072,6 +9129,7 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
} }
#endif /* ECC_SHAMIR */ #endif /* ECC_SHAMIR */
#endif /* FREESCALE_LTC_ECC */ #endif /* FREESCALE_LTC_ECC */
/* v = X_x1 mod n */ /* v = X_x1 mod n */
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_mod(mG->x, curve->order, v); err = mp_mod(mG->x, curve->order, v);
@ -9089,6 +9147,12 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
mp_clear(e); mp_clear(e);
mp_clear(w); mp_clear(w);
FREE_MP_INT_SIZE(w, key->heap, DYNAMIC_TYPE_ECC); FREE_MP_INT_SIZE(w, key->heap, DYNAMIC_TYPE_ECC);
#ifdef WOLFSSL_CHECK_VER_FAULTS
mp_clear(u1);
FREE_MP_INT_SIZE(u1, key->heap, DYNAMIC_TYPE_ECC);
mp_clear(u2);
FREE_MP_INT_SIZE(u2, key->heap, DYNAMIC_TYPE_ECC);
#endif
#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
FREE_MP_INT_SIZE(e_lcl, key->heap, DYNAMIC_TYPE_ECC); FREE_MP_INT_SIZE(e_lcl, key->heap, DYNAMIC_TYPE_ECC);
#endif #endif

View File

@ -48,6 +48,7 @@
#include <wolfssl/wolfcrypt/ed25519.h> #include <wolfssl/wolfcrypt/ed25519.h>
#include <wolfssl/wolfcrypt/ge_operations.h> #include <wolfssl/wolfcrypt/ge_operations.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h> #include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/hash.h> #include <wolfssl/wolfcrypt/hash.h>
#ifdef NO_INLINE #ifdef NO_INLINE
@ -628,6 +629,35 @@ int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,
#ifdef HAVE_ED25519_VERIFY #ifdef HAVE_ED25519_VERIFY
#ifndef WOLFSSL_SE050 #ifndef WOLFSSL_SE050
#ifdef WOLFSSL_CHECK_VER_FAULTS
static const byte sha512_empty[] = {
0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
};
/* sanity check that hash operation happened
* returns 0 on success */
static int ed25519_hash_check(ed25519_key* key, byte* h)
{
(void)key; /* passing in key in case other hash algroithms are used */
if (XMEMCMP(h, sha512_empty, WC_SHA512_DIGEST_SIZE) != 0) {
return 0;
}
else {
return BAD_STATE_E;
}
}
#endif
/* /*
sig is array of bytes containing the signature sig is array of bytes containing the signature
sigLen is the length of sig byte array sigLen is the length of sig byte array
@ -675,6 +705,22 @@ static int ed25519_verify_msg_init_with_sha(const byte* sig, word32 sigLen,
} }
if (ret == 0) if (ret == 0)
ret = ed25519_hash_update(key, sha, sig, ED25519_SIG_SIZE/2); ret = ed25519_hash_update(key, sha, sig, ED25519_SIG_SIZE/2);
#ifdef WOLFSSL_CHECK_VER_FAULTS
/* sanity check that hash operation happened */
if (ret == 0) {
byte h[WC_MAX_DIGEST_SIZE];
ret = wc_Sha512GetHash(sha, h);
if (ret == 0) {
ret = ed25519_hash_check(key, h);
if (ret != 0) {
WOLFSSL_MSG("Unexpected initial state of hash found");
}
}
}
#endif
if (ret == 0) if (ret == 0)
ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE); ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE);

View File

@ -512,6 +512,33 @@ int ge_frombytes_negate_vartime(ge_p3 *p,const unsigned char *s)
return ret; return ret;
} }
#ifdef WOLFSSL_CHECK_VER_FAULTS
/* return 0 if equal and -1 if not equal */
static int ge_equal(ge a, ge b)
{
if (XMEMCMP(a, b, sizeof(ge)) == 0) {
return 0;
}
else {
return -1;
}
}
/* returns 0 if a == b */
static int ge_p3_equal(ge_p3* a, ge_p3* b)
{
int ret = 0;
ret |= ge_equal(a->X, b->X);
ret |= ge_equal(a->Y, b->Y);
ret |= ge_equal(a->Z, b->Z);
ret |= ge_equal(a->T, b->T);
return ret;
}
#endif
int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h, int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h,
const ge_p3 *inA,const unsigned char *sig) const ge_p3 *inA,const unsigned char *sig)
@ -526,9 +553,19 @@ int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h,
/* find H(R,A,M) * -A */ /* find H(R,A,M) * -A */
ed25519_smult(&A, &A, h); ed25519_smult(&A, &A, h);
#ifdef WOLFSSL_CHECK_VER_FAULTS
if (ge_p3_equal(&A, (ge_p3*)inA) == 0) {
ret = BAD_STATE_E;
}
#endif
/* SB + -H(R,A,M)A */ /* SB + -H(R,A,M)A */
ed25519_add(&A, &p, &A); ed25519_add(&A, &p, &A);
#ifdef WOLFSSL_CHECK_VER_FAULTS
if (ge_p3_equal(&A, &p) == 0) {
ret = BAD_STATE_E;
}
#endif
lm_copy(R->X, A.X); lm_copy(R->X, A.X);
lm_copy(R->Y, A.Y); lm_copy(R->Y, A.Y);