diff --git a/src/decaf_fast.c b/src/decaf_fast.c index 367ba55..2a19f4f 100644 --- a/src/decaf_fast.c +++ b/src/decaf_fast.c @@ -42,7 +42,8 @@ extern const gf SQRT_ONE_MINUS_D; /* TODO: Intern this? */ #define sv static void #define snv static void __attribute__((noinline)) #define siv static inline void __attribute__((always_inline)) -static const gf ZERO = {{{0}}}, ONE = {{{1}}}; + + const scalar_t API_NS(scalar_one) = {{{1}}}, API_NS(scalar_zero) = {{{0}}}; extern const scalar_t API_NS(sc_r2); @@ -50,6 +51,14 @@ extern const decaf_word_t API_NS(MONTGOMERY_FACTOR); extern const point_t API_NS(point_base); +/* These are externally exposed (but private) instead of static so that + * f_arithmetic.c can use it + */ +#define ONE API_NS(ONE) +#define ZERO API_NS(ZERO) +#define gf_eq API_NS(gf_eq) +const gf ZERO = {{{0}}}, ONE = {{{1}}}; + /* Projective Niels coordinates */ typedef struct { gf a, b, c; } niels_s, niels_t[1]; typedef struct { niels_t n; gf z; } __attribute__((aligned(32))) pniels_s, pniels_t[1]; /* MAGIC alignment */ @@ -103,7 +112,7 @@ siv cond_swap(gf x, gf_s *__restrict__ y, decaf_bool_t swap) { } /** Compare a==b */ -static decaf_word_t __attribute__((noinline)) gf_eq(const gf a, const gf b) { +decaf_word_t __attribute__((noinline)) gf_eq(const gf a, const gf b) { gf c; gf_sub(c,a,b); gf_strong_reduce(c); @@ -1078,6 +1087,7 @@ void API_NS(point_from_hash_nonuniform) ( 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; gf_deser(r0,ser); gf_strong_reduce(r0); diff --git a/src/include/constant_time.h b/src/include/constant_time.h index 4d4cde4..b249606 100644 --- a/src/include/constant_time.h +++ b/src/include/constant_time.h @@ -238,6 +238,9 @@ constant_time_mask ( * * Note that the output is not __restrict__, but if it overlaps either * input, it must be equal and not partially overlap. + * + * TODO: this has the opposite convention of certain other cond select functions, + * because they are effectively [a,b][bool(mask)] instead of mask ? a : b. */ static __inline__ void __attribute__((unused,always_inline)) diff --git a/src/p25519/f_arithmetic.c b/src/p25519/f_arithmetic.c index e89fa7e..b4bb6dc 100644 --- a/src/p25519/f_arithmetic.c +++ b/src/p25519/f_arithmetic.c @@ -9,6 +9,7 @@ */ #include "field.h" +#include "constant_time.h" const gf_25519_t P25519_SQRT_MINUS_ONE = {FIELD_LITERAL( 0x61b274a0ea0b0, @@ -18,20 +19,9 @@ const gf_25519_t P25519_SQRT_MINUS_ONE = {FIELD_LITERAL( 0x2b8324804fc1d )}; -static const gf_25519_t ONE = {FIELD_LITERAL( // FIXME copy-pasted - 1,0,0,0,0 -)}; - -// ARCH MAGIC FIXME copy-pasted from decaf_fast.c -static mask_t gf_eq(const gf_25519_t a, const gf_25519_t b) { - gf_25519_t c; - gf_sub(c,a,b); - gf_strong_reduce(c); - mask_t ret=0; - int i; - for (i=0; i<5; i++) { ret |= c->limb[i]; } - return ((__uint128_t)ret - 1) >> 64; -} +/* TODO put in header */ +extern const gf_25519_t decaf_255_ONE; +extern mask_t decaf_255_gf_eq(const gf_25519_t a, const gf_25519_t b); /* Guarantee: a^2 x = 0 if x = 0; else a^2 x = 1 or SQRT_MINUS_ONE; */ void @@ -51,10 +41,8 @@ gf_isr ( st[i&1][0] = tmp2[0]; } - mask_t mask = gf_eq(st[1],ONE) | gf_eq(st[1],SQRT_MINUS_ONE); + mask_t mask = decaf_255_gf_eq(st[1],decaf_255_ONE) | decaf_255_gf_eq(st[1],SQRT_MINUS_ONE); - // ARCH MAGIC FIXME: should be cond_sel - for (i=0; i<5; i++) tmp1->limb[i] = (ONE->limb[i] & mask) - | (SQRT_MINUS_ONE->limb[i] & ~mask); + constant_time_select(tmp1, decaf_255_ONE, SQRT_MINUS_ONE, sizeof(tmp1), mask); gf_mul(a,tmp1,st[0]); }