From 6db33051d3054ca96a2a44f886de4581c87e2b3f Mon Sep 17 00:00:00 2001 From: toddouska Date: Fri, 1 May 2015 14:44:43 -0700 Subject: [PATCH] better detection of invalid ecc keys --- wolfcrypt/src/ecc.c | 77 +++++++++++++++++++++++++++++++++ wolfcrypt/src/error.c | 3 ++ wolfcrypt/src/integer.c | 6 ++- wolfcrypt/src/tfm.c | 5 ++- wolfssl/wolfcrypt/error-crypt.h | 1 + wolfssl/wolfcrypt/tfm.h | 2 +- 6 files changed, 91 insertions(+), 3 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index a4c8adc5a..82b74bf5f 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -1734,9 +1734,14 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, /* make up a key and export the public copy */ if (err == MP_OKAY) { + int loop_check = 0; ecc_key pubkey; wc_ecc_init(&pubkey); for (;;) { + if (++loop_check > 64) { + err = RNG_FAILURE_E; + break; + } err = wc_ecc_make_key_ex(rng, &pubkey, key->dp); if (err != MP_OKAY) break; @@ -2311,6 +2316,72 @@ int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, int compresse } +/* is pubkey point on curve ? */ +static int ecc_is_point(ecc_key* key) +{ + mp_int prime, b, t1, t2; + int err; + + if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL, NULL)) != MP_OKAY) { + return err; + } + + /* load prime and b */ + err = mp_read_radix(&prime, key->dp->prime, 16); + if (err == MP_OKAY) + err = mp_read_radix(&b, key->dp->Bf, 16); + + /* compute y^2 */ + if (err == MP_OKAY) + err = mp_sqr(key->pubkey.y, &t1); + + /* compute x^3 */ + if (err == MP_OKAY) + err = mp_sqr(key->pubkey.x, &t2); + if (err == MP_OKAY) + err = mp_mod(&t2, &prime, &t2); + if (err == MP_OKAY) + err = mp_mul(key->pubkey.x, &t2, &t2); + + /* compute y^2 - x^3 */ + if (err == MP_OKAY) + err = mp_sub(&t1, &t2, &t1); + + /* compute y^2 - x^3 + 3x */ + if (err == MP_OKAY) + err = mp_add(&t1, key->pubkey.x, &t1); + if (err == MP_OKAY) + err = mp_add(&t1, key->pubkey.x, &t1); + if (err == MP_OKAY) + err = mp_add(&t1, key->pubkey.x, &t1); + if (err == MP_OKAY) + err = mp_mod(&t1, &prime, &t1); + + while (err == MP_OKAY && mp_cmp_d(&t1, 0) == MP_LT) { + err = mp_add(&t1, &prime, &t1); + } + while (err == MP_OKAY && mp_cmp(&t1, &prime) != MP_LT) { + err = mp_sub(&t1, &prime, &t1); + } + + /* compare to b */ + if (err == MP_OKAY) { + if (mp_cmp(&t1, &b) != MP_EQ) { + err = MP_VAL; + } else { + err = MP_OKAY; + } + } + + mp_clear(&prime); + mp_clear(&b); + mp_clear(&t1); + mp_clear(&t2); + + return err; +} + + /* import public ECC key in ANSI X9.63 format */ int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) { @@ -2445,6 +2516,12 @@ int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) if (err == MP_OKAY) mp_set(key->pubkey.z, 1); + if (err == MP_OKAY) { + err = ecc_is_point(key); + if (err != MP_OKAY) + err = IS_POINT_E; + } + if (err != MP_OKAY) { mp_clear(key->pubkey.x); mp_clear(key->pubkey.y); diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 48da1ba40..dc2917e0d 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -319,6 +319,9 @@ const char* wc_GetErrorString(int error) case MAC_CMP_FAILED_E: return "MAC comparison failed"; + case IS_POINT_E: + return "ECC is point on curve failed"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index b68ec7ea7..eaf538283 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -866,7 +866,7 @@ int mp_invmod (mp_int * a, mp_int * b, mp_int * c) int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) { mp_int x, y, u, v, B, D; - int res, neg; + int res, neg, loop_check = 0; /* 2. [modified] b must be odd */ if (mp_iseven (b) == 1) { @@ -958,6 +958,10 @@ top: /* if not zero goto step 4 */ if (mp_iszero (&u) == 0) { + if (++loop_check > 1024) { + res = MP_VAL; + goto LBL_ERR; + } goto top; } diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 994fcc9ae..526891772 100755 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -863,11 +863,12 @@ top: return FP_OKAY; } + /* c = 1/a (mod b) for odd b only */ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) { fp_int x, y, u, v, B, D; - int neg; + int neg, loop_check = 0; /* 2. [modified] b must be odd */ if (fp_iseven (b) == FP_YES) { @@ -931,6 +932,8 @@ top: /* if not zero goto step 4 */ if (fp_iszero (&u) == FP_NO) { + if (++loop_check > 1024) /* bad input */ + return FP_VAL; goto top; } diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index e172e6aec..65eb9eed8 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -147,6 +147,7 @@ enum { THREAD_STORE_SET_E = -212, /* Thread local storage key set failure */ MAC_CMP_FAILED_E = -213, /* MAC comparison failed */ + IS_POINT_E = -214, /* ECC is point on curve failed */ MIN_CODE_E = -300 /* errors -101 - -299 */ }; diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index a928a2ac6..6c8969307 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -366,7 +366,7 @@ typedef struct { /* zero/even/odd ? */ #define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO) -#define fp_iseven(a) (((a)->used >= 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO) +#define fp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO) #define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO) /* set to a small digit */