Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add option for additional sanity checks #8289

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2357,6 +2357,16 @@ else
AM_CFLAGS="$AM_CFLAGS -DWC_NO_HARDEN -DWC_NO_CACHE_RESISTANT"
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
AC_ARG_ENABLE([ipv6],
Expand Down
69 changes: 69 additions & 0 deletions wolfcrypt/src/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ Possible ECC enable options:
* unmasked copy is computed and stored each time it is
* needed.
* default: off
* WOLFSSL_CHECK_VER_FAULTS
* Sanity check on verification steps in case of faults.
* default: off
*/

/*
Expand Down Expand Up @@ -8970,13 +8973,28 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
#endif

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;
u2 = w;
#endif
v = w;
}
if (err == MP_OKAY) {
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 */
if (err == MP_OKAY) {
Expand All @@ -9000,10 +9018,22 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
if (err == MP_OKAY)
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 */
if (err == MP_OKAY)
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 */
if (err == MP_OKAY)
err = mp_copy(curve->Gx, mG->x);
Expand Down Expand Up @@ -9031,16 +9061,35 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
#ifndef ECC_SHAMIR
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;

if (!mp_iszero((MP_INT_SIZE*)u1)) {
/* compute u1*mG + u2*mQ = mG */
err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0,
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) {
err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0,
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 */
if (err == MP_OKAY)
Expand All @@ -9050,6 +9099,14 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
if (err == MP_OKAY)
err = ecc_projective_add_point_safe(mQ, mG, mG, curve->Af,
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 {
/* compute 0*mG + u2*mQ = mG */
Expand All @@ -9072,6 +9129,7 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
}
#endif /* ECC_SHAMIR */
#endif /* FREESCALE_LTC_ECC */

/* v = X_x1 mod n */
if (err == MP_OKAY)
err = mp_mod(mG->x, curve->order, v);
Expand All @@ -9080,6 +9138,11 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
if (err == MP_OKAY) {
if (mp_cmp(v, r) == MP_EQ)
*res = 1;
#ifdef WOLFSSL_CHECK_VER_FAULTS
/* redundant comparison as sanity check that first one happened */
if (*res == 1 && mp_cmp(r, v) != MP_EQ)
*res = 0;
#endif
}

/* cleanup */
Expand All @@ -9089,6 +9152,12 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
mp_clear(e);
mp_clear(w);
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)
FREE_MP_INT_SIZE(e_lcl, key->heap, DYNAMIC_TYPE_ECC);
#endif
Expand Down
57 changes: 56 additions & 1 deletion wolfcrypt/src/ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

#include <wolfssl/wolfcrypt/ed25519.h>
#include <wolfssl/wolfcrypt/ge_operations.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/hash.h>
#ifdef NO_INLINE
Expand Down Expand Up @@ -628,6 +629,35 @@ int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,

#ifdef HAVE_ED25519_VERIFY
#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
sigLen is the length of sig byte array
Expand Down Expand Up @@ -675,6 +705,22 @@ static int ed25519_verify_msg_init_with_sha(const byte* sig, word32 sigLen,
}
if (ret == 0)
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)
ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE);

Expand Down Expand Up @@ -791,7 +837,16 @@ static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen,
ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2);
if (ret != 0) {
ret = SIG_VERIFY_E;
} else {
}

#ifdef WOLFSSL_CHECK_VER_FAULTS
/* redundant comparison as sanity check that first one happened */
if (ret == 0 && ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2) != 0) {
ret = SIG_VERIFY_E;
}
#endif

if (ret == 0) {
/* set the verification status */
*res = 1;
}
Expand Down
37 changes: 37 additions & 0 deletions wolfcrypt/src/ge_low_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,33 @@ int ge_frombytes_negate_vartime(ge_p3 *p,const unsigned char *s)
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,
const ge_p3 *inA,const unsigned char *sig)
Expand All @@ -526,9 +553,19 @@ int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h,

/* find H(R,A,M) * -A */
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 */
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->Y, A.Y);
Expand Down
7 changes: 7 additions & 0 deletions wolfcrypt/src/ge_operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -9467,6 +9467,13 @@ int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a,
ge_p1p1_to_p2(r,t);
}

#ifdef WOLFSSL_CHECK_VER_FAULTS
if (i != -1) {
/* did not go through whole loop */
return BAD_STATE_E;
}
#endif

#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
out:

Expand Down
Loading