@@ -92,7 +92,7 @@ gf_cpy(gf x, const gf y) { x[0] = y[0]; } | |||||
/** Constant time, x = is_z ? z : y */ | /** Constant time, x = is_z ? z : y */ | ||||
static INLINE void | static INLINE void | ||||
cond_sel(gf x, const gf y, const gf z, decaf_bool_t is_z) { | cond_sel(gf x, const gf y, const gf z, decaf_bool_t is_z) { | ||||
constant_time_select(x,z,y,sizeof(gf),is_z); | |||||
constant_time_select(x,z,y,sizeof(gf),is_z,0); | |||||
} | } | ||||
/** Constant time, if (neg) x=-x; */ | /** Constant time, if (neg) x=-x; */ | ||||
@@ -115,6 +115,8 @@ cond_swap(gf x, gf_s *__restrict__ y, decaf_bool_t swap) { | |||||
/** Compare a==b */ | /** Compare a==b */ | ||||
/* Not static because it's used in inverse square root. */ | /* Not static because it's used in inverse square root. */ | ||||
decaf_word_t gf_eq(const gf a, const gf b); | |||||
decaf_word_t | decaf_word_t | ||||
gf_eq(const gf a, const gf b) { | gf_eq(const gf a, const gf b) { | ||||
gf c; | gf c; | ||||
@@ -300,7 +302,7 @@ decaf_error_t API_NS(scalar_invert) ( | |||||
residue = 0; | residue = 0; | ||||
} | } | ||||
if (trailing > 0 && (trailing & (1<<SCALAR_WINDOW_BITS)-1) == 0) { | |||||
if (trailing > 0 && (trailing & ((1<<SCALAR_WINDOW_BITS)-1)) == 0) { | |||||
if (started) { | if (started) { | ||||
sc_montmul(out,out,precmp[trailing>>(SCALAR_WINDOW_BITS+1)]); | sc_montmul(out,out,precmp[trailing>>(SCALAR_WINDOW_BITS+1)]); | ||||
} else { | } else { | ||||
@@ -1328,8 +1330,8 @@ static void gf_batch_invert ( | |||||
static void batch_normalize_niels ( | static void batch_normalize_niels ( | ||||
niels_t *table, | niels_t *table, | ||||
gf *zs, | |||||
gf *zis, | |||||
const gf *zs, | |||||
gf *__restrict__ zis, | |||||
int n | int n | ||||
) { | ) { | ||||
int i; | int i; | ||||
@@ -1408,7 +1410,7 @@ void API_NS(precompute) ( | |||||
} | } | ||||
} | } | ||||
batch_normalize_niels(table->table,zs,zis,n<<(t-1)); | |||||
batch_normalize_niels(table->table,(const gf *)zs,zis,n<<(t-1)); | |||||
decaf_bzero(zs,sizeof(zs)); | decaf_bzero(zs,sizeof(zs)); | ||||
decaf_bzero(zis,sizeof(zis)); | decaf_bzero(zis,sizeof(zis)); | ||||
@@ -1484,7 +1486,7 @@ void API_NS(point_cond_sel) ( | |||||
decaf_bool_t pick_b | decaf_bool_t pick_b | ||||
) { | ) { | ||||
pick_b = ~word_is_zero(pick_b); | pick_b = ~word_is_zero(pick_b); | ||||
constant_time_select(out,b,a,sizeof(point_t),pick_b); | |||||
constant_time_select(out,b,a,sizeof(point_t),pick_b,0); | |||||
} | } | ||||
void API_NS(scalar_cond_sel) ( | void API_NS(scalar_cond_sel) ( | ||||
@@ -1494,7 +1496,7 @@ void API_NS(scalar_cond_sel) ( | |||||
decaf_bool_t pick_b | decaf_bool_t pick_b | ||||
) { | ) { | ||||
pick_b = ~word_is_zero(pick_b); | pick_b = ~word_is_zero(pick_b); | ||||
constant_time_select(out,b,a,sizeof(scalar_t),pick_b); | |||||
constant_time_select(out,b,a,sizeof(scalar_t),pick_b,sizeof(out->limb[0])); | |||||
} | } | ||||
/* FUTURE: restore Curve25519 Montgomery ladder? */ | /* FUTURE: restore Curve25519 Montgomery ladder? */ | ||||
@@ -1627,7 +1629,7 @@ void API_NS(precompute_wnafs) ( | |||||
memcpy(out[i], tmp[i]->n, sizeof(niels_t)); | memcpy(out[i], tmp[i]->n, sizeof(niels_t)); | ||||
gf_cpy(zs[i], tmp[i]->z); | gf_cpy(zs[i], tmp[i]->z); | ||||
} | } | ||||
batch_normalize_niels(out, zs, zis, 1<<DECAF_WNAF_FIXED_TABLE_BITS); | |||||
batch_normalize_niels(out, (const gf *)zs, zis, 1<<DECAF_WNAF_FIXED_TABLE_BITS); | |||||
decaf_bzero(tmp,sizeof(tmp)); | decaf_bzero(tmp,sizeof(tmp)); | ||||
decaf_bzero(zs,sizeof(zs)); | decaf_bzero(zs,sizeof(zs)); | ||||
@@ -234,7 +234,8 @@ constant_time_mask ( | |||||
/** | /** | ||||
* @brief Constant-time a = mask ? bTrue : bFalse. | * @brief Constant-time a = mask ? bTrue : bFalse. | ||||
* | * | ||||
* The input and output must be at least as aligned as elem_bytes. | |||||
* The input and output must be at least as aligned as alignment_bytes | |||||
* or their size, whichever is smaller. | |||||
* | * | ||||
* Note that the output is not __restrict__, but if it overlaps either | * Note that the output is not __restrict__, but if it overlaps either | ||||
* input, it must be equal and not partially overlap. | * input, it must be equal and not partially overlap. | ||||
@@ -249,16 +250,19 @@ constant_time_select ( | |||||
const void *bTrue_, | const void *bTrue_, | ||||
const void *bFalse_, | const void *bFalse_, | ||||
word_t elem_bytes, | word_t elem_bytes, | ||||
mask_t mask | |||||
mask_t mask, | |||||
size_t alignment_bytes | |||||
) { | ) { | ||||
unsigned char *a = (unsigned char *)a_; | unsigned char *a = (unsigned char *)a_; | ||||
const unsigned char *bTrue = (const unsigned char *)bTrue_; | const unsigned char *bTrue = (const unsigned char *)bTrue_; | ||||
const unsigned char *bFalse = (const unsigned char *)bFalse_; | const unsigned char *bFalse = (const unsigned char *)bFalse_; | ||||
alignment_bytes |= elem_bytes; | |||||
word_t k; | word_t k; | ||||
big_register_t br_mask = br_set_to_mask(mask); | big_register_t br_mask = br_set_to_mask(mask); | ||||
for (k=0; k<=elem_bytes-sizeof(big_register_t); k+=sizeof(big_register_t)) { | for (k=0; k<=elem_bytes-sizeof(big_register_t); k+=sizeof(big_register_t)) { | ||||
if (elem_bytes % sizeof(big_register_t)) { | |||||
if (alignment_bytes % sizeof(big_register_t)) { | |||||
/* unaligned */ | /* unaligned */ | ||||
((unaligned_br_t*)(&a[k]))->unaligned = | ((unaligned_br_t*)(&a[k]))->unaligned = | ||||
( br_mask & ((const unaligned_br_t*)(&bTrue [k]))->unaligned) | ( br_mask & ((const unaligned_br_t*)(&bTrue [k]))->unaligned) | ||||
@@ -273,7 +277,7 @@ constant_time_select ( | |||||
if (elem_bytes % sizeof(big_register_t) >= sizeof(word_t)) { | if (elem_bytes % sizeof(big_register_t) >= sizeof(word_t)) { | ||||
for (; k<=elem_bytes-sizeof(word_t); k+=sizeof(word_t)) { | for (; k<=elem_bytes-sizeof(word_t); k+=sizeof(word_t)) { | ||||
if (elem_bytes % sizeof(word_t)) { | |||||
if (alignment_bytes % sizeof(word_t)) { | |||||
/* unaligned */ | /* unaligned */ | ||||
((unaligned_word_t*)(&a[k]))->unaligned = | ((unaligned_word_t*)(&a[k]))->unaligned = | ||||
( mask & ((const unaligned_word_t*)(&bTrue [k]))->unaligned) | ( mask & ((const unaligned_word_t*)(&bTrue [k]))->unaligned) | ||||
@@ -43,6 +43,6 @@ gf_isr ( | |||||
mask_t mask = decaf_255_gf_eq(st[1],decaf_255_ONE) | decaf_255_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); | ||||
constant_time_select(tmp1, decaf_255_ONE, SQRT_MINUS_ONE, sizeof(tmp1), mask); | |||||
constant_time_select(tmp1, decaf_255_ONE, SQRT_MINUS_ONE, sizeof(tmp1), mask, 0); | |||||
gf_mul(a,tmp1,st[0]); | gf_mul(a,tmp1,st[0]); | ||||
} | } |
@@ -21,14 +21,11 @@ extern "C" { | |||||
#define DECAF_255_SCALAR_BITS 253 | #define DECAF_255_SCALAR_BITS 253 | ||||
#define DECAF_255_SCALAR_LIMBS (256/DECAF_WORD_BITS) | #define DECAF_255_SCALAR_LIMBS (256/DECAF_WORD_BITS) | ||||
#ifndef __DECAF_255_GF_DEFINED__ | |||||
#define __DECAF_255_GF_DEFINED__ 1 | |||||
/** Galois field element internal structure */ | /** Galois field element internal structure */ | ||||
typedef struct gf_25519_s { | typedef struct gf_25519_s { | ||||
decaf_word_t limb[DECAF_255_LIMBS]; | decaf_word_t limb[DECAF_255_LIMBS]; | ||||
} gf_25519_s, gf_25519_t[1]; | |||||
} __attribute__((aligned(32))) gf_25519_s, gf_25519_t[1]; | |||||
/** @endcond */ | /** @endcond */ | ||||
#endif /* __DECAF_255_GF_DEFINED__ */ | |||||
/** Number of bytes in a serialized point. */ | /** Number of bytes in a serialized point. */ | ||||
#define DECAF_255_SER_BYTES 32 | #define DECAF_255_SER_BYTES 32 | ||||