diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index e28191730..d69002ebf 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -2415,181 +2415,22 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) #if !defined(FREESCALE_LTC_ECC) && !defined(WOLFSSL_STM32_PKA) -#if !defined(FP_ECC) || !defined(WOLFSSL_SP_MATH) -/** - Perform a point multiplication - k The scalar to multiply by - G The base point - R [out] Destination for kG - a ECC curve parameter a - modulus The modulus of the field the ECC curve is in - map Boolean whether to map back to affine or not - (1==map, 0 == leave in projective) - return MP_OKAY on success -*/ -#ifdef FP_ECC -static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, - void* heap) -#else -int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, - void* heap) -#endif -{ #ifndef WOLFSSL_SP_MATH + #ifndef ECC_TIMING_RESISTANT - /* size of sliding window, don't change this! */ - #define WINSIZE 4 - #define M_POINTS 8 - int first = 1, bitbuf = 0, bitcpy = 0, j; -#elif defined(WC_NO_CACHE_RESISTANT) - #define M_POINTS 4 -#else - #define M_POINTS 5 -#endif - ecc_point *tG, *M[M_POINTS]; - int i, err; -#ifdef WOLFSSL_SMALL_STACK_CACHE - ecc_key key; -#endif -#ifdef WOLFSSL_SMALL_STACK - mp_int* mu = NULL; -#else - mp_int mu[1]; -#endif - mp_digit mp; - mp_digit buf; - int bitcnt = 0, mode = 0, digidx = 0; +/* size of sliding window, don't change this! */ +#define WINSIZE 4 +#define M_POINTS 8 - if (k == NULL || G == NULL || R == NULL || modulus == NULL) { - return ECC_BAD_ARG_E; - } - - /* init variables */ - tG = NULL; - XMEMSET(M, 0, sizeof(M)); -#ifdef WOLFSSL_SMALL_STACK - mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); - if (mu == NULL) - return MEMORY_E; -#endif -#ifdef WOLFSSL_SMALL_STACK_CACHE - key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); - key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); -#ifdef ALT_ECC_SIZE - key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); - key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); - key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); -#endif - if (key.t1 == NULL || key.t2 == NULL -#ifdef ALT_ECC_SIZE - || key.x == NULL || key.y == NULL || key.z == NULL -#endif - ) { -#ifdef ALT_ECC_SIZE - XFREE(key.z, heap, DYNAMIC_TYPE_ECC); - XFREE(key.y, heap, DYNAMIC_TYPE_ECC); - XFREE(key.x, heap, DYNAMIC_TYPE_ECC); -#endif - XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); - XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); - XFREE(mu, heap, DYNAMIC_TYPE_ECC); - return MEMORY_E; - } -#endif /* WOLFSSL_SMALL_STACK_CACHE */ - - /* init montgomery reduction */ - if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { -#ifdef WOLFSSL_SMALL_STACK_CACHE -#ifdef ALT_ECC_SIZE - XFREE(key.z, heap, DYNAMIC_TYPE_ECC); - XFREE(key.y, heap, DYNAMIC_TYPE_ECC); - XFREE(key.x, heap, DYNAMIC_TYPE_ECC); -#endif - XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); - XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); -#endif /* WOLFSSL_SMALL_STACK_CACHE */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(mu, heap, DYNAMIC_TYPE_ECC); -#endif - return err; - } - - if ((err = mp_init(mu)) != MP_OKAY) { -#ifdef WOLFSSL_SMALL_STACK_CACHE -#ifdef ALT_ECC_SIZE - XFREE(key.z, heap, DYNAMIC_TYPE_ECC); - XFREE(key.y, heap, DYNAMIC_TYPE_ECC); - XFREE(key.x, heap, DYNAMIC_TYPE_ECC); -#endif - XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); - XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); -#endif /* WOLFSSL_SMALL_STACK_CACHE */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(mu, heap, DYNAMIC_TYPE_ECC); -#endif - return err; - } - if ((err = mp_montgomery_calc_normalization(mu, modulus)) != MP_OKAY) { - mp_clear(mu); -#ifdef WOLFSSL_SMALL_STACK_CACHE -#ifdef ALT_ECC_SIZE - XFREE(key.z, heap, DYNAMIC_TYPE_ECC); - XFREE(key.y, heap, DYNAMIC_TYPE_ECC); - XFREE(key.x, heap, DYNAMIC_TYPE_ECC); -#endif - XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); - XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); -#endif /* WOLFSSL_SMALL_STACK_CACHE */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(mu, heap, DYNAMIC_TYPE_ECC); -#endif - return err; - } - - /* alloc ram for window temps */ - for (i = 0; i < M_POINTS; i++) { - M[i] = wc_ecc_new_point_h(heap); - if (M[i] == NULL) { - mp_clear(mu); - err = MEMORY_E; goto exit; - } -#ifdef WOLFSSL_SMALL_STACK_CACHE - M[i]->key = &key; -#endif - } - - /* make a copy of G in case R==G */ - tG = wc_ecc_new_point_h(heap); - if (tG == NULL) - err = MEMORY_E; - - /* tG = G and convert to montgomery */ - if (err == MP_OKAY) { - if (mp_cmp_d(mu, 1) == MP_EQ) { - err = mp_copy(G->x, tG->x); - if (err == MP_OKAY) - err = mp_copy(G->y, tG->y); - if (err == MP_OKAY) - err = mp_copy(G->z, tG->z); - } else { - err = mp_mulmod(G->x, mu, modulus, tG->x); - if (err == MP_OKAY) - err = mp_mulmod(G->y, mu, modulus, tG->y); - if (err == MP_OKAY) - err = mp_mulmod(G->z, mu, modulus, tG->z); - } - } - - /* done with mu */ - mp_clear(mu); - -#ifdef WOLFSSL_SMALL_STACK_CACHE - R->key = &key; -#endif -#ifndef ECC_TIMING_RESISTANT +static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M, + mp_int* a, mp_int* modulus, mp_digit mp) +{ + int err = MP_OKAY; + int i; + int first = 1, bitbuf = 0, bitcpy = 0, j; + int bitcnt = 0, mode = 0, digidx = 0; + mp_digit buf; /* calc the M tab, which holds kG for k==8..15 */ /* M[0] == 8G */ @@ -2670,7 +2511,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, } if (err != MP_OKAY) break; /* out of first for(;;) */ - /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ + /* now add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ err = ecc_projective_add_point(R, M[bitbuf-M_POINTS], R, a, modulus, mp); } @@ -2718,7 +2559,24 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, #undef WINSIZE -#else /* ECC_TIMING_RESISTANT */ + return err; +} + +#else + +#if defined(WC_NO_CACHE_RESISTANT) + #define M_POINTS 4 +#else + #define M_POINTS 5 +#endif + +static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M, + mp_int* a, mp_int* modulus, mp_digit mp) +{ + int err = MP_OKAY; + int i; + int bitcnt = 0, mode = 0, digidx = 0; + mp_digit buf; /* calc the M tab */ /* M[0] == G */ @@ -2745,9 +2603,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* setup sliding window */ mode = 0; digidx = get_digit_count(modulus) - 1; - /* The order MAY be 1 bit longer than the modulus. */ - digidx += modulus->dp[digidx] >> (DIGIT_BIT-1); - bitcnt = (mp_count_bits(modulus) + 1) % DIGIT_BIT; + /* The order MAY be 1 bit longer than the modulus. + * k MAY be 1 bit longer than the order. + */ + bitcnt = (mp_count_bits(modulus) + 2) % DIGIT_BIT; + digidx += (bitcnt <= 3); buf = get_digit(k, digidx) << (DIGIT_BIT - bitcnt); bitcnt = (bitcnt + 1) % DIGIT_BIT; digidx -= bitcnt != 1; @@ -2858,8 +2718,182 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, if (err == MP_OKAY) err = mp_copy(M[0]->z, R->z); -#endif /* ECC_TIMING_RESISTANT */ + return err; +} +#endif + +#ifndef WOLFSSL_SP_MATH +/* Convert the point to montogmery form. + * + * @param [in] p Point to convert. + * @param [out] r Point in montgomery form. + * @param [in] modulus Modulus of ordinates. + * @return 0 on success. + * @return -ve on failure. + */ +static int ecc_point_to_mont(ecc_point* p, ecc_point* r, mp_int* modulus, + void* heap) +{ + int err = MP_OKAY; +#ifdef WOLFSSL_SMALL_STACK + mp_int* mu = NULL; +#else + mp_int mu[1]; +#endif + + (void)heap; + +#ifdef WOLFSSL_SMALL_STACK + mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + if (mu == NULL) + err = MEMORY_E; +#endif + if (err == MP_OKAY) + err = mp_init(mu); + if (err == MP_OKAY) { + err = mp_montgomery_calc_normalization(mu, modulus); + } + + if (err == MP_OKAY) { + if (mp_cmp_d(mu, 1) == MP_EQ) { + err = mp_copy(p->x, r->x); + if (err == MP_OKAY) + err = mp_copy(p->y, r->y); + if (err == MP_OKAY) + err = mp_copy(p->z, r->z); + } + else { + err = mp_mulmod(p->x, mu, modulus, r->x); + if (err == MP_OKAY) + err = mp_mulmod(p->y, mu, modulus, r->y); + if (err == MP_OKAY) + err = mp_mulmod(p->z, mu, modulus, r->z); + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (mu != NULL) + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif + return err; +} +#endif /* !WOLFSSL_SP_MATH */ + +#ifdef WOLFSSL_SMALL_STACK_CACHE +static int ecc_key_tmp_init(ecc_key* key, void* heap) +{ + int err = MP_OKAY; + + XMEMSET(*key, 0, sizeof(key)); + + key->t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key->t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#ifdef ALT_ECC_SIZE + key->x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key->y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key->z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#endif + if (key->t1 == NULL || key->t2 == NULL +#ifdef ALT_ECC_SIZE + || key->x == NULL || key->y == NULL || key->z == NULL +#endif + ) { + err = MEMORY_E; + } + + return err; +} + +static void ecc_key_tmp_final(ecc_key* key, void* heap) +{ +#ifdef ALT_ECC_SIZE + if (key->z != NULL) + XFREE(key->z, heap, DYNAMIC_TYPE_ECC); + if (key->y != NULL) + XFREE(key->y, heap, DYNAMIC_TYPE_ECC); + if (key->x != NULL) + XFREE(key->x, heap, DYNAMIC_TYPE_ECC); +#endif + if (key->t2 != NULL) + XFREE(key->t2, heap, DYNAMIC_TYPE_ECC); + if (key.t1 != NULL) + XFREE(key->t1, heap, DYNAMIC_TYPE_ECC); +} +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#endif /* !WOLFSSL_SP_MATH */ + +#if !defined(WOLFSSL_SP_MATH) || !defined(FP_ECC) +/** + Perform a point multiplication + k The scalar to multiply by + G The base point + R [out] Destination for kG + a ECC curve parameter a + modulus The modulus of the field the ECC curve is in + map Boolean whether to map back to affine or not + (1==map, 0 == leave in projective) + return MP_OKAY on success +*/ +#ifdef FP_ECC +static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map, void* heap) +#else +int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map, void* heap) +#endif +#ifndef WOLFSSL_SP_MATH +{ + ecc_point *tG, *M[M_POINTS]; + int i, err; +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key key; +#endif + mp_digit mp; + + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + /* init variables */ + tG = NULL; + XMEMSET(M, 0, sizeof(M)); + +#ifdef WOLFSSL_SMALL_STACK_CACHE + err = ecc_key_tmp_init(&key, heap); + if (err != MP_OKAY) + goto exit; + R->key = &key; +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + + /* alloc ram for window temps */ + for (i = 0; i < M_POINTS; i++) { + M[i] = wc_ecc_new_point_h(heap); + if (M[i] == NULL) { + err = MEMORY_E; + goto exit; + } +#ifdef WOLFSSL_SMALL_STACK_CACHE + M[i]->key = &key; +#endif + } + + /* make a copy of G in case R==G */ + tG = wc_ecc_new_point_h(heap); + if (tG == NULL) { + err = MEMORY_E; + goto exit; + } + if ((err = ecc_point_to_mont(G, tG, modulus, heap)) != MP_OKAY) { + goto exit; + } + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { + goto exit; + } + + err = ecc_mulmod(k, tG, R, M, a, modulus, mp); /* map R back from projective space */ if (err == MP_OKAY && map) err = ecc_map(R, modulus, mp); @@ -2873,20 +2907,13 @@ exit: } #ifdef WOLFSSL_SMALL_STACK_CACHE R->key = NULL; -#ifdef ALT_ECC_SIZE - XFREE(key.z, heap, DYNAMIC_TYPE_ECC); - XFREE(key.y, heap, DYNAMIC_TYPE_ECC); - XFREE(key.x, heap, DYNAMIC_TYPE_ECC); -#endif - XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); - XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + ecc_key_tmp_free(&key, heap); #endif /* WOLFSSL_SMALL_STACK_CACHE */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(mu, heap, DYNAMIC_TYPE_ECC); -#endif return err; +} #else +{ if (k == NULL || G == NULL || R == NULL || modulus == NULL) { return ECC_BAD_ARG_E; } @@ -2904,10 +2931,75 @@ exit: } #endif return ECC_BAD_ARG_E; -#endif } +#endif +#endif /* !defined(WOLFSSL_SP_MATH) && !defined(FP_ECC) */ -#endif /* !FP_ECC || !WOLFSSL_SP_MATH */ +#ifndef FP_ECC +/** + Perform a point multiplication + k The scalar to multiply by + G The base point + R [out] Destination for kG + a ECC curve parameter a + modulus The modulus of the field the ECC curve is in + map Boolean whether to map back to affine or not + (1==map, 0 == leave in projective) + return MP_OKAY on success +*/ +int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, mp_int* order, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_MATH) && defined(ECC_TIMING_RESISTANT) + int err; + mp_int t; + mp_int o; + mp_digit mask; + int i; + + if ((err = mp_init(&t)) != MP_OKAY) + return err; + if ((err = mp_init(&o)) != MP_OKAY) { + mp_free(&t); + return err; + } + + if (k == NULL || order == NULL) { + err = ECC_BAD_ARG_E; + } + + /* Make k at 1 bit longer than order. */ + if (err == MP_OKAY) { + err = mp_add(k, order, &t); + } + if (err == MP_OKAY) { + err = mp_copy(order, &o); + } + if (err == MP_OKAY) { + /* Only add if order + k has same number of bits as order */ + mask = (mp_digit)0 - (mp_count_bits(&t) == mp_count_bits(order)); + for (i = 0; i < o.used; i++) { + o.dp[i] &= mask; + } + err = mp_add(&t, &o, &t); + } + + if (err == MP_OKAY) { + err = wc_ecc_mulmod_ex(&t, G, R, a, modulus, map, heap); + } + + mp_forcezero(&t); + mp_free(&o); + mp_free(&t); + + return err; +#else + (void)order; + + return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, heap); +#endif /* !WOLFSSL_SP_MATH && ECC_TIMING_RESISTANT */ +} +#endif /* !FP_ECC */ #endif /* !FREESCALE_LTC_ECC && !WOLFSSL_STM32_PKA */ @@ -3580,8 +3672,8 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, } /* Map in a separate call as this should be constant time */ - err = wc_ecc_mulmod_ex(k, point, result, curve->Af, curve->prime, 0, - private_key->heap); + err = wc_ecc_mulmod_ex2(k, point, result, curve->Af, curve->prime, + curve->order, 0, private_key->heap); if (err == MP_OKAY) { err = mp_montgomery_setup(curve->prime, &mp); } @@ -3681,7 +3773,7 @@ int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, byte* out, word32 *outlen) { int err; - DECLARE_CURVE_SPECS(curve, 2); + DECLARE_CURVE_SPECS(curve, 3); if (private_key == NULL || point == NULL || out == NULL || outlen == NULL) { @@ -3689,9 +3781,9 @@ int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, } /* load curve info */ - ALLOC_CURVE_SPECS(2); + ALLOC_CURVE_SPECS(3); err = wc_ecc_curve_load(private_key->dp, &curve, - (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER)); if (err != MP_OKAY) { FREE_CURVE_SPECS(); return err; @@ -3964,8 +4056,8 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, /* make the public key */ if (err == MP_OKAY) { /* Map in a separate call as this should be constant time */ - err = wc_ecc_mulmod_ex(&key->k, base, pub, curve->Af, curve->prime, - 0, key->heap); + err = wc_ecc_mulmod_ex2(&key->k, base, pub, curve->Af, curve->prime, + curve->order, 0, key->heap); if (err == MP_MEM) { err = MEMORY_E; } @@ -6802,12 +6894,12 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) int err = MP_OKAY; ecc_point* base = NULL; ecc_point* res = NULL; - DECLARE_CURVE_SPECS(curve, 2); + DECLARE_CURVE_SPECS(curve, 3); if (key == NULL) return BAD_FUNC_ARG; - ALLOC_CURVE_SPECS(2); + ALLOC_CURVE_SPECS(3); res = wc_ecc_new_point_h(key->heap); if (res == NULL) @@ -6838,8 +6930,8 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) if (err == MP_OKAY) { /* load curve info */ - err = wc_ecc_curve_load(key->dp, &curve, - (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY)); + err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_GX | + ECC_CURVE_FIELD_GY | ECC_CURVE_FIELD_ORDER)); } /* set up base generator */ @@ -6851,7 +6943,8 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) err = mp_set(base->z, 1); if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&key->k, base, res, a, prime, 1, key->heap); + err = wc_ecc_mulmod_ex2(&key->k, base, res, a, prime, curve->order, + 1, key->heap); } if (err == MP_OKAY) { @@ -9588,6 +9681,163 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, #endif } +#ifndef WOLFSSL_SP_MATH +static int normal_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, + mp_int* a, mp_int* modulus, mp_int* order, + int map, void* heap) +{ + int err; + mp_int t; + mp_int o; + mp_digit mask; + int i; + + if ((err = mp_init(&t)) != MP_OKAY) + return err; + if ((err = mp_init(&o)) != MP_OKAY) { + mp_free(&t); + return err; + } + + /* Make k at 1 bit longer than order. */ + if (err == MP_OKAY) { + err = mp_add(k, order, &t); + } + if (err == MP_OKAY) { + err = mp_copy(order, &o); + } + if (err == MP_OKAY) { + /* Only add if order + k has same number of bits as order */ + mask = (mp_digit)0 - (mp_count_bits(&t) == mp_count_bits(order)); + for (i = 0; i < o.used; i++) { + o.dp[i] &= mask; + } + err = mp_add(&t, &o, &t); + } + + if (err == MP_OKAY) { + err = normal_ecc_mulmod(&t, G, R, a, modulus, map, heap); + } + + mp_forcezero(&t); + mp_free(&o); + mp_free(&t); + + return err; +} +#endif /* !WOLFSSL_SP_MATH */ + +/** ECC Fixed Point mulmod global + k The multiplicand + G Base point to multiply + R [out] Destination of product + a ECC curve parameter a + modulus The modulus for the curve + map [boolean] If non-zero maps the point back to affine coordinates, + otherwise it's left in jacobian-montgomery form + return MP_OKAY if successful +*/ +int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, mp_int* order, int map, void* heap) +{ +#ifndef WOLFSSL_SP_MATH + int idx, err = MP_OKAY; + mp_digit mp; + mp_int mu; + int mpSetup = 0; + + if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL || + order == NULL) { + return ECC_BAD_ARG_E; + } + + if (mp_init(&mu) != MP_OKAY) + return MP_INIT_E; + +#ifndef HAVE_THREAD_LS + if (initMutex == 0) { /* extra sanity check if wolfCrypt_Init not called */ + wc_InitMutex(&ecc_fp_lock); + initMutex = 1; + } + + if (wc_LockMutex(&ecc_fp_lock) != 0) + return BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + /* find point */ + idx = find_base(G); + + /* no entry? */ + if (idx == -1) { + /* find hole and add it */ + idx = find_hole(); + + if (idx >= 0) + err = add_entry(idx, G); + } + if (err == MP_OKAY && idx >= 0) { + /* increment LRU */ + ++(fp_cache[idx].lru_count); + } + + + if (err == MP_OKAY) { + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx >= 0 && fp_cache[idx].lru_count >= 2 && !fp_cache[idx].LUT_set) { + /* compute mp */ + err = mp_montgomery_setup(modulus, &mp); + + if (err == MP_OKAY) { + /* compute mu */ + mpSetup = 1; + err = mp_montgomery_calc_normalization(&mu, modulus); + } + + if (err == MP_OKAY) + /* build the LUT */ + err = build_lut(idx, a, modulus, mp, &mu); + } + } + + if (err == MP_OKAY) { + if (idx >= 0 && fp_cache[idx].LUT_set) { + if (mpSetup == 0) { + /* compute mp */ + err = mp_montgomery_setup(modulus, &mp); + } + if (err == MP_OKAY) + err = accel_fp_mul(idx, k, R, a, modulus, mp, map); + } else { + err = normal_ecc_mulmod_ex(k, G, R, a, modulus, order, map, heap); + } + } + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&ecc_fp_lock); +#endif /* HAVE_THREAD_LS */ + mp_clear(&mu); + + return err; +#else + if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL || + order == NULL) { + return ECC_BAD_ARG_E; + } + +#ifndef WOLFSSL_SP_NO_256 + if (mp_count_bits(modulus) == 256) { + return sp_ecc_mulmod_256(k, G, R, map, heap); + } +#endif +#ifdef WOLFSSL_SP_384 + if (mp_count_bits(modulus) == 384) { + return sp_ecc_mulmod_384(k, G, R, map, heap); + } +#endif + return WC_KEY_SIZE_E; +#endif +} + #ifndef WOLFSSL_SP_MATH /* helper function for freeing the cache ... must be called with the cache mutex locked */ diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 930b96199..fe9bb489a 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -600,6 +600,9 @@ int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, WOLFSSL_LOCAL int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map, void* heap); +WOLFSSL_LOCAL +int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, mp_int* order, int map, void* heap); #endif /* !WOLFSSL_ATECC508A */