mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 18:57:27 +02:00
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:
@ -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(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 WOLFSSL_SP_MATH
|
||||||
|
|
||||||
#ifndef ECC_TIMING_RESISTANT
|
#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];
|
/* size of sliding window, don't change this! */
|
||||||
int i, err;
|
#define WINSIZE 4
|
||||||
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
#define M_POINTS 8
|
||||||
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) {
|
static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M,
|
||||||
return ECC_BAD_ARG_E;
|
mp_int* a, mp_int* modulus, mp_digit mp)
|
||||||
}
|
{
|
||||||
|
int err = MP_OKAY;
|
||||||
/* init variables */
|
int i;
|
||||||
tG = NULL;
|
int first = 1, bitbuf = 0, bitcpy = 0, j;
|
||||||
XMEMSET(M, 0, sizeof(M));
|
int bitcnt = 0, mode = 0, digidx = 0;
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
mp_digit buf;
|
||||||
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
|
|
||||||
|
|
||||||
/* calc the M tab, which holds kG for k==8..15 */
|
/* calc the M tab, which holds kG for k==8..15 */
|
||||||
/* M[0] == 8G */
|
/* 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(;;) */
|
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,
|
err = ecc_projective_add_point(R, M[bitbuf-M_POINTS], R, a,
|
||||||
modulus, mp);
|
modulus, mp);
|
||||||
}
|
}
|
||||||
@ -2718,7 +2559,24 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
|
|||||||
|
|
||||||
#undef WINSIZE
|
#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 */
|
/* calc the M tab */
|
||||||
/* M[0] == G */
|
/* M[0] == G */
|
||||||
@ -2745,9 +2603,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
|
|||||||
/* setup sliding window */
|
/* setup sliding window */
|
||||||
mode = 0;
|
mode = 0;
|
||||||
digidx = get_digit_count(modulus) - 1;
|
digidx = get_digit_count(modulus) - 1;
|
||||||
/* The order MAY be 1 bit longer than the modulus. */
|
/* The order MAY be 1 bit longer than the modulus.
|
||||||
digidx += modulus->dp[digidx] >> (DIGIT_BIT-1);
|
* k MAY be 1 bit longer than the order.
|
||||||
bitcnt = (mp_count_bits(modulus) + 1) % DIGIT_BIT;
|
*/
|
||||||
|
bitcnt = (mp_count_bits(modulus) + 2) % DIGIT_BIT;
|
||||||
|
digidx += (bitcnt <= 3);
|
||||||
buf = get_digit(k, digidx) << (DIGIT_BIT - bitcnt);
|
buf = get_digit(k, digidx) << (DIGIT_BIT - bitcnt);
|
||||||
bitcnt = (bitcnt + 1) % DIGIT_BIT;
|
bitcnt = (bitcnt + 1) % DIGIT_BIT;
|
||||||
digidx -= bitcnt != 1;
|
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)
|
if (err == MP_OKAY)
|
||||||
err = mp_copy(M[0]->z, R->z);
|
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 */
|
/* map R back from projective space */
|
||||||
if (err == MP_OKAY && map)
|
if (err == MP_OKAY && map)
|
||||||
err = ecc_map(R, modulus, mp);
|
err = ecc_map(R, modulus, mp);
|
||||||
@ -2873,20 +2907,13 @@ exit:
|
|||||||
}
|
}
|
||||||
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
||||||
R->key = NULL;
|
R->key = NULL;
|
||||||
#ifdef ALT_ECC_SIZE
|
ecc_key_tmp_free(&key, heap);
|
||||||
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 */
|
#endif /* WOLFSSL_SMALL_STACK_CACHE */
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
|
||||||
XFREE(mu, heap, DYNAMIC_TYPE_ECC);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
{
|
||||||
if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
|
if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
|
||||||
return ECC_BAD_ARG_E;
|
return ECC_BAD_ARG_E;
|
||||||
}
|
}
|
||||||
@ -2904,10 +2931,75 @@ exit:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ECC_BAD_ARG_E;
|
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 */
|
#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 */
|
/* Map in a separate call as this should be constant time */
|
||||||
err = wc_ecc_mulmod_ex(k, point, result, curve->Af, curve->prime, 0,
|
err = wc_ecc_mulmod_ex2(k, point, result, curve->Af, curve->prime,
|
||||||
private_key->heap);
|
curve->order, 0, private_key->heap);
|
||||||
if (err == MP_OKAY) {
|
if (err == MP_OKAY) {
|
||||||
err = mp_montgomery_setup(curve->prime, &mp);
|
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)
|
byte* out, word32 *outlen)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
DECLARE_CURVE_SPECS(curve, 2);
|
DECLARE_CURVE_SPECS(curve, 3);
|
||||||
|
|
||||||
if (private_key == NULL || point == NULL || out == NULL ||
|
if (private_key == NULL || point == NULL || out == NULL ||
|
||||||
outlen == NULL) {
|
outlen == NULL) {
|
||||||
@ -3689,9 +3781,9 @@ int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* load curve info */
|
/* load curve info */
|
||||||
ALLOC_CURVE_SPECS(2);
|
ALLOC_CURVE_SPECS(3);
|
||||||
err = wc_ecc_curve_load(private_key->dp, &curve,
|
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) {
|
if (err != MP_OKAY) {
|
||||||
FREE_CURVE_SPECS();
|
FREE_CURVE_SPECS();
|
||||||
return err;
|
return err;
|
||||||
@ -3964,8 +4056,8 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
|
|||||||
/* make the public key */
|
/* make the public key */
|
||||||
if (err == MP_OKAY) {
|
if (err == MP_OKAY) {
|
||||||
/* Map in a separate call as this should be constant time */
|
/* Map in a separate call as this should be constant time */
|
||||||
err = wc_ecc_mulmod_ex(&key->k, base, pub, curve->Af, curve->prime,
|
err = wc_ecc_mulmod_ex2(&key->k, base, pub, curve->Af, curve->prime,
|
||||||
0, key->heap);
|
curve->order, 0, key->heap);
|
||||||
if (err == MP_MEM) {
|
if (err == MP_MEM) {
|
||||||
err = MEMORY_E;
|
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;
|
int err = MP_OKAY;
|
||||||
ecc_point* base = NULL;
|
ecc_point* base = NULL;
|
||||||
ecc_point* res = NULL;
|
ecc_point* res = NULL;
|
||||||
DECLARE_CURVE_SPECS(curve, 2);
|
DECLARE_CURVE_SPECS(curve, 3);
|
||||||
|
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
ALLOC_CURVE_SPECS(2);
|
ALLOC_CURVE_SPECS(3);
|
||||||
|
|
||||||
res = wc_ecc_new_point_h(key->heap);
|
res = wc_ecc_new_point_h(key->heap);
|
||||||
if (res == NULL)
|
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) {
|
if (err == MP_OKAY) {
|
||||||
/* load curve info */
|
/* load curve info */
|
||||||
err = wc_ecc_curve_load(key->dp, &curve,
|
err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_GX |
|
||||||
(ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY));
|
ECC_CURVE_FIELD_GY | ECC_CURVE_FIELD_ORDER));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set up base generator */
|
/* 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);
|
err = mp_set(base->z, 1);
|
||||||
|
|
||||||
if (err == MP_OKAY)
|
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) {
|
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
|
#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
|
#ifndef WOLFSSL_SP_MATH
|
||||||
/* helper function for freeing the cache ...
|
/* helper function for freeing the cache ...
|
||||||
must be called with the cache mutex locked */
|
must be called with the cache mutex locked */
|
||||||
|
@ -600,6 +600,9 @@ int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
|
|||||||
WOLFSSL_LOCAL
|
WOLFSSL_LOCAL
|
||||||
int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
|
int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
|
||||||
mp_int* a, mp_int* modulus, int map, void* heap);
|
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 */
|
#endif /* !WOLFSSL_ATECC508A */
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user