|
|
@@ -61,35 +61,34 @@ siv gf_sqrn ( gf x, const gf y, int n ) { |
|
|
|
for (i=0; i<n; i++) gf_sqr(x,x); |
|
|
|
} |
|
|
|
|
|
|
|
static void ISR(gf a, const gf x) { |
|
|
|
gf L0, L1, L2; |
|
|
|
gf_sqr (L1, x ); |
|
|
|
gf_mul (L2, x, L1 ); |
|
|
|
gf_sqr (L1, L2 ); |
|
|
|
gf_mul (L2, x, L1 ); |
|
|
|
gf_sqrn(L1, L2, 3 ); |
|
|
|
gf_mul (L0, L2, L1 ); |
|
|
|
gf_sqrn(L1, L0, 3 ); |
|
|
|
gf_mul (L0, L2, L1 ); |
|
|
|
gf_sqrn(L2, L0, 9 ); |
|
|
|
gf_mul (L1, L0, L2 ); |
|
|
|
gf_sqr (L0, L1 ); |
|
|
|
gf_mul (L2, x, L0 ); |
|
|
|
gf_sqrn(L0, L2, 18 ); |
|
|
|
gf_mul (L2, L1, L0 ); |
|
|
|
gf_sqrn(L0, L2, 37 ); |
|
|
|
gf_mul (L1, L2, L0 ); |
|
|
|
gf_sqrn(L0, L1, 37 ); |
|
|
|
gf_mul (L1, L2, L0 ); |
|
|
|
gf_sqrn(L0, L1, 111 ); |
|
|
|
gf_mul (L2, L1, L0 ); |
|
|
|
gf_sqr (L0, L2 ); |
|
|
|
gf_mul (L1, x, L0 ); |
|
|
|
gf_sqrn(L0, L1, 223 ); |
|
|
|
gf_mul ( a, L2, L0 ); |
|
|
|
static void gf_isqrt(gf y, const gf x) { |
|
|
|
gf a, b, c; |
|
|
|
gf_sqrn( b, x, 1 ); |
|
|
|
gf_mul ( c, x, b ); |
|
|
|
gf_sqrn( b, c, 1 ); |
|
|
|
gf_mul ( c, x, b ); |
|
|
|
gf_sqrn( b, c, 3 ); |
|
|
|
gf_mul ( a, c, b ); |
|
|
|
gf_sqrn( b, a, 3 ); |
|
|
|
gf_mul ( a, c, b ); |
|
|
|
gf_sqrn( c, a, 9 ); |
|
|
|
gf_mul ( b, a, c ); |
|
|
|
gf_sqrn( a, b, 1 ); |
|
|
|
gf_mul ( c, x, a ); |
|
|
|
gf_sqrn( a, c, 18 ); |
|
|
|
gf_mul ( c, b, a ); |
|
|
|
gf_sqrn( a, c, 37 ); |
|
|
|
gf_mul ( b, c, a ); |
|
|
|
gf_sqrn( a, b, 37 ); |
|
|
|
gf_mul ( b, c, a ); |
|
|
|
gf_sqrn( a, b, 111 ); |
|
|
|
gf_mul ( c, b, a ); |
|
|
|
gf_sqrn( a, c, 1 ); |
|
|
|
gf_mul ( b, x, a ); |
|
|
|
gf_sqrn( a, b, 223 ); |
|
|
|
gf_mul ( y, c, a ); |
|
|
|
} |
|
|
|
|
|
|
|
const decaf_point_t decaf_identity_point = {{{0},{1},{1},{0}}}; |
|
|
|
|
|
|
|
siv gf_reduce(gf x) { |
|
|
|
x[NLIMBS/2] += x[NLIMBS-1] >> LBITS; |
|
|
@@ -172,118 +171,119 @@ static inline word_t hibit(const gf x) { |
|
|
|
} |
|
|
|
|
|
|
|
// FIXME: 32-bit cleanliness |
|
|
|
siv gf_ser ( uint8_t serial[56], const gf x ) { |
|
|
|
int i,j; |
|
|
|
siv gf_ser ( uint8_t serial[DECAF_SER_BYTES], const gf x ) { |
|
|
|
int j; |
|
|
|
gf red; |
|
|
|
gf_cpy(red,x); |
|
|
|
gf_canon(red); |
|
|
|
for (i=0; i<8; i++) { |
|
|
|
FOR_LIMB(i,{ |
|
|
|
for (j=0; j<7; j++) { |
|
|
|
serial[7*i+j] = red[i]; |
|
|
|
red[i] >>= 8; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// FIXME: 32-bit cleanliness |
|
|
|
static mask_t gf_deser ( gf x, const uint8_t serial[56] ) { |
|
|
|
int i,j; |
|
|
|
for (i=0; i<8; i++) { |
|
|
|
static mask_t gf_deser ( gf x, const uint8_t serial[DECAF_SER_BYTES] ) { |
|
|
|
int j; |
|
|
|
FOR_LIMB(i, { |
|
|
|
uint64_t out = 0; |
|
|
|
for (j=0; j<7; j++) { |
|
|
|
out |= ((uint64_t)serial[7*i+j])<<(8*j); |
|
|
|
} |
|
|
|
x[i] = out; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
sdword_t accum = 0; |
|
|
|
FOR_LIMB(i, accum = (accum + P[i] - x[i]) >> WBITS ); |
|
|
|
return ~accum; |
|
|
|
} |
|
|
|
|
|
|
|
siv |
|
|
|
add_sub_point ( |
|
|
|
decaf_point_t c, |
|
|
|
const decaf_point_t d, |
|
|
|
const decaf_point_t e, |
|
|
|
const decaf_point_t decaf_identity_point = {{{0},{1},{1},{0}}}; |
|
|
|
|
|
|
|
siv add_sub_point ( |
|
|
|
decaf_point_t p, |
|
|
|
const decaf_point_t q, |
|
|
|
const decaf_point_t r, |
|
|
|
mask_t sub |
|
|
|
) { |
|
|
|
gf L0, L1, L2, L3; |
|
|
|
gf_sub ( L1, d->y, d->x ); |
|
|
|
gf_sub ( L2, e->y, e->x ); |
|
|
|
gf_add ( L3, e->y, e->x ); |
|
|
|
cond_swap(L2,L3,sub); |
|
|
|
gf_mul ( L0, L2, L1 ); |
|
|
|
gf_add ( L1, d->y, d->x ); |
|
|
|
gf_mul ( c->y, L3, L1 ); |
|
|
|
gf_mul ( L1, e->t, d->t ); |
|
|
|
gf_mlw ( c->x, L1, 2-2*EDWARDS_D ); |
|
|
|
gf_add ( L1, L0, c->y ); |
|
|
|
gf_sub ( L2, c->y, L0 ); |
|
|
|
gf_mul ( L0, d->z, e->z ); |
|
|
|
gf_add ( L0, L0, L0 ); |
|
|
|
gf_add ( c->y, L0, c->x ); |
|
|
|
gf_sub ( L0, L0, c->x ); |
|
|
|
cond_swap(L0,c->y,sub); |
|
|
|
gf_mul ( c->z, L0, c->y ); |
|
|
|
gf_mul ( c->x, c->y, L2 ); |
|
|
|
gf_mul ( c->y, L0, L1 ); |
|
|
|
gf_mul ( c->t, L1, L2 ); |
|
|
|
gf a, b, c, d; |
|
|
|
gf_sub ( b, q->y, q->x ); |
|
|
|
gf_sub ( c, r->y, r->x ); |
|
|
|
gf_add ( d, r->y, r->x ); |
|
|
|
cond_swap(c,d,sub); |
|
|
|
gf_mul ( a, c, b ); |
|
|
|
gf_add ( b, q->y, q->x ); |
|
|
|
gf_mul ( p->y, d, b ); |
|
|
|
gf_mul ( b, r->t, q->t ); |
|
|
|
gf_mlw ( p->x, b, 2-2*EDWARDS_D ); |
|
|
|
gf_add ( b, a, p->y ); |
|
|
|
gf_sub ( c, p->y, a ); |
|
|
|
gf_mul ( a, q->z, r->z ); |
|
|
|
gf_add ( a, a, a ); |
|
|
|
gf_add ( p->y, a, p->x ); |
|
|
|
gf_sub ( a, a, p->x ); |
|
|
|
cond_swap(a,p->y,sub); |
|
|
|
gf_mul ( p->z, a, p->y ); |
|
|
|
gf_mul ( p->x, p->y, c ); |
|
|
|
gf_mul ( p->y, a, b ); |
|
|
|
gf_mul ( p->t, b, c ); |
|
|
|
} |
|
|
|
|
|
|
|
void decaf_encode( uint8_t ser[DECAF_SER_BYTES], const decaf_point_t a ) { |
|
|
|
gf L0, L1, L2, L3; |
|
|
|
gf_mlw ( L0, a->y, 1-EDWARDS_D ); |
|
|
|
gf_mul ( L2, L0, a->t ); |
|
|
|
gf_mul ( L0, a->x, a->z ); |
|
|
|
gf_sub ( L3, L2, L0 ); |
|
|
|
gf_add ( L0, a->z, a->y ); |
|
|
|
gf_sub ( L1, a->z, a->y ); |
|
|
|
gf_mul ( L2, L1, L0 ); |
|
|
|
gf_mlw ( L1, L2, -EDWARDS_D ); |
|
|
|
ISR ( L0, L1 ); |
|
|
|
gf_mlw ( L1, L0, -EDWARDS_D ); |
|
|
|
gf_mul ( L2, L1, L0 ); |
|
|
|
gf_mul ( L0, L2, L3 ); |
|
|
|
gf_add ( L3, L1, L1 ); |
|
|
|
gf_mul ( L2, L3, a->z ); |
|
|
|
cond_neg ( L1, ~hibit(L2) ); |
|
|
|
gf_mul ( L2, L1, a->y ); |
|
|
|
gf_add ( L0, L0, L2 ); |
|
|
|
cond_neg ( L0, hibit(L0) ); |
|
|
|
gf_ser(ser,L0); |
|
|
|
void decaf_encode( uint8_t ser[DECAF_SER_BYTES], const decaf_point_t p ) { |
|
|
|
gf a, b, c, d; |
|
|
|
gf_mlw ( a, p->y, 1-EDWARDS_D ); |
|
|
|
gf_mul ( c, a, p->t ); |
|
|
|
gf_mul ( a, p->x, p->z ); |
|
|
|
gf_sub ( d, c, a ); |
|
|
|
gf_add ( a, p->z, p->y ); |
|
|
|
gf_sub ( b, p->z, p->y ); |
|
|
|
gf_mul ( c, b, a ); |
|
|
|
gf_mlw ( b, c, -EDWARDS_D ); |
|
|
|
gf_isqrt ( a, b ); |
|
|
|
gf_mlw ( b, a, -EDWARDS_D ); |
|
|
|
gf_mul ( c, b, a ); |
|
|
|
gf_mul ( a, c, d ); |
|
|
|
gf_add ( d, b, b ); |
|
|
|
gf_mul ( c, d, p->z ); |
|
|
|
cond_neg ( b, ~hibit(c) ); |
|
|
|
gf_mul ( c, b, p->y ); |
|
|
|
gf_add ( a, a, c ); |
|
|
|
cond_neg ( a, hibit(a) ); |
|
|
|
gf_ser(ser,a); |
|
|
|
} |
|
|
|
|
|
|
|
decaf_bool_t decaf_decode ( |
|
|
|
decaf_point_t a, |
|
|
|
decaf_point_t p, |
|
|
|
const uint8_t ser[DECAF_SER_BYTES], |
|
|
|
decaf_bool_t allow_identity |
|
|
|
) { |
|
|
|
gf s, L0, L1, L2, L3, L4; |
|
|
|
mask_t zero = gf_eq(s, ZERO); |
|
|
|
gf s, a, b, c, d, e; |
|
|
|
mask_t succ = gf_deser( s, ser ); |
|
|
|
mask_t zero = gf_eq(s, ZERO); |
|
|
|
succ &= allow_identity | ~zero; |
|
|
|
succ &= ~hibit(s); |
|
|
|
gf_sqr ( L0, s ); |
|
|
|
gf_sub ( a->z, ONE, L0 ); |
|
|
|
gf_sqr ( L1, a->z ); |
|
|
|
gf_mlw ( L2, L0, 4-4*EDWARDS_D ); |
|
|
|
gf_add ( L2, L2, L1 ); |
|
|
|
gf_mul ( L1, L2, L0 ); |
|
|
|
ISR ( L3, L1 ); |
|
|
|
gf_sqr ( L4, L3 ); |
|
|
|
gf_mul ( L0, L4, L1 ); |
|
|
|
gf_add ( L0, L0, ONE ); |
|
|
|
succ &= ~gf_eq ( L0, ZERO ); |
|
|
|
gf_mul ( L1, L2, L3 ); |
|
|
|
cond_neg ( L3, hibit(L1) ); |
|
|
|
gf_add ( a->x, s, s ); |
|
|
|
gf_mul ( L2, L3, s ); |
|
|
|
gf_sub ( L1, TWO, a->z ); |
|
|
|
gf_mul ( L0, L1, L2 ); |
|
|
|
gf_mul ( a->y,L0,a->z ); |
|
|
|
gf_mul ( a->t,a->x,L0 ); |
|
|
|
a->y[0] -= zero; |
|
|
|
gf_sqr ( a, s ); |
|
|
|
gf_sub ( p->z, ONE, a ); |
|
|
|
gf_sqr ( b, p->z ); |
|
|
|
gf_mlw ( c, a, 4-4*EDWARDS_D ); |
|
|
|
gf_add ( c, c, b ); |
|
|
|
gf_mul ( b, c, a ); |
|
|
|
gf_isqrt ( d, b ); |
|
|
|
gf_sqr ( e, d ); |
|
|
|
gf_mul ( a, e, b ); |
|
|
|
gf_add ( a, a, ONE ); |
|
|
|
succ &= ~gf_eq ( a, ZERO ); |
|
|
|
gf_mul ( b, c, d ); |
|
|
|
cond_neg ( d, hibit(b) ); |
|
|
|
gf_add ( p->x, s, s ); |
|
|
|
gf_mul ( c, d, s ); |
|
|
|
gf_sub ( b, TWO, p->z ); |
|
|
|
gf_mul ( a, b, c ); |
|
|
|
gf_mul ( p->y,a,p->z ); |
|
|
|
gf_mul ( p->t,p->x,a ); |
|
|
|
p->y[0] -= zero; |
|
|
|
return succ; |
|
|
|
} |
|
|
|
|
|
|
@@ -304,9 +304,9 @@ void decaf_add_sub ( |
|
|
|
add_sub_point(a,b,c,do_sub); |
|
|
|
} |
|
|
|
|
|
|
|
decaf_bool_t decaf_eq ( const decaf_point_t a, const decaf_point_t b ) { |
|
|
|
gf L0, L1; |
|
|
|
gf_mul ( L0, b->y, a->x ); |
|
|
|
gf_mul ( L1, a->y, b->x ); |
|
|
|
return gf_eq(L0,L1); |
|
|
|
decaf_bool_t decaf_eq ( const decaf_point_t p, const decaf_point_t q ) { |
|
|
|
gf a, b; |
|
|
|
gf_mul ( a, p->y, q->x ); |
|
|
|
gf_mul ( b, q->y, p->x ); |
|
|
|
return gf_eq(a,b); |
|
|
|
} |