add wc_ecc_check_key(), import validate option too

pull/77/head
toddouska 2015-06-16 11:29:27 -07:00
parent c40dc11ce3
commit a62589f3fc
7 changed files with 193 additions and 49 deletions

View File

@ -195,6 +195,7 @@ int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* modulus,
mp_digit* mp);
static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
int map);
static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order);
#ifdef ECC_SHAMIR
static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB,
ecc_point* C, mp_int* modulus);
@ -1519,8 +1520,6 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
}
#ifdef WOLFSSL_VALIDATE_KEYGEN
/* return 1 if point is at infinity, 0 if not, < 0 on error */
static int ecc_point_is_at_infinity(ecc_point* p)
{
@ -1533,8 +1532,6 @@ static int ecc_point_is_at_infinity(ecc_point* p)
return 0;
}
#endif /* WOLFSSL_VALIDATE_KEYGEN */
int wc_ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp);
@ -1652,20 +1649,10 @@ int wc_ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
if (err == MP_OKAY)
err = ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1);
#ifdef WOLFSSL_VALIDATE_KEYGEN
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
/* validate the public key, order * pubkey = point at infinity */
if (err == MP_OKAY) {
ecc_point* inf = ecc_new_point();
if (inf == NULL)
err = MEMORY_E;
else {
err = ecc_mulmod(&order, &key->pubkey, inf, &prime, 1);
if (err == MP_OKAY && !ecc_point_is_at_infinity(inf))
err = MP_NOT_INF_E;
ecc_del_point(inf);
}
}
if (err == MP_OKAY)
err = ecc_check_pubkey_order(key, &prime, &order);
#endif /* WOLFSSL_VALIDATE_KEYGEN */
if (err == MP_OKAY)
@ -2358,32 +2345,30 @@ 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)
/* is ec point on curve descriped by dp ? */
static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime)
{
mp_int prime, b, t1, t2;
mp_int b, t1, t2;
int err;
if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL, NULL)) != MP_OKAY) {
if ((err = mp_init_multi(&b, &t1, &t2, NULL, 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);
/* load b */
err = mp_read_radix(&b, dp->Bf, 16);
/* compute y^2 */
if (err == MP_OKAY)
err = mp_sqr(key->pubkey.y, &t1);
err = mp_sqr(ecp->y, &t1);
/* compute x^3 */
if (err == MP_OKAY)
err = mp_sqr(key->pubkey.x, &t2);
err = mp_sqr(ecp->x, &t2);
if (err == MP_OKAY)
err = mp_mod(&t2, &prime, &t2);
err = mp_mod(&t2, prime, &t2);
if (err == MP_OKAY)
err = mp_mul(key->pubkey.x, &t2, &t2);
err = mp_mul(ecp->x, &t2, &t2);
/* compute y^2 - x^3 */
if (err == MP_OKAY)
@ -2391,19 +2376,19 @@ static int ecc_is_point(ecc_key* key)
/* compute y^2 - x^3 + 3x */
if (err == MP_OKAY)
err = mp_add(&t1, key->pubkey.x, &t1);
err = mp_add(&t1, ecp->x, &t1);
if (err == MP_OKAY)
err = mp_add(&t1, key->pubkey.x, &t1);
err = mp_add(&t1, ecp->x, &t1);
if (err == MP_OKAY)
err = mp_add(&t1, key->pubkey.x, &t1);
err = mp_add(&t1, ecp->x, &t1);
if (err == MP_OKAY)
err = mp_mod(&t1, &prime, &t1);
err = mp_mod(&t1, prime, &t1);
while (err == MP_OKAY && mp_cmp_d(&t1, 0) == MP_LT) {
err = mp_add(&t1, &prime, &t1);
err = mp_add(&t1, prime, &t1);
}
while (err == MP_OKAY && mp_cmp(&t1, &prime) != MP_LT) {
err = mp_sub(&t1, &prime, &t1);
while (err == MP_OKAY && mp_cmp(&t1, prime) != MP_LT) {
err = mp_sub(&t1, prime, &t1);
}
/* compare to b */
@ -2415,7 +2400,6 @@ static int ecc_is_point(ecc_key* key)
}
}
mp_clear(&prime);
mp_clear(&b);
mp_clear(&t1);
mp_clear(&t2);
@ -2424,6 +2408,146 @@ static int ecc_is_point(ecc_key* key)
}
/* validate privkey * generator == pubkey, 0 on success */
static int ecc_check_privkey_gen(ecc_key* key, mp_int* prime)
{
ecc_point* base = NULL;
ecc_point* res = NULL;
int err;
if (key == NULL)
return BAD_FUNC_ARG;
base = ecc_new_point();
if (base == NULL)
return MEMORY_E;
/* set up base generator */
err = mp_read_radix(base->x, (char*)key->dp->Gx, 16);
if (err == MP_OKAY)
err = mp_read_radix(base->y, (char*)key->dp->Gy, 16);
if (err == MP_OKAY)
mp_set(base->z, 1);
if (err == MP_OKAY) {
res = ecc_new_point();
if (res == NULL)
err = MEMORY_E;
else {
err = ecc_mulmod(&key->k, base, res, prime, 1);
if (err == MP_OKAY) {
/* compare result to public key */
if (mp_cmp(res->x, key->pubkey.x) != MP_EQ ||
mp_cmp(res->y, key->pubkey.y) != MP_EQ ||
mp_cmp(res->z, key->pubkey.z) != MP_EQ) {
/* didn't match */
err = ECC_PRIV_KEY_E;
}
}
}
}
ecc_del_point(res);
ecc_del_point(base);
return err;
}
#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
/* check privkey generator helper, creates prime needed */
static int ecc_check_privkey_gen_helper(ecc_key* key)
{
mp_int prime;
int err;
if (key == NULL)
return BAD_FUNC_ARG;
err = mp_init(&prime);
if (err != MP_OKAY)
return err;
err = mp_read_radix(&prime, (char*)key->dp->prime, 16);
if (err == MP_OKAY);
err = ecc_check_privkey_gen(key, &prime);
mp_clear(&prime);
return err;
}
#endif /* WOLFSSL_VALIDATE_ECC_IMPORT */
/* validate order * pubkey = point at infinity, 0 on success */
static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order)
{
ecc_point* inf = NULL;
int err;
if (key == NULL)
return BAD_FUNC_ARG;
inf = ecc_new_point();
if (inf == NULL)
err = MEMORY_E;
else {
err = ecc_mulmod(order, &key->pubkey, inf, prime, 1);
if (err == MP_OKAY && !ecc_point_is_at_infinity(inf))
err = ECC_INF_E;
}
ecc_del_point(inf);
return err;
}
/* perform sanity checks on ec key validity, 0 on success */
int wc_ecc_check_key(ecc_key* key)
{
mp_int prime; /* used by multiple calls so let's cache */
mp_int order; /* other callers have, so let's gen here */
int err;
if (key == NULL)
return BAD_FUNC_ARG;
/* pubkey point cannot be at inifinity */
if (ecc_point_is_at_infinity(&key->pubkey))
return ECC_INF_E;
err = mp_init_multi(&prime, &order, NULL, NULL, NULL, NULL);
if (err != MP_OKAY)
return err;
err = mp_read_radix(&prime, (char*)key->dp->prime, 16);
/* make sure point is actually on curve */
if (err == MP_OKAY)
err = ecc_is_point(key->dp, &key->pubkey, &prime);
if (err == MP_OKAY)
err = mp_read_radix(&order, (char*)key->dp->order, 16);
/* pubkey * order must be at infinity */
if (err == MP_OKAY)
err = ecc_check_pubkey_order(key, &prime, &order);
/* private * base generator must equal pubkey */
if (err == MP_OKAY && key->type == ECC_PRIVATEKEY)
err = ecc_check_privkey_gen(key, &prime);
mp_clear(&order);
mp_clear(&prime);
return err;
}
/* import public ECC key in ANSI X9.63 format */
int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
{
@ -2558,11 +2682,10 @@ 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;
}
#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
if (err == MP_OKAY)
err = wc_ecc_check_key(key);
#endif
if (err != MP_OKAY) {
mp_clear(key->pubkey.x);
@ -2610,7 +2733,14 @@ int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
key->type = ECC_PRIVATEKEY;
return mp_read_unsigned_bin(&key->k, priv, privSz);
ret = mp_read_unsigned_bin(&key->k, priv, privSz);
#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
if (ret == MP_OKAY)
ret = ecc_check_privkey_gen_helper(key);
#endif
return ret;
}
/**
@ -2722,6 +2852,11 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
err = mp_read_radix(&key->k, d, 16);
}
#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
if (err == MP_OKAY)
err = wc_ecc_check_key(key);
#endif
if (err != MP_OKAY) {
mp_clear(key->pubkey.x);
mp_clear(key->pubkey.y);

View File

@ -322,8 +322,11 @@ const char* wc_GetErrorString(int error)
case IS_POINT_E:
return "ECC is point on curve failed";
case MP_NOT_INF_E:
return " ECC point expected at infinity error";
case ECC_INF_E:
return " ECC point at infinity error";
case ECC_PRIV_KEY_E:
return " ECC private key is not valid error";
default:
return "unknown error number";

View File

@ -2638,10 +2638,9 @@ int mp_read_radix(mp_int *a, const char *str, int radix)
}
/* fast math conversion */
int mp_set(fp_int *a, fp_digit b)
void mp_set(fp_int *a, fp_digit b)
{
fp_set(a,b);
return MP_OKAY;
}
/* fast math conversion */

