diff --git a/src/decaf.c b/src/decaf.c index b9af62c..da7590a 100644 --- a/src/decaf.c +++ b/src/decaf.c @@ -414,7 +414,7 @@ deisogenize ( cond_neg ( s, toggle_hibit_s ^ hibit(s) ); #else /* More complicated because of rotation */ - /* FIXME This code is wrong for certain non-Curve25519 curves; check if it's because of Cofactor==8 or IMAGINE_ROTATION */ + /* MAGIC This code is wrong for certain non-Curve25519 curves; check if it's because of Cofactor==8 or IMAGINE_ROTATION */ gf c, d; gf_s *b = s, *a = minus_t_over_s; @@ -1164,67 +1164,49 @@ void API_NS(point_from_hash_nonuniform) ( point_t p, const unsigned char ser[SER_BYTES] ) { - // TODO: simplify since we don't return a hint anymore - // TODO: test pathological case ur0^2 = 1/(1-d) - gf r0,r,a,b,c,dee,D,N,rN,e; + /* TODO: test pathological case ur0^2 = 1/(1-d) */ + gf r0,r,a,b,c,D,N,e; gf_deserialize(r0,ser); gf_strong_reduce(r0); gf_sqr(a,r0); #if P_MOD_8 == 5 - /* r = QNR * a */ + /* r = QNR * r0^2 */ gf_mul(r,a,SQRT_MINUS_ONE); -#else +#elif P_MOD_8 == 3 || P_MOD_8 == 7 gf_sub(r,ZERO,a); +#else +#error "Only supporting p=3,5,7 mod 8" #endif - gf_mulw_sgn(dee,ONE,EDWARDS_D); - gf_mulw_sgn(c,r,EDWARDS_D); - + /* Compute D := (dr+a-d)(dr-ar-d) with a=1 */ - gf_sub(a,c,dee); - gf_add(a,a,ONE); - gf_sub(b,c,r); - gf_sub(b,b,dee); + gf_sub(a,r,ONE); + gf_mulw_sgn(b,a,EDWARDS_D); /* dr-d */ + gf_add(a,b,ONE); + gf_sub(b,b,r); gf_mul(D,a,b); /* compute N := (r+1)(a-2d) */ gf_add(a,r,ONE); gf_mulw_sgn(N,a,1-2*EDWARDS_D); - /* e = +-1/sqrt(+-ND) */ - gf_mul(rN,r,N); - gf_mul(a,rN,D); - - mask_t square = gf_isqrt_chk(e,a,DECAF_FALSE); - - /* b <- t/s */ - cond_sel(c,r0,r,square); /* r? = sqr ? r : 1 */ - /* In two steps to avoid overflow on 32-bit arch */ - gf_mulw_sgn(a,c,1-2*EDWARDS_D); - gf_mulw_sgn(b,a,1-2*EDWARDS_D); - gf_sub(c,r,ONE); - gf_mul(a,b,c); /* = r? * (r-1) * (a-2d)^2 with a=1 */ - gf_mul(b,a,e); - cond_neg(b,~square); - cond_sel(c,r0,ONE,square); - gf_mul(a,e,c); - gf_mul(c,a,D); /* 1/s except for sign. FUTURE: simplify using this. */ - gf_sub(b,b,c); - - /* a <- s = e * N * (sqr ? r : r0) - * e^2 r N D = 1 - * 1/s = 1/(e * N * (sqr ? r : r0)) = e * D * (sqr ? 1 : r0) - */ - gf_mul(a,N,r0); - cond_sel(rN,a,rN,square); - gf_mul(a,rN,e); - gf_mul(c,a,b); - - /* Normalize/negate */ - mask_t neg_s = hibit(a) ^ ~square; - cond_neg(a,neg_s); /* ends up negative if ~square */ - - /* b <- t */ - cond_sel(b,c,ONE,gf_eq(c,ZERO)); /* 0,0 -> 1,0 */ + /* e = +-sqrt(1/ND) or +-r0 * sqrt(qnr/ND) */ + gf_mul(a,D,N); + mask_t square = gf_isqrt_chk(b,a,DECAF_FALSE); + cond_sel(c,r0,ONE,square); /* r? = square ? 1 : r0 */ + gf_mul(e,b,c); + + /* s@a = +-|N.e| */ + gf_mul(a,N,e); + cond_neg(a,hibit(a)^square); /* NB this is - what is listen in the paper */ + + /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */ + gf_mulw_sgn(c,e,1-2*EDWARDS_D); /* (a-2d)e */ + gf_sqr(b,c); + gf_sub(e,r,ONE); + gf_mul(c,b,e); + gf_mul(b,c,N); + cond_neg(b,square); + gf_sub(b,b,ONE); /* isogenize */ #if IMAGINE_TWIST diff --git a/src/include/field.h b/src/include/field.h index 0846a47..3a3ec96 100644 --- a/src/include/field.h +++ b/src/include/field.h @@ -43,14 +43,19 @@ gf_sqrn ( static inline void gf_sub_nr ( gf c, const gf a, const gf b ) { gf_sub_RAW(c,a,b); gf_bias(c, 2); - if (DECAF_WORD_BITS==32) gf_weak_reduce(c); // HACK + if (DECAF_WORD_BITS==32) gf_weak_reduce(c); // HACK PERF MAGIC + // Depending on headroom, this is needed in some of the Ed routines, but + // not in the Montgomery ladder. Need to find a better way to prevent + // overflow. In particular, the headroom depends on the field+arch combo, + // not just one or the other, and whether the reduction is needed depends + // also on the algorithm. } /** Subtract mod p. Bias by amt but don't reduce. */ static inline void gf_subx_nr ( gf c, const gf a, const gf b, int amt ) { gf_sub_RAW(c,a,b); gf_bias(c, amt); - if (DECAF_WORD_BITS==32) gf_weak_reduce(c); // HACK + if (DECAF_WORD_BITS==32) gf_weak_reduce(c); // HACK PERF MAGIC } diff --git a/test/test_decaf.cxx b/test/test_decaf.cxx index 3a0a714..afc3081 100644 --- a/test/test_decaf.cxx +++ b/test/test_decaf.cxx @@ -474,7 +474,7 @@ int main(int argc, char **argv) { Tests::test_cfrg_crypto(); Tests::test_cfrg_vectors(); Tests::test_crypto(); - + printf("\n"); printf("Testing %s:\n", Ed448Goldilocks::name()); Tests::test_arithmetic();