forked from wolfSSL/wolfssl
Merge pull request #2859 from SparkiDev/tfm_ec_invmod_ct
Constant time EC map to affine for private operations
This commit is contained in:
@ -2285,9 +2285,10 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a,
|
||||
P [in/out] The point to map
|
||||
modulus The modulus of the field the ECC curve is in
|
||||
mp The "b" value from montgomery_setup()
|
||||
ct Operation should be constant time.
|
||||
return MP_OKAY on success
|
||||
*/
|
||||
int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp)
|
||||
int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct)
|
||||
{
|
||||
#ifndef WOLFSSL_SP_MATH
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
@ -2307,6 +2308,8 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp)
|
||||
mp_int *x, *y, *z;
|
||||
int err;
|
||||
|
||||
(void)ct;
|
||||
|
||||
if (P == NULL || modulus == NULL)
|
||||
return ECC_BAD_ARG_E;
|
||||
|
||||
@ -2402,12 +2405,23 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp)
|
||||
z = P->z;
|
||||
#endif
|
||||
|
||||
/* first map z back to normal */
|
||||
err = mp_montgomery_reduce(z, modulus, mp);
|
||||
|
||||
/* get 1/z */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_invmod(z, modulus, t1);
|
||||
if (err == MP_OKAY) {
|
||||
#if defined(ECC_TIMING_RESISTANT) && defined(USE_FAST_MATH)
|
||||
if (ct) {
|
||||
err = mp_invmod_mont_ct(z, modulus, t1, mp);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_montgomery_reduce(t1, modulus, mp);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* first map z back to normal */
|
||||
err = mp_montgomery_reduce(z, modulus, mp);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_invmod(z, modulus, t1);
|
||||
}
|
||||
}
|
||||
|
||||
/* get 1/z^2 and 1/z^3 */
|
||||
if (err == MP_OKAY)
|
||||
@ -2484,6 +2498,10 @@ done:
|
||||
#endif
|
||||
}
|
||||
|
||||
int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp)
|
||||
{
|
||||
return ecc_map_ex(P, modulus, mp, 0);
|
||||
}
|
||||
#endif /* !WOLFSSL_SP_MATH || WOLFSSL_PUBLIC_ECC_ADD_DBL */
|
||||
|
||||
#if !defined(FREESCALE_LTC_ECC) && !defined(WOLFSSL_STM32_PKA)
|
||||
@ -3639,6 +3657,8 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point,
|
||||
}
|
||||
#else
|
||||
{
|
||||
mp_digit mp = 0;
|
||||
|
||||
/* make new point */
|
||||
result = wc_ecc_new_point_h(private_key->heap);
|
||||
if (result == NULL) {
|
||||
@ -3649,8 +3669,16 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point,
|
||||
return MEMORY_E;
|
||||
}
|
||||
|
||||
err = wc_ecc_mulmod_ex(k, point, result, curve->Af, curve->prime, 1,
|
||||
/* 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);
|
||||
if (err == MP_OKAY) {
|
||||
err = mp_montgomery_setup(curve->prime, &mp);
|
||||
}
|
||||
if (err == MP_OKAY) {
|
||||
/* Use constant time map if compiled in */
|
||||
err = ecc_map_ex(result, curve->prime, mp, 1);
|
||||
}
|
||||
if (err == MP_OKAY) {
|
||||
x = mp_unsigned_bin_size(curve->prime);
|
||||
if (*outlen < x || (int)x < mp_unsigned_bin_size(result->x)) {
|
||||
@ -4008,6 +4036,8 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
|
||||
err = WC_KEY_SIZE_E;
|
||||
#else
|
||||
{
|
||||
mp_digit mp;
|
||||
|
||||
if (err == MP_OKAY) {
|
||||
base = wc_ecc_new_point_h(key->heap);
|
||||
if (base == NULL)
|
||||
@ -4023,12 +4053,20 @@ 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,
|
||||
1, key->heap);
|
||||
0, key->heap);
|
||||
if (err == MP_MEM) {
|
||||
err = MEMORY_E;
|
||||
}
|
||||
}
|
||||
if (err == MP_OKAY) {
|
||||
err = mp_montgomery_setup(curve->prime, &mp);
|
||||
}
|
||||
if (err == MP_OKAY) {
|
||||
/* Use constant time map if compiled in */
|
||||
err = ecc_map_ex(pub, curve->prime, mp, 1);
|
||||
}
|
||||
|
||||
wc_ecc_del_point_h(base, key->heap);
|
||||
}
|
||||
|
@ -1160,6 +1160,75 @@ top:
|
||||
return FP_OKAY;
|
||||
}
|
||||
|
||||
#define CT_INV_MOD_PRE_CNT 8
|
||||
|
||||
/* modulus (b) must be greater than 2 and a prime */
|
||||
int fp_invmod_mont_ct(fp_int *a, fp_int *b, fp_int *c, fp_digit mp)
|
||||
{
|
||||
int i, j;
|
||||
#ifndef WOLFSSL_SMALL_STACK
|
||||
fp_int t[1], e[1];
|
||||
fp_int pre[CT_INV_MOD_PRE_CNT];
|
||||
#else
|
||||
fp_int* t;
|
||||
fp_int* e;
|
||||
fp_int* pre;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
t = (fp_int*)XMALLOC(sizeof(fp_int) * (2 + CT_INV_MOD_PRE_CNT), NULL,
|
||||
DYNAMIC_TYPE_BIGINT);
|
||||
if (t == NULL)
|
||||
return FP_MEM;
|
||||
e = t + 1;
|
||||
pre = t + 2;
|
||||
#endif
|
||||
|
||||
fp_init(t);
|
||||
fp_init(e);
|
||||
|
||||
fp_init(&pre[0]);
|
||||
fp_copy(a, &pre[0]);
|
||||
for (i = 1; i < CT_INV_MOD_PRE_CNT; i++) {
|
||||
fp_init(&pre[i]);
|
||||
fp_sqr(&pre[i-1], &pre[i]);
|
||||
fp_montgomery_reduce(&pre[i], b, mp);
|
||||
fp_mul(&pre[i], a, &pre[i]);
|
||||
fp_montgomery_reduce(&pre[i], b, mp);
|
||||
}
|
||||
|
||||
fp_sub_d(b, 2, e);
|
||||
/* Highest bit is always set. */
|
||||
for (i = fp_count_bits(e)-2, j = 1; i >= 0; i--, j++) {
|
||||
if (!fp_is_bit_set(e, i) || j == CT_INV_MOD_PRE_CNT)
|
||||
break;
|
||||
}
|
||||
fp_copy(&pre[j-1], t);
|
||||
for (j = 0; i >= 0; i--) {
|
||||
int set = fp_is_bit_set(e, i);
|
||||
|
||||
if ((j == CT_INV_MOD_PRE_CNT) || (!set && j > 0)) {
|
||||
fp_mul(t, &pre[j-1], t);
|
||||
fp_montgomery_reduce(t, b, mp);
|
||||
j = 0;
|
||||
}
|
||||
fp_sqr(t, t);
|
||||
fp_montgomery_reduce(t, b, mp);
|
||||
j += set;
|
||||
}
|
||||
if (j > 0) {
|
||||
fp_mul(t, &pre[j-1], c);
|
||||
fp_montgomery_reduce(c, b, mp);
|
||||
}
|
||||
else
|
||||
fp_copy(t, c);
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
|
||||
#endif
|
||||
return FP_OKAY;
|
||||
}
|
||||
|
||||
/* d = a * b (mod c) */
|
||||
int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
|
||||
{
|
||||
@ -3545,6 +3614,12 @@ int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
|
||||
return fp_invmod(a, b, c);
|
||||
}
|
||||
|
||||
/* hac 14.61, pp608 */
|
||||
int mp_invmod_mont_ct (mp_int * a, mp_int * b, mp_int * c, mp_digit mp)
|
||||
{
|
||||
return fp_invmod_mont_ct(a, b, c, mp);
|
||||
}
|
||||
|
||||
/* this is a shell function that calls either the normal or Montgomery
|
||||
* exptmod functions. Originally the call to the montgomery code was
|
||||
* embedded in the normal function but that wasted a lot of stack space
|
||||
|
@ -439,6 +439,7 @@ ECC_API int ecc_mul2add(ecc_point* A, mp_int* kA,
|
||||
ecc_point* C, mp_int* a, mp_int* modulus, void* heap);
|
||||
|
||||
ECC_API int ecc_map(ecc_point*, mp_int*, mp_digit);
|
||||
ECC_API int ecc_map_ex(ecc_point*, mp_int*, mp_digit, int ct);
|
||||
ECC_API int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
|
||||
mp_int* a, mp_int* modulus, mp_digit mp);
|
||||
ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a,
|
||||
|
@ -535,6 +535,7 @@ int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c);
|
||||
|
||||
/* c = 1/a (mod b) */
|
||||
int fp_invmod(fp_int *a, fp_int *b, fp_int *c);
|
||||
int fp_invmod_mont_ct(fp_int *a, fp_int *b, fp_int *c, fp_digit mp);
|
||||
|
||||
/* c = (a, b) */
|
||||
/*int fp_gcd(fp_int *a, fp_int *b, fp_int *c);*/
|
||||
@ -743,6 +744,7 @@ MP_API int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d);
|
||||
MP_API int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d);
|
||||
MP_API int mp_mod(mp_int *a, mp_int *b, mp_int *c);
|
||||
MP_API int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
|
||||
MP_API int mp_invmod_mont_ct(mp_int *a, mp_int *b, mp_int *c, fp_digit mp);
|
||||
MP_API int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y);
|
||||
MP_API int mp_exptmod_ex (mp_int * g, mp_int * x, int minDigits, mp_int * p,
|
||||
mp_int * y);
|
||||
|
Reference in New Issue
Block a user