Avoid direct indexed access in precomputed table
This commit is contained in:
parent
123e22ec08
commit
d497040ddd
@ -139,9 +139,53 @@ ED25519_FN(ed25519_point_scalarmul) (ge25519 *r, const ge25519 *p, const bignum2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(ED25519_64BIT)
|
||||||
|
typedef uint64_t ed25519_move_cond_word;
|
||||||
|
#else
|
||||||
|
typedef uint32_t ed25519_move_cond_word;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* out = (flag) ? in : out */
|
||||||
|
DONNA_INLINE static void
|
||||||
|
ed25519_move_cond_pniels(ge25519_pniels *out, const ge25519_pniels *in, uint32_t flag) {
|
||||||
|
const int word_count = sizeof(ge25519_pniels) / sizeof(ed25519_move_cond_word);
|
||||||
|
const ed25519_move_cond_word nb = (ed25519_move_cond_word) flag - 1, b = ~nb;
|
||||||
|
|
||||||
|
ed25519_move_cond_word *outw = (ed25519_move_cond_word *) out;
|
||||||
|
const ed25519_move_cond_word *inw = (const ed25519_move_cond_word *) in;
|
||||||
|
|
||||||
|
// ge25519_pniels has 4 coordinates, so word_count is divisible by 4
|
||||||
|
for (int i = 0; i < word_count; i += 4) {
|
||||||
|
outw[i + 0] = (outw[i + 0] & nb) | (inw[i + 0] & b);
|
||||||
|
outw[i + 1] = (outw[i + 1] & nb) | (inw[i + 1] & b);
|
||||||
|
outw[i + 2] = (outw[i + 2] & nb) | (inw[i + 2] & b);
|
||||||
|
outw[i + 3] = (outw[i + 3] & nb) | (inw[i + 3] & b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ed25519_point_scalarmul_w_choose_pniels(ge25519_pniels *t, const ge25519_pniels table[15], uint32_t pos) {
|
||||||
|
// initialize t to identity, i.e. (1, 1, 1, 0)
|
||||||
|
memset(t, 0, sizeof(ge25519_pniels));
|
||||||
|
t->ysubx[0] = 1;
|
||||||
|
t->xaddy[0] = 1;
|
||||||
|
t->z[0] = 1;
|
||||||
|
|
||||||
|
// move one entry from table matching requested position,
|
||||||
|
// scanning all table to avoid cache-timing attack
|
||||||
|
//
|
||||||
|
// when pos == 0, no entry matches and this returns
|
||||||
|
// identity as expected
|
||||||
|
for (uint32_t i = 1; i < 16; i++) {
|
||||||
|
uint32_t flag = ((i ^ pos) - 1) >> 31;
|
||||||
|
ed25519_move_cond_pniels(t, table + i - 1, flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ED25519_FN(ed25519_point_scalarmul_w) (ge25519 *r, const ge25519 *p, const bignum256modm s) {
|
ED25519_FN(ed25519_point_scalarmul_w) (ge25519 *r, const ge25519 *p, const bignum256modm s) {
|
||||||
ge25519_pniels mult[16];
|
ge25519_pniels mult[15];
|
||||||
|
ge25519_pniels pn;
|
||||||
ge25519_p1p1 t;
|
ge25519_p1p1 t;
|
||||||
unsigned char ss[32];
|
unsigned char ss[32];
|
||||||
|
|
||||||
@ -153,26 +197,17 @@ ED25519_FN(ed25519_point_scalarmul_w) (ge25519 *r, const ge25519 *p, const bignu
|
|||||||
r->y[0] = 1;
|
r->y[0] = 1;
|
||||||
r->z[0] = 1;
|
r->z[0] = 1;
|
||||||
|
|
||||||
// initialize mult[0] to identity, i.e. ge25519_pniels (1, 1, 1, 0)
|
// precompute multiples of P: 1.P, 2.P, ..., 15.P
|
||||||
memset(&mult[0], 0, sizeof(ge25519_pniels));
|
ge25519_full_to_pniels(&mult[0], p);
|
||||||
mult->ysubx[0] = 1;
|
for (int i = 1; i < 15; i++) {
|
||||||
mult->xaddy[0] = 1;
|
|
||||||
mult->z[0] = 1;
|
|
||||||
|
|
||||||
// precompute other multiples of P: 1.P, 2.P, ..., 15.P
|
|
||||||
ge25519_full_to_pniels(&mult[1], p);
|
|
||||||
for (int i = 2; i < 16; i++) {
|
|
||||||
ge25519_pnielsadd(&mult[i], p, &mult[i-1]);
|
ge25519_pnielsadd(&mult[i], p, &mult[i-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4-bit fixed window, still 256 doublings but 64 additions
|
// 4-bit fixed window, still 256 doublings but 64 additions
|
||||||
//
|
|
||||||
// NOTE: direct indexed access to 'mult' table leaks data through
|
|
||||||
// CPU cache but provides 33% speedup compared to naive unvectored
|
|
||||||
// table lookup with unint32 constant-time conditional selection
|
|
||||||
for (int i = 31; i >= 0; i--) {
|
for (int i = 31; i >= 0; i--) {
|
||||||
// higher bits in ss[i]
|
// higher bits in ss[i]
|
||||||
ge25519_pnielsadd_p1p1(&t, r, &mult[ss[i] >> 4], 0);
|
ed25519_point_scalarmul_w_choose_pniels(&pn, mult, ss[i] >> 4);
|
||||||
|
ge25519_pnielsadd_p1p1(&t, r, &pn, 0);
|
||||||
ge25519_p1p1_to_partial(r, &t);
|
ge25519_p1p1_to_partial(r, &t);
|
||||||
|
|
||||||
ge25519_double_partial(r, r);
|
ge25519_double_partial(r, r);
|
||||||
@ -181,7 +216,8 @@ ED25519_FN(ed25519_point_scalarmul_w) (ge25519 *r, const ge25519 *p, const bignu
|
|||||||
ge25519_double(r, r);
|
ge25519_double(r, r);
|
||||||
|
|
||||||
// lower bits in ss[i]
|
// lower bits in ss[i]
|
||||||
ge25519_pnielsadd_p1p1(&t, r, &mult[ss[i] & 0x0F], 0);
|
ed25519_point_scalarmul_w_choose_pniels(&pn, mult, ss[i] & 0x0F);
|
||||||
|
ge25519_pnielsadd_p1p1(&t, r, &pn, 0);
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
ge25519_p1p1_to_partial(r, &t);
|
ge25519_p1p1_to_partial(r, &t);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user