View File

@ -4888,6 +4888,10 @@ int ecc_test(void)
if (ret != 0)
return -1014;
ret = wc_ecc_check_key(&userA);
if (ret != 0)
return -1024;
ret = wc_ecc_make_key(&rng, 32, &userB);
if (ret != 0)

View File

@ -135,6 +135,8 @@ extern const ecc_set_type ecc_sets[];
WOLFSSL_API
int wc_ecc_make_key(RNG* rng, int keysize, ecc_key* key);
WOLFSSL_API
int wc_ecc_check_key(ecc_key* key);
WOLFSSL_API
int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
word32* outlen);
WOLFSSL_API

View File

@ -148,7 +148,8 @@ enum {
MAC_CMP_FAILED_E = -213, /* MAC comparison failed */
IS_POINT_E = -214, /* ECC is point on curve failed */
MP_NOT_INF_E = -215, /* ECC point expected at infinity error */
ECC_INF_E = -215, /* ECC point infinity error */
ECC_PRIV_KEY_E = -216, /* ECC private key not valid error */
MIN_CODE_E = -300 /* errors -101 - -299 */
};

View File

@ -684,7 +684,7 @@ void mp_rshb(mp_int *a, int x);
#ifdef HAVE_ECC
int mp_read_radix(mp_int* a, const char* str, int radix);
int mp_set(fp_int *a, fp_digit b);
void mp_set(fp_int *a, fp_digit b);
int mp_sqr(fp_int *a, fp_int *b);
int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp);
int mp_montgomery_setup(fp_int *a, fp_digit *rho);