diff --git a/src/ec_point.c b/src/ec_point.c index df3294c..dcb8751 100644 --- a/src/ec_point.c +++ b/src/ec_point.c @@ -243,7 +243,7 @@ convert_tw_niels_to_tw_extensible ( } void -deserialize_montgomery_decaf ( +decaf_deserialize_montgomery ( montgomery_aux_a_t a, const field_a_t s ) { @@ -254,20 +254,6 @@ deserialize_montgomery_decaf ( field_set_ui ( a->zd, 0 ); } -mask_t -serialize_montgomery_decaf ( - field_a_t b, - const montgomery_aux_a_t a, - const field_a_t sbz -) { - field_a_t L0, L1; - field_isr(L0,a->zd); - field_sqr(L1,L0); - field_mul(b,a->xd,L1); - (void)sbz; - return 0; // Fail, because this routine isn't done yet. -} - void montgomery_aux_step ( struct montgomery_aux_t* a @@ -407,6 +393,82 @@ decaf_make_even ( field_strong_reduce ( a ); } +mask_t +decaf_serialize_montgomery ( + field_a_t out, + const montgomery_aux_a_t a, + mask_t swapped +) { + field_a_t xz_d, xz_a, x0, den, L0, L1, L2, L3; + mask_t zcase, output_zero, flip, succ, za_zero; + field_mul(xz_d, a->xd, a->zd); + field_mul(xz_a, a->xa, a->za); + output_zero = field_is_zero(xz_d); + za_zero = field_is_zero(a->za); + field_addw(xz_d, -output_zero); /* make xz_d always nonzero */ + zcase = output_zero | field_is_zero(xz_a); + + field_sqr(x0, a->s0); + + /* Curve test in zcase */ + field_copy(L0,x0); + field_addw(L0,1); + field_sqr(L1,L0); + field_mulw_scc_wr(L0,x0,-4*EDWARDS_D); + field_add(L1,L1,L0); + constant_time_select(xz_a,L1,xz_a,sizeof(xz_a),zcase); + + /* Compute denominator */ + field_mul(L0, x0, xz_d); + field_mulw(L2, L0, 4); + field_mul(L1, L2, xz_a); + field_isr(den, L1); + + /* Check squareness */ + field_sqr(L2, den); + field_mul(L0, L1, L2); + field_addw(L0, 1); + succ = ~field_low_bit(a->s0) & ~field_is_zero(L0); + + /* Compute y/x */ + field_mul(L1, x0, a->xd); + field_sub(L1, a->zd, L1); + field_mul(L0, a->za, L1); /* L0 = "opq" */ + field_mul(L1, x0, a->zd); + field_sub(L1, L1, a->xd); + field_mul(L2, a->xa, L1); /* L2 = "pqr" */ + + field_sub(L1, L0, L2); + field_add(L0, L0, L2); + field_mul(L2, L1, den); /* L2 = y0 / x0 */ + field_mul(L1, L0, den); /* L1 = yO / xO */ + flip = field_low_bit(L1) ^ field_low_bit(L2) ^ za_zero; + constant_time_select(L0, a->zd, a->xd, sizeof(L0), flip); /* L0 = "times" */ + /* OK, done with y-coordinates */ + + /* OK, now correct for swappage */ + field_add(den,den,den); + field_mul(L1,den,a->s0); + field_sqr(L2,L1); + field_mul(L3,L2,xz_a); + constant_time_select(den,L3,L1,sizeof(den),swapped &~ zcase); + + /* compute the output */ + field_mul(L1,L0,den); + + constant_time_select(L2,a->s0,a->zs,sizeof(L2),zcase); /* zs, but s0 in zcase */ + field_mul(L0,L1,L2); + + constant_time_select(L3,a->xd,a->zd,sizeof(L3),za_zero); + constant_time_select(L2,L3,a->xs,sizeof(L2),zcase); /* xs, but zq or qq in zcase */ + field_mul(out,L0,L2); + + constant_time_mask(out,out,sizeof(field_a_t),~output_zero); + decaf_make_even(out); + + return succ; +} + void decaf_serialize_extensible ( field_a_t b, diff --git a/src/goldilocks.c b/src/goldilocks.c index 32c9a12..866ed10 100644 --- a/src/goldilocks.c +++ b/src/goldilocks.c @@ -41,7 +41,7 @@ #else #define FIELD_HASH_BYTES (SHA512_OUTPUT_BYTES * ((FIELD_BYTES-1)/SHA512_OUTPUT_BYTES + 1)) static inline void field_hash_final ( - sha512_ctx_a_t *ctx, + sha512_ctx_a_t ctx, unsigned char out[FIELD_HASH_BYTES] ) { /* SHA PRNG I guess? I really should have used SHAKE */ diff --git a/src/include/constant_time.h b/src/include/constant_time.h index 405c2f5..e0cdca4 100644 --- a/src/include/constant_time.h +++ b/src/include/constant_time.h @@ -191,7 +191,7 @@ constant_time_lookup ( static __inline__ void __attribute__((unused,always_inline)) constant_time_mask ( - void *__restrict__ a_, + void * a_, const void *b_, word_t elem_bytes, mask_t mask diff --git a/src/include/ec_point.h b/src/include/ec_point.h index a22572f..0338782 100644 --- a/src/include/ec_point.h +++ b/src/include/ec_point.h @@ -296,14 +296,14 @@ serialize_montgomery ( ); mask_t -serialize_montgomery_decaf ( +decaf_serialize_montgomery ( field_a_t b, const montgomery_aux_a_t a, - const field_a_t sbz + mask_t swapped ); void -deserialize_montgomery_decaf ( +decaf_deserialize_montgomery ( montgomery_aux_a_t a, const field_a_t s ); diff --git a/src/include/scalarmul.h b/src/include/scalarmul.h index fb2bbd8..0fe8dac 100644 --- a/src/include/scalarmul.h +++ b/src/include/scalarmul.h @@ -100,7 +100,7 @@ montgomery_ladder ( /** * Full Montgomery aux ladder in decaf format. * - * Out = [2^n_extra_doubles * scalar] * in, where + * Out = scalar * in, where * scalar is little-endian and has length $nbits$ bits. * * This function (once it's done; TODO) will always reject points @@ -115,20 +115,17 @@ montgomery_ladder ( * @param [in] scalar The scalar's little-endian representation. * @param [in] nbits The number of bits in the scalar. Note that * unlike in Curve25519, we do not require the top bit to be set. - * @param [in] n_extra_doubles The number of extra doubles to do at - * the end. * * @retval MASK_SUCCESS The operation was successful. * @retval MASK_FAILURE The input point was invalid, or the output * would be the identity or the point of order 2. */ mask_t -montgomery_ladder_decaf ( +decaf_montgomery_ladder ( field_a_t out, const field_a_t in, const word_t *scalar, - unsigned int nbits, - unsigned int n_extra_doubles + unsigned int nbits ) __attribute__((warn_unused_result)); /** diff --git a/src/scalarmul.c b/src/scalarmul.c index bd9c2a9..8f861d5 100644 --- a/src/scalarmul.c +++ b/src/scalarmul.c @@ -49,15 +49,14 @@ montgomery_ladder ( } mask_t -montgomery_ladder_decaf ( +decaf_montgomery_ladder ( field_a_t out, const field_a_t in, const word_t *scalar, - unsigned int nbits, - unsigned int n_extra_doubles + unsigned int nbits ) { montgomery_aux_a_t mont; - deserialize_montgomery_decaf(mont, in); + decaf_deserialize_montgomery(mont, in); int i,j,n=(nbits-1)%WORD_BITS; mask_t pflip = 0; @@ -75,12 +74,7 @@ montgomery_ladder_decaf ( constant_time_cond_swap(mont->xa,mont->xd,sizeof(mont->xd),pflip); constant_time_cond_swap(mont->za,mont->zd,sizeof(mont->xd),pflip); - assert(n_extra_doubles < INT_MAX); - for (j=0; j<(int)n_extra_doubles; j++) { - montgomery_aux_step(mont); - } - - return serialize_montgomery_decaf(out, mont, in); + return decaf_serialize_montgomery(out, mont, pflip); } static __inline__ void diff --git a/test/bench.c b/test/bench.c index 5549a7d..6769ae8 100644 --- a/test/bench.c +++ b/test/bench.c @@ -328,7 +328,7 @@ int main(int argc, char **argv) { when = now(); for (i=0; i