Merge pull request #24
9037707
Rewrite 5x52 normalize method to be faster (Peter Dettman)
This commit is contained in:
commit
b110f84bbb
|
@ -34,41 +34,39 @@ void static secp256k1_fe_inner_start(void) {}
|
||||||
void static secp256k1_fe_inner_stop(void) {}
|
void static secp256k1_fe_inner_stop(void) {}
|
||||||
|
|
||||||
void static secp256k1_fe_normalize(secp256k1_fe_t *r) {
|
void static secp256k1_fe_normalize(secp256k1_fe_t *r) {
|
||||||
uint64_t c;
|
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||||
c = r->n[0];
|
|
||||||
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL;
|
|
||||||
c = (c >> 52) + r->n[1];
|
|
||||||
uint64_t t1 = c & 0xFFFFFFFFFFFFFULL;
|
|
||||||
c = (c >> 52) + r->n[2];
|
|
||||||
uint64_t t2 = c & 0xFFFFFFFFFFFFFULL;
|
|
||||||
c = (c >> 52) + r->n[3];
|
|
||||||
uint64_t t3 = c & 0xFFFFFFFFFFFFFULL;
|
|
||||||
c = (c >> 52) + r->n[4];
|
|
||||||
uint64_t t4 = c & 0x0FFFFFFFFFFFFULL;
|
|
||||||
c >>= 48;
|
|
||||||
|
|
||||||
// The following code will not modify the t's if c is initially 0.
|
// Reduce t4 at the start so there will be at most a single carry from the first pass
|
||||||
c = c * 0x1000003D1ULL + t0;
|
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
|
||||||
t0 = c & 0xFFFFFFFFFFFFFULL;
|
|
||||||
c = (c >> 52) + t1;
|
|
||||||
t1 = c & 0xFFFFFFFFFFFFFULL;
|
|
||||||
c = (c >> 52) + t2;
|
|
||||||
t2 = c & 0xFFFFFFFFFFFFFULL;
|
|
||||||
c = (c >> 52) + t3;
|
|
||||||
t3 = c & 0xFFFFFFFFFFFFFULL;
|
|
||||||
c = (c >> 52) + t4;
|
|
||||||
t4 = c & 0x0FFFFFFFFFFFFULL;
|
|
||||||
assert((c >> 48) == 0);
|
|
||||||
|
|
||||||
// Subtract p if result >= p
|
// The first pass ensures the magnitude is 1, ...
|
||||||
uint64_t mask = -(int64_t)((t4 < 0xFFFFFFFFFFFFULL) | (t3 < 0xFFFFFFFFFFFFFULL) | (t2 < 0xFFFFFFFFFFFFFULL) | (t1 < 0xFFFFFFFFFFFFFULL) | (t0 < 0xFFFFEFFFFFC2FULL));
|
t0 += x * 0x1000003D1ULL;
|
||||||
t4 &= mask;
|
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||||
t3 &= mask;
|
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL;
|
||||||
t2 &= mask;
|
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL;
|
||||||
t1 &= mask;
|
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL;
|
||||||
t0 -= (~mask & 0xFFFFEFFFFFC2FULL);
|
|
||||||
|
// ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element)
|
||||||
|
assert(t4 >> 49 == 0);
|
||||||
|
|
||||||
|
// At most a single final reduction is needed; check if the value is >= the field characteristic
|
||||||
|
x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL)
|
||||||
|
& ((t3 & t2 & t1) == 0xFFFFFFFFFFFFFULL)
|
||||||
|
& (t0 >= 0xFFFFEFFFFFC2FULL));
|
||||||
|
|
||||||
|
// Apply the final reduction (for constant-time behaviour, we do it always)
|
||||||
|
t0 += x * 0x1000003D1ULL;
|
||||||
|
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||||
|
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL;
|
||||||
|
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL;
|
||||||
|
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL;
|
||||||
|
|
||||||
|
// If t4 didn't carry to bit 48 already, then it should have after any final reduction
|
||||||
|
assert(t4 >> 48 == x);
|
||||||
|
|
||||||
|
// Mask off the possible multiple of 2^256 from the final reduction
|
||||||
|
t4 &= 0x0FFFFFFFFFFFFULL;
|
||||||
|
|
||||||
// push internal variables back
|
|
||||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||||
|
|
||||||
#ifdef VERIFY
|
#ifdef VERIFY
|
||||||
|
|
Loading…
Reference in New Issue