forked from wolfSSL/wolfssl
ECC: better protection when using encrypted memory
Added new ECC scalar multiplication implementation.
This commit is contained in:
@ -87,6 +87,11 @@ Possible ECC enable options:
|
||||
* the variant macro is used the bits2octets operation on
|
||||
* the hash is removed.
|
||||
* default: off
|
||||
*
|
||||
* WC_PROTECT_ENCRYPTED_MEM:
|
||||
* Enables implementations that protect data that is in
|
||||
* encrypted memory.
|
||||
* default: off
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -2762,6 +2767,7 @@ static int wc_ecc_gen_z(WC_RNG* rng, int size, ecc_point* p,
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifndef WC_PROTECT_ENCRYPTED_MEM
|
||||
#define M_POINTS 3
|
||||
|
||||
/* Joye double-add ladder.
|
||||
@ -2925,6 +2931,183 @@ static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q,
|
||||
return err;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Number of points to allocate for use during scalar multiplication. */
|
||||
#define M_POINTS 5
|
||||
/* Last of the points is used as a temporary during calculations. */
|
||||
#define TMP_IDX M_POINTS - 1
|
||||
|
||||
static void mp_cond_swap_into_ct(mp_int* ra, mp_int* rb, mp_int* a, mp_int* b,
|
||||
int digits, int m)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if !defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_SP_INT_NEGATIVE)
|
||||
/* Only using positive numbers in ECC operations. */
|
||||
ra->sign = 0;
|
||||
rb->sign = 0;
|
||||
#endif
|
||||
/* Don't store 0 when mask is 0, it will be in a register. */
|
||||
ra->used = (int)(((a->used ^ b->used) & ((mp_digit)0 - (m & 1))) ^ a->used);
|
||||
rb->used = (int)(((a->used ^ b->used) & ((mp_digit)0 - (m & 1))) ^ b->used);
|
||||
for (i = 0; i < digits; i++) {
|
||||
ra->dp[i] = ((a->dp[i] ^ b->dp[i]) & ((mp_digit)0 - (m & 1))) ^
|
||||
a->dp[i];
|
||||
rb->dp[i] = ((a->dp[i] ^ b->dp[i]) & ((mp_digit)0 - (m & 1))) ^
|
||||
b->dp[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void ecc_cond_swap_into_ct(ecc_point* ra, ecc_point* rb, ecc_point* a,
|
||||
ecc_point* b, int digits, int m)
|
||||
{
|
||||
/* Conditionally swap each ordinate. */
|
||||
mp_cond_swap_into_ct(ra->x, rb->x, a->x, b->x, digits, m);
|
||||
mp_cond_swap_into_ct(ra->y, rb->y, a->y, b->y, digits, m);
|
||||
mp_cond_swap_into_ct(ra->z, rb->z, a->z, b->z, digits, m);
|
||||
}
|
||||
|
||||
/* Joye double-add ladder.
|
||||
* "Highly Regular Right-to-Left Algorithms for Scalar Multiplication"
|
||||
* by Marc Joye (2007)
|
||||
*
|
||||
* Algorithm 1':
|
||||
* Input: P element of curve, k = (k[t-1],..., k[0]) base 2
|
||||
* Output: Q = kP
|
||||
* 1: R[0] = P; R[1] = P
|
||||
* 2: for j = 1 to t-1 do
|
||||
* 3: b = 1 - k[j]; R[b] = 2*R[b] + R[k[j]]
|
||||
* 4: end for
|
||||
* 5: b = k[0]; R[b] = R[b] - P
|
||||
* 6: return R[0]
|
||||
*
|
||||
* Assumes: k < order.
|
||||
*/
|
||||
static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q,
|
||||
ecc_point** R, mp_int* a, mp_int* modulus, mp_digit mp, WC_RNG* rng)
|
||||
{
|
||||
int err = MP_OKAY;
|
||||
int bytes = (mp_count_bits(modulus) + 7) / 8;
|
||||
int i;
|
||||
int j = 1;
|
||||
int cnt;
|
||||
int t = 0;
|
||||
mp_int* kt = R[TMP_IDX]->x;
|
||||
/* First bit always 1 (fix at end) and swap equals first bit */
|
||||
register int swap = 1;
|
||||
/* Which pair of points has current value. R[0,1] or R[2,3] */
|
||||
int set = 0;
|
||||
int infinity;
|
||||
|
||||
/* Step 1: R[0] = P; R[1] = P */
|
||||
/* R[0] = P */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(P->x, R[0]->x);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(P->y, R[0]->y);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(P->z, R[0]->z);
|
||||
|
||||
/* R[1] = P */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(P->x, R[1]->x);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(P->y, R[1]->y);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(P->z, R[1]->z);
|
||||
|
||||
/* Randomize z ordinates to obfuscate timing. */
|
||||
if ((err == MP_OKAY) && (rng != NULL))
|
||||
err = wc_ecc_gen_z(rng, bytes, R[0], modulus, mp, R[TMP_IDX]->x,
|
||||
R[TMP_IDX]->y);
|
||||
if ((err == MP_OKAY) && (rng != NULL))
|
||||
err = wc_ecc_gen_z(rng, bytes, R[1], modulus, mp, R[TMP_IDX]->x,
|
||||
R[TMP_IDX]->y);
|
||||
|
||||
if (err == MP_OKAY) {
|
||||
/* Order could be one greater than the size of the modulus. */
|
||||
t = mp_count_bits(modulus) + 1;
|
||||
err = mp_copy(k, kt);
|
||||
}
|
||||
if (err == MP_OKAY) {
|
||||
err = mp_grow(kt, modulus->used + 1);
|
||||
}
|
||||
/* Step 2: for j = 1 to t-1 do */
|
||||
for (i = 1, j = 0, cnt = 0; (err == MP_OKAY) && (i < t); i++) {
|
||||
if (++cnt == DIGIT_BIT) {
|
||||
j++;
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
/* Step 3: b = 1 - k[j]; R[b] = 2*R[b] + R[k[j]] */
|
||||
/* Swap R[0] and R[1] if other index is needed. */
|
||||
/* Ensure 'swap' changes when shifted word is 0. */
|
||||
swap += (kt->dp[j] >> cnt) + 2;
|
||||
ecc_cond_swap_into_ct(R[(2 - set) + 0], R[(2 - set) + 1],
|
||||
R[set + 0], R[set + 1], modulus->used, swap);
|
||||
/* Change to operate on set copied into. */
|
||||
set = 2 - set;
|
||||
/* Ensure 'swap' changes to a previously unseen value. */
|
||||
swap += (kt->dp[j] >> cnt) + swap;
|
||||
|
||||
err = ecc_projective_dbl_point_safe(R[set + 0], R[set + 0], a, modulus,
|
||||
mp);
|
||||
if (err == MP_OKAY) {
|
||||
err = ecc_projective_add_point_safe(R[set + 0], R[set + 1],
|
||||
R[set + 0], a, modulus, mp, &infinity);
|
||||
}
|
||||
}
|
||||
/* Step 4: end for */
|
||||
/* Swap back if last bit is 0. */
|
||||
/* Ensure 'swap' changes. */
|
||||
swap += 1;
|
||||
if (err == MP_OKAY) {
|
||||
ecc_cond_swap_into_ct(R[(2 - set) + 0], R[(2 - set) + 1],
|
||||
R[set + 0], R[set + 1], modulus->used, swap);
|
||||
set = 2 - set;
|
||||
}
|
||||
|
||||
/* Step 5: b = k[0]; R[b] = R[b] - P */
|
||||
/* R[TMP_IDX] = -P */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(P->x, R[TMP_IDX]->x);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_sub(modulus, P->y, R[TMP_IDX]->y);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(P->z, R[TMP_IDX]->z);
|
||||
/* Subtract point by adding negative. */
|
||||
if (err == MP_OKAY) {
|
||||
/* Swap R[0] and R[1], if necessary, to operate on the one we want.
|
||||
* Last bit of k->dp[0] is being used to make decision to swap.
|
||||
*/
|
||||
ecc_cond_swap_into_ct(R[(2 - set) + 0], R[(2 - set) + 1],
|
||||
R[set + 0], R[set + 1], modulus->used,
|
||||
(int)k->dp[0]);
|
||||
set = 2 - set;
|
||||
err = ecc_projective_add_point_safe(R[set + 0], R[TMP_IDX], R[set + 0],
|
||||
a, modulus, mp, &infinity);
|
||||
/* Swap back if necessary. */
|
||||
if (err == MP_OKAY) {
|
||||
ecc_cond_swap_into_ct(R[(2 - set) + 0], R[(2 - set) + 1],
|
||||
R[set + 0], R[set + 1], modulus->used,
|
||||
(int)k->dp[0]);
|
||||
set = 2 - set;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 6: return R[0] */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(R[set + 0]->x, Q->x);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(R[set + 0]->y, Q->y);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_copy(R[set + 0]->z, Q->z);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Convert the point to montgomery form.
|
||||
|
Reference in New Issue
Block a user