better detection of invalid ecc keys

This commit is contained in:
toddouska
2015-05-01 14:44:43 -07:00
parent 46eca67336
commit 6db33051d3
6 changed files with 91 additions and 3 deletions

View File

@@ -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);

View File

@@ -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";

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 */
};

View File

@@ -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 */