Fixes to reduce stack usage with ECC_CACHE_CURVE disabled (same as previous code). Added USE_ECC_B_PARAM macro (enabled with ECC_CACHE_CURVE or HAVE_COMP_KEY). Fixed bug with WOLFSSL_VALIDATE_ECC_KEYGEN defined and args to ecc_check_pubkey_order. Fixed counts for DECLARE_CURVE_SPECS(). Fixed wc_ecc_import_point_der to use curve cache. Enhance wc_ecc_check_key to support ECC_CACHE_CURVE for b or load using read_radix. Enhance to expose wc_ecc_is_point with all required mp_int* args directly.

This commit is contained in:
David Garske
2017-01-09 11:15:13 -08:00
parent 07ce995b12
commit 0722f4d20f
2 changed files with 87 additions and 42 deletions

View File

@ -46,6 +46,8 @@ Possible ECC enable options:
* ECC_CACHE_CURVE: Enables cache of curve info to improve perofrmance
default: off
* FP_ECC: ECC Fixed Point Cache default: off
* USE_ECC_B_PARAM: Enable ECC curve B param default: off
(on for HAVE_COMP_KEY)
*/
/*
@ -970,7 +972,9 @@ typedef struct ecc_curve_spec {
mp_int* prime;
mp_int* Af;
mp_int* Bf;
#ifdef USE_ECC_B_PARAM
mp_int* Bf;
#endif
mp_int* order;
mp_int* Gx;
mp_int* Gy;
@ -978,7 +982,9 @@ typedef struct ecc_curve_spec {
#ifdef ECC_CACHE_CURVE
mp_int prime_lcl;
mp_int Af_lcl;
mp_int Bf_lcl;
#ifdef USE_ECC_B_PARAM
mp_int Bf_lcl;
#endif
mp_int order_lcl;
mp_int Gx_lcl;
mp_int Gy_lcl;
@ -995,11 +1001,19 @@ enum ecc_curve_load_mask {
ECC_CURVE_FIELD_NONE = 0x00,
ECC_CURVE_FIELD_PRIME = 0x01,
ECC_CURVE_FIELD_AF = 0x02,
#ifdef USE_ECC_B_PARAM
ECC_CURVE_FIELD_BF = 0x04,
#endif
ECC_CURVE_FIELD_ORDER = 0x08,
ECC_CURVE_FIELD_GX = 0x10,
ECC_CURVE_FIELD_GY = 0x20,
ECC_CURVE_FIELD_ALL = 0x3F
#ifdef USE_ECC_B_PARAM
ECC_CURVE_FIELD_ALL = 0x3F,
ECC_CURVE_FIELD_COUNT = 6,
#else
ECC_CURVE_FIELD_ALL = 0x3B,
ECC_CURVE_FIELD_COUNT = 5,
#endif
};
#ifdef ECC_CACHE_CURVE
@ -1029,8 +1043,10 @@ static void _wc_ecc_curve_free(ecc_curve_spec* curve)
mp_clear(curve->prime);
if (curve->load_mask & ECC_CURVE_FIELD_AF)
mp_clear(curve->Af);
#ifdef USE_ECC_B_PARAM
if (curve->load_mask & ECC_CURVE_FIELD_BF)
mp_clear(curve->Bf);
#endif
if (curve->load_mask & ECC_CURVE_FIELD_ORDER)
mp_clear(curve->order);
if (curve->load_mask & ECC_CURVE_FIELD_GX)
@ -1114,7 +1130,9 @@ static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve,
#ifdef ECC_CACHE_CURVE
curve->prime = &curve->prime_lcl;
curve->Af = &curve->Af_lcl;
curve->Bf = &curve->Bf_lcl;
#ifdef USE_ECC_B_PARAM
curve->Bf = &curve->Bf_lcl;
#endif
curve->order = &curve->order_lcl;
curve->Gx = &curve->Gx_lcl;
curve->Gy = &curve->Gy_lcl;
@ -1133,9 +1151,11 @@ static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve,
if (load_items & ECC_CURVE_FIELD_AF)
x += wc_ecc_curve_load_item(dp->Af, &curve->Af, curve,
ECC_CURVE_FIELD_AF);
#ifdef USE_ECC_B_PARAM
if (load_items & ECC_CURVE_FIELD_BF)
x += wc_ecc_curve_load_item(dp->Bf, &curve->Bf, curve,
ECC_CURVE_FIELD_BF);
#endif
if (load_items & ECC_CURVE_FIELD_ORDER)
x += wc_ecc_curve_load_item(dp->order, &curve->order, curve,
ECC_CURVE_FIELD_ORDER);
@ -2713,7 +2733,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id)
int err;
#ifndef WOLFSSL_ATECC508A
ecc_point* base = NULL;
DECLARE_CURVE_SPECS(6)
DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT)
#endif
if (key == NULL || rng == NULL) {
@ -2798,8 +2818,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id)
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
/* validate the public key, order * pubkey = point at infinity */
if (err == MP_OKAY)
err = ecc_check_pubkey_order(key, curve->Af, curve->Bf, curve->prime,
curve->order);
err = ecc_check_pubkey_order(key, curve->Af, curve->prime, curve->order);
#endif /* WOLFSSL_VALIDATE_KEYGEN */
if (err == MP_OKAY)
@ -3615,7 +3634,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
mp_int u1;
mp_int u2;
mp_int e;
DECLARE_CURVE_SPECS(6)
DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT)
#else
byte sigRS[ATECC_KEY_SIZE*2];
#endif
@ -3840,61 +3859,58 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
#ifdef HAVE_COMP_KEY
if (err == MP_OKAY && compressed == 1) { /* build y */
mp_int t1, t2, prime, a, b;
mp_int t1, t2;
DECLARE_CURVE_SPECS(3)
int did_init = 0;
if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY)
if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY)
err = MEMORY_E;
else
did_init = 1;
/* read in the specs for this curve */
if (err == MP_OKAY)
err = mp_read_radix(&prime, ecc_sets[curve_idx].prime, 16);
if (err == MP_OKAY)
err = mp_read_radix(&a, ecc_sets[curve_idx].Af, 16);
if (err == MP_OKAY)
err = mp_read_radix(&b, ecc_sets[curve_idx].Bf, 16);
/* load curve info */
err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve,
(ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_BF));
/* compute x^3 */
if (err == MP_OKAY)
err = mp_sqr(point->x, &t1);
if (err == MP_OKAY)
err = mp_mulmod(&t1, point->x, &prime, &t1);
err = mp_mulmod(&t1, point->x, curve->prime, &t1);
/* compute x^3 + a*x */
if (err == MP_OKAY)
err = mp_mulmod(&a, point->x, &prime, &t2);
err = mp_mulmod(curve->Af, point->x, curve->prime, &t2);
if (err == MP_OKAY)
err = mp_add(&t1, &t2, &t1);
/* compute x^3 + a*x + b */
if (err == MP_OKAY)
err = mp_add(&t1, &b, &t1);
err = mp_add(&t1, curve->Bf, &t1);
/* compute sqrt(x^3 + a*x + b) */
if (err == MP_OKAY)
err = mp_sqrtmod_prime(&t1, &prime, &t2);
err = mp_sqrtmod_prime(&t1, curve->prime, &t2);
/* adjust y */
if (err == MP_OKAY) {
if ((mp_isodd(&t2) == MP_YES && in[0] == 0x03) ||
(mp_isodd(&t2) == MP_NO && in[0] == 0x02)) {
err = mp_mod(&t2, &prime, point->y);
err = mp_mod(&t2, curve->prime, point->y);
}
else {
err = mp_submod(&prime, &t2, &prime, point->y);
err = mp_submod(curve->prime, &t2, curve->prime, point->y);
}
}
if (did_init) {
#ifndef USE_FAST_MATH
mp_clear(&a);
mp_clear(&b);
mp_clear(&prime);
#ifndef USE_FAST_MATH
mp_clear(&t2);
mp_clear(&t1);
#endif
#endif
wc_ecc_curve_free(curve);
}
}
#endif
@ -4098,20 +4114,15 @@ int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen,
#ifndef WOLFSSL_ATECC508A
/* is ecc point on curve described by dp ? */
static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime)
int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime)
{
mp_int a, b, t1, t2;
int err;
mp_int t1, t2;
if ((err = mp_init_multi(&a, &b, &t1, &t2, NULL, NULL)) != MP_OKAY) {
if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
return err;
}
/* read in the specs for this curve */
err = mp_read_radix(&a, dp->Af, 16);
if (err == MP_OKAY)
err = mp_read_radix(&b, dp->Bf, 16);
/* compute y^2 */
if (err == MP_OKAY)
err = mp_sqr(ecp->y, &t1);
@ -4133,7 +4144,7 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime)
if (err == MP_OKAY) {
/* Use a and prime to determine if a == 3 */
mp_set(&t2, 0);
err = mp_submod(prime, &a, prime, &t2);
err = mp_submod(prime, a, prime, &t2);
}
if (err == MP_OKAY && mp_cmp_d(&t2, 3) != MP_EQ) {
/* compute y^2 - x^3 + a*x */
@ -4169,7 +4180,7 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime)
/* compare to b */
if (err == MP_OKAY) {
if (mp_cmp(&t1, &b) != MP_EQ) {
if (mp_cmp(&t1, b) != MP_EQ) {
err = MP_VAL;
} else {
err = MP_OKAY;
@ -4177,8 +4188,6 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime)
}
#ifndef USE_FAST_MATH
mp_clear(&a);
mp_clear(&b);
mp_clear(&t1);
mp_clear(&t2);
#endif
@ -4307,7 +4316,15 @@ int wc_ecc_check_key(ecc_key* key)
{
int err;
#ifndef WOLFSSL_ATECC508A
mp_int* b;
#ifdef USE_ECC_B_PARAM
DECLARE_CURVE_SPECS(4)
#else
mp_int b_lcl;
DECLARE_CURVE_SPECS(3)
b = &b_lcl;
XMEMSET(b, 0, sizeof(mp_int));
#endif
#endif /* WOLFSSL_ATECC508A */
if (key == NULL)
@ -4325,11 +4342,25 @@ int wc_ecc_check_key(ecc_key* key)
/* load curve info */
err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME |
ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_BF | ECC_CURVE_FIELD_ORDER));
ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER
#ifdef USE_ECC_B_PARAM
| ECC_CURVE_FIELD_BF
#endif
));
#ifndef USE_ECC_B_PARAM
/* load curve b parameter */
if (err == MP_OKAY)
err = mp_init(b);
if (err == MP_OKAY)
err = mp_read_radix(b, key->dp->Bf, 16);
#else
b = curve->Bf;
#endif
/* make sure point is actually on curve */
if (err == MP_OKAY)
err = ecc_is_point(key->dp, &key->pubkey, curve->prime);
err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime);
/* pubkey * order must be at infinity */
if (err == MP_OKAY)
@ -4341,6 +4372,10 @@ int wc_ecc_check_key(ecc_key* key)
wc_ecc_curve_free(curve);
#ifndef USE_ECC_B_PARAM
mp_clear(b);
#endif
#endif /* WOLFSSL_ATECC508A */
return err;

View File

@ -48,6 +48,14 @@
#endif
/* Enable curve B parameter if needed */
#if defined(HAVE_COMP_KEY) || defined(ECC_CACHE_CURVE)
#ifndef USE_ECC_B_PARAM /* Allow someone to force enable */
#define USE_ECC_B_PARAM
#endif
#endif
/* Use this as the key->idx if a custom ecc_set is used for key->dp */
#define ECC_CUSTOM_IDX (-1)
@ -278,6 +286,8 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key,
int curve_id);
WOLFSSL_API
int wc_ecc_check_key(ecc_key* key);
WOLFSSL_API
int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime);
#ifdef HAVE_ECC_DHE
WOLFSSL_API