Browse Source

sliding window

master
Michael Hamburg 9 years ago
parent
commit
820c83a80c
1 changed files with 47 additions and 68 deletions
  1. +47
    -68
      src/decaf_fast.c

+ 47
- 68
src/decaf_fast.c View File

@@ -257,11 +257,7 @@ void API_NS(scalar_mul) (
}

/* PERF: could implement this */
static INLINE void
sc_montsqr (
scalar_t out,
const scalar_t a
) {
static INLINE void sc_montsqr (scalar_t out, const scalar_t a) {
sc_montmul(out,a,a);
}

@@ -269,77 +265,60 @@ decaf_bool_t API_NS(scalar_invert) (
scalar_t out,
const scalar_t a
) {
#if 0
/* FIELD MAGIC. TODO PERF: not updated for 25519 */
scalar_t chain[7], tmp;
sc_montmul(chain[0],a,API_NS(sc_r2));
unsigned int i,j;
/* Addition chain generated by a not-too-clever SAGE script. First part: compute a^(2^222-1) */
const struct { uint8_t widx, sidx, sct, midx; } muls [] = {
{2,0,1,0}, {3,2,1,0}, {4,3,1,0}, {5,4,1,0}, /* 0x3,7,f,1f */
{1,5,1,0}, {1,1,3,3}, {6,1,9,1}, {1,6,1,0}, {6,1,18,6}, /* a^(2^37-1) */
{1,6,37,6}, {1,1,37,6}, {1,1,111,1} /* a^(2^222-1) */
};
/* Second part: sliding window */
const struct { uint8_t sct, midx; } muls1 [] = {
{6, 5}, {4, 2}, {3, 0}, {2, 0}, {4, 0}, {8, 5},
{2, 0}, {5, 3}, {4, 0}, {4, 0}, {5, 3}, {3, 2},
{3, 2}, {3, 2}, {2, 0}, {3, 0}, {4, 2}, {2, 0},
{4, 3}, {3, 2}, {2, 0}, {3, 2}, {5, 2}, {3, 2},
{2, 0}, {3, 0}, {7, 0}, {5, 0}, {3, 2}, {3, 2},
{4, 2}, {5, 0}, {5, 3}, {3, 0}, {2, 0}, {5, 2},
{4, 3}, {4, 0}, {3, 2}, {7, 4}, {2, 0}, {2, 0},
{2, 0}, {2, 0}, {3, 0}, {5, 2}, {5, 4}, {5, 2},
{5, 0}, {2, 0}, {3, 0}, {3, 0}, {2, 0}, {2, 0},
{2, 0}, {3, 2}, {2, 0}, {3, 2}, {5, 0}, {4, 0},
{6, 4}, {4, 0}
};
for (i=0; i<sizeof(muls)/sizeof(muls[0]); i++) {
sc_montsqr(tmp, chain[muls[i].sidx]);
for (j=1; j<muls[i].sct; j++) {
sc_montsqr(tmp, tmp);
}
sc_montmul(chain[muls[i].widx], tmp, chain[muls[i].midx]);
}
for (i=0; i<sizeof(muls1)/sizeof(muls1[0]); i++) {
sc_montsqr(tmp, chain[1]);
for (j=1; j<muls1[i].sct; j++) {
sc_montsqr(tmp, tmp);
}
sc_montmul(chain[1], tmp, chain[muls1[i].midx]);
/* Fermat's little theorem, sliding window.
* Sliding window is fine here because the modulus isn't secret.
*/
const int SCALAR_WINDOW_BITS = 3;
scalar_t precmp[1<<SCALAR_WINDOW_BITS];
const int LAST = (1<<SCALAR_WINDOW_BITS)-1;

/* Precompute precmp = [a^1,a^3,...] */
sc_montmul(precmp[0],a,API_NS(sc_r2));
if (LAST > 0) sc_montmul(precmp[LAST],precmp[0],precmp[0]);

int i;
for (i=1; i<=LAST; i++) {
sc_montmul(precmp[i],precmp[i-1],precmp[LAST]);
}
sc_montmul(out,chain[1],API_NS(scalar_one));
for (i=0; i<sizeof(chain)/sizeof(chain[0]); i++) {
API_NS(scalar_destroy)(chain[i]);
}
return ~API_NS(scalar_eq)(out,API_NS(scalar_zero));
#else
scalar_t b, ma;
int i;
sc_montmul(b,API_NS(scalar_one),API_NS(sc_r2));
sc_montmul(ma,a,API_NS(sc_r2));
for (i=SCALAR_BITS-1; i>=0; i--) {
sc_montsqr(b,b);
decaf_word_t w = sc_p->limb[i/WBITS];
if (i<WBITS) {
/* Sliding window */
unsigned residue = 0, trailing = 0, started = 0;
for (i=SCALAR_BITS-1; i>=-SCALAR_WINDOW_BITS; i--) {
if (started) sc_montsqr(out,out);
decaf_word_t w = (i>=0) ? sc_p->limb[i/WBITS] : 0;
if (i >= 0 && i<WBITS) {
assert(w >= 2);
w-=2;
}
if (1 & w>>(i%WBITS)) {
sc_montmul(b,b,ma);
residue = (residue<<1) | ((w>>(i%WBITS))&1);
if (residue>>SCALAR_WINDOW_BITS != 0) {
assert(trailing == 0);
trailing = residue;
residue = 0;
}
if (trailing > 0 && (trailing & (1<<SCALAR_WINDOW_BITS)-1) == 0) {
if (started) {
sc_montmul(out,out,precmp[trailing>>(SCALAR_WINDOW_BITS+1)]);
} else {
API_NS(scalar_copy)(out,precmp[trailing>>(SCALAR_WINDOW_BITS+1)]);
started = 1;
}
trailing = 0;
}
trailing <<= 1;
}

sc_montmul(out,b,API_NS(scalar_one));
API_NS(scalar_destroy)(b);
API_NS(scalar_destroy)(ma);
assert(residue==0);
assert(trailing==0);
/* Demontgomerize */
sc_montmul(out,out,API_NS(scalar_one));
decaf_bzero(precmp, sizeof(precmp));
return ~API_NS(scalar_eq)(out,API_NS(scalar_zero));
#endif
}

void API_NS(scalar_sub) (


Loading…
Cancel
Save