Reworked ECC mulmod and fix size of k

When using wc_ecc_mulmod_ex2(), the k size can be fixed to be one bit
longer than order.
This commit is contained in:
Sean Parkinson
2020-06-09 12:26:05 +10:00
parent 9ef9671886
commit 8b05160349
2 changed files with 454 additions and 201 deletions

View File

@ -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
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;
#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;
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
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 /* !defined(WOLFSSL_SP_MATH) && !defined(FP_ECC) */
#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;
}
#endif /* !FP_ECC || !WOLFSSL_SP_MATH */
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 */

View File

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