diff --git a/src/decaf.c b/src/decaf.c index 39c0484..8ec5c47 100644 --- a/src/decaf.c +++ b/src/decaf.c @@ -61,35 +61,34 @@ siv gf_sqrn ( gf x, const gf y, int n ) { for (i=0; i> 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); } diff --git a/test/test_pointops.c b/test/test_pointops.c index 12aaffd..caff3c1 100644 --- a/test/test_pointops.c +++ b/test/test_pointops.c @@ -356,10 +356,20 @@ int test_decaf_evil (void) { scalarmul_ed(pt_ed, random_scalar); decaf_serialize_tw_extended(out_ed, pt_ed); + uint8_t ser_de[56], ser_ed[56]; + decaf_point_t pt_dec, pt_dec2; + memcpy(pt_dec, pt_ed, sizeof(pt_dec)); + decaf_encode(ser_de, pt_dec); + mask_t succ_dec = decaf_decode(pt_dec2, ser_de, -1); + field_serialize(ser_ed, out_ed); + if ((care_should && should != s_m) || ~s_base || s_e != s_te || s_m != s_te || s_ed != s_te || (s_te && ~field_eq(out_e,out_m)) || (s_ed && ~field_eq(out_e,out_ed)) + || memcmp(ser_de, ser_ed, 56) + || (s_e & ~succ_dec) + || (s_e & ~decaf_eq(pt_dec, pt_dec2)) ) { youfail(); field_print(" base", base); @@ -367,8 +377,9 @@ int test_decaf_evil (void) { field_print(" oute", out_e); field_print(" outE", out_ed); field_print(" outm", out_m); - printf(" succ: m=%d, e=%d, t=%d, b=%d, T=%d, should=%d[%d]\n", - -(int)s_m,-(int)s_e,-(int)s_te,-(int)s_base,-(int)s_ed,-(int)should,-(int)care_should + printf(" succ: m=%d, e=%d, t=%d, b=%d, T=%d, D=%d, should=%d[%d]\n", + -(int)s_m,-(int)s_e,-(int)s_te,-(int)s_base,-(int)s_ed,-(int)succ_dec, + -(int)should,-(int)care_should ); ret = -1; fails++;