constant-time inverses
This commit is contained in:
parent
e4a5cc3cf2
commit
d3d72f64cc
@ -74,16 +74,6 @@ static void gf2x_mod(DIGIT out[], const DIGIT in[]) {
|
|||||||
out[0] &= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS) - 1;
|
out[0] &= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void left_bit_shift(const int length, DIGIT in[]) {
|
|
||||||
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < length - 1; j++) {
|
|
||||||
in[j] <<= 1; /* logical shift does not need clearing */
|
|
||||||
in[j] |= in[j + 1] >> (DIGIT_SIZE_b - 1);
|
|
||||||
}
|
|
||||||
in[j] <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void right_bit_shift(unsigned int length, DIGIT in[]) {
|
static void right_bit_shift(unsigned int length, DIGIT in[]) {
|
||||||
|
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
@ -153,17 +143,6 @@ void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_transpose_in_place(DIGIT A[]) {
|
|||||||
A[NUM_DIGITS_GF2X_ELEMENT - 1] = (A[NUM_DIGITS_GF2X_ELEMENT - 1] & (~mask)) | a00;
|
A[NUM_DIGITS_GF2X_ELEMENT - 1] = (A[NUM_DIGITS_GF2X_ELEMENT - 1] & (~mask)) | a00;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rotate_bit_left(DIGIT in[]) { /* equivalent to x * in(x) mod x^P+1 */
|
|
||||||
|
|
||||||
DIGIT mask, rotated_bit;
|
|
||||||
int msb_offset_in_digit = MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS - 1;
|
|
||||||
mask = ((DIGIT)0x1) << msb_offset_in_digit;
|
|
||||||
rotated_bit = !!(in[0] & mask);
|
|
||||||
in[0] &= ~mask;
|
|
||||||
left_bit_shift(NUM_DIGITS_GF2X_ELEMENT, in);
|
|
||||||
in[NUM_DIGITS_GF2X_ELEMENT - 1] |= rotated_bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */
|
static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */
|
||||||
|
|
||||||
DIGIT rotated_bit = in[NUM_DIGITS_GF2X_ELEMENT - 1] & ((DIGIT)0x1);
|
DIGIT rotated_bit = in[NUM_DIGITS_GF2X_ELEMENT - 1] & ((DIGIT)0x1);
|
||||||
@ -173,87 +152,90 @@ static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */
|
|||||||
in[0] |= rotated_bit;
|
in[0] |= rotated_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gf2x_swap(const int length, DIGIT f[], DIGIT s[]) {
|
/* cond swap: swaps digits A and B if swap_mask == -1 */
|
||||||
|
static void gf2x_cswap(DIGIT *a, DIGIT *b, int swap_mask) {
|
||||||
|
int i;
|
||||||
DIGIT t;
|
DIGIT t;
|
||||||
for (int i = length - 1; i >= 0; i--) {
|
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
t = f[i];
|
t = swap_mask & (a[i] ^ b[i]);
|
||||||
f[i] = s[i];
|
a[i] ^= t;
|
||||||
s[i] = t;
|
b[i] ^= t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* returns -1 mask if x != 0, otherwise 0 */
|
||||||
* Optimized extended GCD algorithm to compute the multiplicative inverse of
|
static inline int nonzero(DIGIT x) {
|
||||||
* a non-zero element in GF(2)[x] mod x^P+1, in polyn. representation.
|
DIGIT t = x;
|
||||||
*
|
t = -t;
|
||||||
* H. Brunner, A. Curiger, and M. Hofstetter. 1993.
|
t >>= DIGIT_SIZE_b - 1;
|
||||||
* On Computing Multiplicative Inverses in GF(2^m).
|
return -(int)t;
|
||||||
* IEEE Trans. Comput. 42, 8 (August 1993), 1010-1015.
|
}
|
||||||
* DOI=http://dx.doi.org/10.1109/12.238496
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Henri Cohen, Gerhard Frey, Roberto Avanzi, Christophe Doche, Tanja Lange,
|
|
||||||
* Kim Nguyen, and Frederik Vercauteren. 2012.
|
|
||||||
* Handbook of Elliptic and Hyperelliptic Curve Cryptography,
|
|
||||||
* Second Edition (2nd ed.). Chapman & Hall/CRC.
|
|
||||||
* (Chapter 11 -- Algorithm 11.44 -- pag 223)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]) { /* in^{-1} mod x^P-1 */
|
|
||||||
|
|
||||||
int i;
|
/* returns -1 mask if x < 0 else 0 */
|
||||||
int delta = 0;
|
static inline int negative(int x) {
|
||||||
DIGIT u[NUM_DIGITS_GF2X_ELEMENT] = {0};
|
uint32_t u = x;
|
||||||
DIGIT v[NUM_DIGITS_GF2X_ELEMENT] = {0};
|
u >>= 31;
|
||||||
DIGIT s[NUM_DIGITS_GF2X_MODULUS] = {0};
|
return -(int)u;
|
||||||
DIGIT f[NUM_DIGITS_GF2X_MODULUS] = {0}; // alignas(32)?
|
}
|
||||||
|
|
||||||
DIGIT mask;
|
/* return f(0) as digit */
|
||||||
u[NUM_DIGITS_GF2X_ELEMENT - 1] = 0x1;
|
static inline DIGIT lsb(const DIGIT *p) {
|
||||||
v[NUM_DIGITS_GF2X_ELEMENT - 1] = 0x0;
|
DIGIT mask = (DIGIT)1;
|
||||||
|
return p[NUM_DIGITS_GF2X_ELEMENT - 1] & mask;
|
||||||
|
}
|
||||||
|
|
||||||
s[NUM_DIGITS_GF2X_MODULUS - 1] = 0x1;
|
/* multiply poly with scalar and accumulate, expects s all-zero of all-one mask */
|
||||||
|
static void gf2x_mult_scalar_acc(DIGIT *f, const DIGIT *g, const DIGIT s) {
|
||||||
|
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
|
f[i] = f[i] ^ (s & g[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mask = (((DIGIT)0x1) << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);
|
/* constant-time inverse, source: gcd.cr.yp.to */
|
||||||
s[0] |= mask;
|
int PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]) {
|
||||||
|
int i, loop, swap, delta = 1;
|
||||||
|
DIGIT g0_mask;
|
||||||
|
|
||||||
for (i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= 0 && in[i] == 0; i--) { };
|
DIGIT f[NUM_DIGITS_GF2X_MODULUS] = {0}; // f = x^P + 1
|
||||||
if (i < 0) {
|
DIGIT g[NUM_DIGITS_GF2X_ELEMENT]; // g = in
|
||||||
return 0;
|
DIGIT *v = out; // v = 0, save space
|
||||||
|
DIGIT r[NUM_DIGITS_GF2X_ELEMENT] = {0}; // r = 1
|
||||||
|
|
||||||
|
f[NUM_DIGITS_GF2X_MODULUS - 1] = 1;
|
||||||
|
f[0] |= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
|
g[i] = in[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = NUM_DIGITS_GF2X_MODULUS - 1; i >= 0 ; i--) {
|
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
f[i] = in[i];
|
v[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i <= 2 * P; i++) {
|
r[NUM_DIGITS_GF2X_ELEMENT - 1] = 1;
|
||||||
if ( (f[0] & mask) == 0 ) {
|
|
||||||
left_bit_shift(NUM_DIGITS_GF2X_MODULUS, f);
|
for (loop = 0; loop < 2 * P - 1; ++loop) {
|
||||||
rotate_bit_left(u);
|
|
||||||
delta += 1;
|
swap = negative(-delta) & nonzero(lsb(g)); // swap = -1 if -delta < 0 AND g(0) != 0
|
||||||
} else {
|
delta ^= swap & (delta ^ -delta); // cond swap delta with -delta if swap
|
||||||
if ( (s[0] & mask) != 0) {
|
delta++;
|
||||||
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_add(s, s, f, NUM_DIGITS_GF2X_MODULUS);
|
|
||||||
PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_add(v, v, u);
|
gf2x_cswap(f, g, swap);
|
||||||
}
|
gf2x_cswap(v, r, swap);
|
||||||
left_bit_shift(NUM_DIGITS_GF2X_MODULUS, s);
|
|
||||||
if ( delta == 0 ) {
|
g0_mask = -lsb(g);
|
||||||
gf2x_swap(NUM_DIGITS_GF2X_MODULUS, f, s);
|
|
||||||
gf2x_swap(NUM_DIGITS_GF2X_ELEMENT, u, v);
|
// g = (g - g0 * f) / x
|
||||||
rotate_bit_left(u);
|
gf2x_mult_scalar_acc(g, f, g0_mask);
|
||||||
delta = 1;
|
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, g);
|
||||||
} else {
|
|
||||||
rotate_bit_right(u);
|
// r = (r - g0 * v) / x
|
||||||
delta = delta - 1;
|
gf2x_mult_scalar_acc(r, v, g0_mask);
|
||||||
}
|
rotate_bit_right(r);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= 0 ; i--) {
|
return nonzero(delta); // -1 if fail, 0 if success
|
||||||
out[i] = u[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (delta == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {
|
void PQCLEAN_LEDAKEMLT12_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {
|
||||||
|
@ -74,16 +74,6 @@ static void gf2x_mod(DIGIT out[], const DIGIT in[]) {
|
|||||||
out[0] &= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS) - 1;
|
out[0] &= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void left_bit_shift(const int length, DIGIT in[]) {
|
|
||||||
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < length - 1; j++) {
|
|
||||||
in[j] <<= 1; /* logical shift does not need clearing */
|
|
||||||
in[j] |= in[j + 1] >> (DIGIT_SIZE_b - 1);
|
|
||||||
}
|
|
||||||
in[j] <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void right_bit_shift(unsigned int length, DIGIT in[]) {
|
static void right_bit_shift(unsigned int length, DIGIT in[]) {
|
||||||
|
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
@ -94,7 +84,6 @@ static void right_bit_shift(unsigned int length, DIGIT in[]) {
|
|||||||
in[j] >>= 1;
|
in[j] >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* shifts by whole digits */
|
/* shifts by whole digits */
|
||||||
static void left_DIGIT_shift_n(unsigned int length, DIGIT in[], unsigned int amount) {
|
static void left_DIGIT_shift_n(unsigned int length, DIGIT in[], unsigned int amount) {
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
@ -151,17 +140,6 @@ void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_transpose_in_place(DIGIT A[]) {
|
|||||||
A[NUM_DIGITS_GF2X_ELEMENT - 1] = (A[NUM_DIGITS_GF2X_ELEMENT - 1] & (~mask)) | a00;
|
A[NUM_DIGITS_GF2X_ELEMENT - 1] = (A[NUM_DIGITS_GF2X_ELEMENT - 1] & (~mask)) | a00;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rotate_bit_left(DIGIT in[]) { /* equivalent to x * in(x) mod x^P+1 */
|
|
||||||
|
|
||||||
DIGIT mask, rotated_bit;
|
|
||||||
int msb_offset_in_digit = MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS - 1;
|
|
||||||
mask = ((DIGIT)0x1) << msb_offset_in_digit;
|
|
||||||
rotated_bit = !!(in[0] & mask);
|
|
||||||
in[0] &= ~mask;
|
|
||||||
left_bit_shift(NUM_DIGITS_GF2X_ELEMENT, in);
|
|
||||||
in[NUM_DIGITS_GF2X_ELEMENT - 1] |= rotated_bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */
|
static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */
|
||||||
|
|
||||||
DIGIT rotated_bit = in[NUM_DIGITS_GF2X_ELEMENT - 1] & ((DIGIT)0x1);
|
DIGIT rotated_bit = in[NUM_DIGITS_GF2X_ELEMENT - 1] & ((DIGIT)0x1);
|
||||||
@ -171,87 +149,90 @@ static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */
|
|||||||
in[0] |= rotated_bit;
|
in[0] |= rotated_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gf2x_swap(const int length, DIGIT f[], DIGIT s[]) {
|
/* cond swap: swaps digits A and B if swap_mask == -1 */
|
||||||
|
static void gf2x_cswap(DIGIT *a, DIGIT *b, int swap_mask) {
|
||||||
|
int i;
|
||||||
DIGIT t;
|
DIGIT t;
|
||||||
for (int i = length - 1; i >= 0; i--) {
|
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
t = f[i];
|
t = swap_mask & (a[i] ^ b[i]);
|
||||||
f[i] = s[i];
|
a[i] ^= t;
|
||||||
s[i] = t;
|
b[i] ^= t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* returns -1 mask if x != 0, otherwise 0 */
|
||||||
* Optimized extended GCD algorithm to compute the multiplicative inverse of
|
static inline int nonzero(DIGIT x) {
|
||||||
* a non-zero element in GF(2)[x] mod x^P+1, in polyn. representation.
|
DIGIT t = x;
|
||||||
*
|
t = -t;
|
||||||
* H. Brunner, A. Curiger, and M. Hofstetter. 1993.
|
t >>= DIGIT_SIZE_b - 1;
|
||||||
* On Computing Multiplicative Inverses in GF(2^m).
|
return -(int)t;
|
||||||
* IEEE Trans. Comput. 42, 8 (August 1993), 1010-1015.
|
}
|
||||||
* DOI=http://dx.doi.org/10.1109/12.238496
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Henri Cohen, Gerhard Frey, Roberto Avanzi, Christophe Doche, Tanja Lange,
|
|
||||||
* Kim Nguyen, and Frederik Vercauteren. 2012.
|
|
||||||
* Handbook of Elliptic and Hyperelliptic Curve Cryptography,
|
|
||||||
* Second Edition (2nd ed.). Chapman & Hall/CRC.
|
|
||||||
* (Chapter 11 -- Algorithm 11.44 -- pag 223)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]) { /* in^{-1} mod x^P-1 */
|
|
||||||
|
|
||||||
int i;
|
/* returns -1 mask if x < 0 else 0 */
|
||||||
int delta = 0;
|
static inline int negative(int x) {
|
||||||
DIGIT u[NUM_DIGITS_GF2X_ELEMENT] = {0};
|
uint32_t u = x;
|
||||||
DIGIT v[NUM_DIGITS_GF2X_ELEMENT] = {0};
|
u >>= 31;
|
||||||
DIGIT s[NUM_DIGITS_GF2X_MODULUS] = {0};
|
return -(int)u;
|
||||||
DIGIT f[NUM_DIGITS_GF2X_MODULUS] = {0}; // alignas(32)?
|
}
|
||||||
|
|
||||||
DIGIT mask;
|
/* return f(0) as digit */
|
||||||
u[NUM_DIGITS_GF2X_ELEMENT - 1] = 0x1;
|
static inline DIGIT lsb(const DIGIT *p) {
|
||||||
v[NUM_DIGITS_GF2X_ELEMENT - 1] = 0x0;
|
DIGIT mask = (DIGIT)1;
|
||||||
|
return p[NUM_DIGITS_GF2X_ELEMENT - 1] & mask;
|
||||||
|
}
|
||||||
|
|
||||||
s[NUM_DIGITS_GF2X_MODULUS - 1] = 0x1;
|
/* multiply poly with scalar and accumulate, expects s all-zero of all-one mask */
|
||||||
|
static void gf2x_mult_scalar_acc(DIGIT *f, const DIGIT *g, const DIGIT s) {
|
||||||
|
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
|
f[i] = f[i] ^ (s & g[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mask = (((DIGIT)0x1) << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);
|
/* constant-time inverse, source: gcd.cr.yp.to */
|
||||||
s[0] |= mask;
|
int PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]) {
|
||||||
|
int i, loop, swap, delta = 1;
|
||||||
|
DIGIT g0_mask;
|
||||||
|
|
||||||
for (i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= 0 && in[i] == 0; i--) { };
|
DIGIT f[NUM_DIGITS_GF2X_MODULUS] = {0}; // f = x^P + 1
|
||||||
if (i < 0) {
|
DIGIT g[NUM_DIGITS_GF2X_ELEMENT]; // g = in
|
||||||
return 0;
|
DIGIT *v = out; // v = 0, save space
|
||||||
|
DIGIT r[NUM_DIGITS_GF2X_ELEMENT] = {0}; // r = 1
|
||||||
|
|
||||||
|
f[NUM_DIGITS_GF2X_MODULUS - 1] = 1;
|
||||||
|
f[0] |= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
|
g[i] = in[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = NUM_DIGITS_GF2X_MODULUS - 1; i >= 0 ; i--) {
|
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
f[i] = in[i];
|
v[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i <= 2 * P; i++) {
|
r[NUM_DIGITS_GF2X_ELEMENT - 1] = 1;
|
||||||
if ( (f[0] & mask) == 0 ) {
|
|
||||||
left_bit_shift(NUM_DIGITS_GF2X_MODULUS, f);
|
for (loop = 0; loop < 2 * P - 1; ++loop) {
|
||||||
rotate_bit_left(u);
|
|
||||||
delta += 1;
|
swap = negative(-delta) & nonzero(lsb(g)); // swap = -1 if -delta < 0 AND g(0) != 0
|
||||||
} else {
|
delta ^= swap & (delta ^ -delta); // cond swap delta with -delta if swap
|
||||||
if ( (s[0] & mask) != 0) {
|
delta++;
|
||||||
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_add(s, s, f, NUM_DIGITS_GF2X_MODULUS);
|
|
||||||
PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_add(v, v, u);
|
gf2x_cswap(f, g, swap);
|
||||||
}
|
gf2x_cswap(v, r, swap);
|
||||||
left_bit_shift(NUM_DIGITS_GF2X_MODULUS, s);
|
|
||||||
if ( delta == 0 ) {
|
g0_mask = -lsb(g);
|
||||||
gf2x_swap(NUM_DIGITS_GF2X_MODULUS, f, s);
|
|
||||||
gf2x_swap(NUM_DIGITS_GF2X_ELEMENT, u, v);
|
// g = (g - g0 * f) / x
|
||||||
rotate_bit_left(u);
|
gf2x_mult_scalar_acc(g, f, g0_mask);
|
||||||
delta = 1;
|
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, g);
|
||||||
} else {
|
|
||||||
rotate_bit_right(u);
|
// r = (r - g0 * v) / x
|
||||||
delta = delta - 1;
|
gf2x_mult_scalar_acc(r, v, g0_mask);
|
||||||
}
|
rotate_bit_right(r);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= 0 ; i--) {
|
return nonzero(delta); // -1 if fail, 0 if success
|
||||||
out[i] = u[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (delta == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {
|
void PQCLEAN_LEDAKEMLT32_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {
|
||||||
|
@ -74,16 +74,6 @@ static void gf2x_mod(DIGIT out[], const DIGIT in[]) {
|
|||||||
out[0] &= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS) - 1;
|
out[0] &= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void left_bit_shift(const int length, DIGIT in[]) {
|
|
||||||
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < length - 1; j++) {
|
|
||||||
in[j] <<= 1; /* logical shift does not need clearing */
|
|
||||||
in[j] |= in[j + 1] >> (DIGIT_SIZE_b - 1);
|
|
||||||
}
|
|
||||||
in[j] <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void right_bit_shift(unsigned int length, DIGIT in[]) {
|
static void right_bit_shift(unsigned int length, DIGIT in[]) {
|
||||||
|
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
@ -94,7 +84,6 @@ static void right_bit_shift(unsigned int length, DIGIT in[]) {
|
|||||||
in[j] >>= 1;
|
in[j] >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* shifts by whole digits */
|
/* shifts by whole digits */
|
||||||
static void left_DIGIT_shift_n(unsigned int length, DIGIT in[], unsigned int amount) {
|
static void left_DIGIT_shift_n(unsigned int length, DIGIT in[], unsigned int amount) {
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
@ -151,17 +140,6 @@ void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_transpose_in_place(DIGIT A[]) {
|
|||||||
A[NUM_DIGITS_GF2X_ELEMENT - 1] = (A[NUM_DIGITS_GF2X_ELEMENT - 1] & (~mask)) | a00;
|
A[NUM_DIGITS_GF2X_ELEMENT - 1] = (A[NUM_DIGITS_GF2X_ELEMENT - 1] & (~mask)) | a00;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rotate_bit_left(DIGIT in[]) { /* equivalent to x * in(x) mod x^P+1 */
|
|
||||||
|
|
||||||
DIGIT mask, rotated_bit;
|
|
||||||
int msb_offset_in_digit = MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS - 1;
|
|
||||||
mask = ((DIGIT)0x1) << msb_offset_in_digit;
|
|
||||||
rotated_bit = !!(in[0] & mask);
|
|
||||||
in[0] &= ~mask;
|
|
||||||
left_bit_shift(NUM_DIGITS_GF2X_ELEMENT, in);
|
|
||||||
in[NUM_DIGITS_GF2X_ELEMENT - 1] |= rotated_bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */
|
static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */
|
||||||
|
|
||||||
DIGIT rotated_bit = in[NUM_DIGITS_GF2X_ELEMENT - 1] & ((DIGIT)0x1);
|
DIGIT rotated_bit = in[NUM_DIGITS_GF2X_ELEMENT - 1] & ((DIGIT)0x1);
|
||||||
@ -171,87 +149,90 @@ static void rotate_bit_right(DIGIT in[]) { /* x^{-1} * in(x) mod x^P+1 */
|
|||||||
in[0] |= rotated_bit;
|
in[0] |= rotated_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gf2x_swap(const int length, DIGIT f[], DIGIT s[]) {
|
/* cond swap: swaps digits A and B if swap_mask == -1 */
|
||||||
|
static void gf2x_cswap(DIGIT *a, DIGIT *b, int swap_mask) {
|
||||||
|
int i;
|
||||||
DIGIT t;
|
DIGIT t;
|
||||||
for (int i = length - 1; i >= 0; i--) {
|
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
t = f[i];
|
t = swap_mask & (a[i] ^ b[i]);
|
||||||
f[i] = s[i];
|
a[i] ^= t;
|
||||||
s[i] = t;
|
b[i] ^= t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* returns -1 mask if x != 0, otherwise 0 */
|
||||||
* Optimized extended GCD algorithm to compute the multiplicative inverse of
|
static inline int nonzero(DIGIT x) {
|
||||||
* a non-zero element in GF(2)[x] mod x^P+1, in polyn. representation.
|
DIGIT t = x;
|
||||||
*
|
t = -t;
|
||||||
* H. Brunner, A. Curiger, and M. Hofstetter. 1993.
|
t >>= DIGIT_SIZE_b - 1;
|
||||||
* On Computing Multiplicative Inverses in GF(2^m).
|
return -(int)t;
|
||||||
* IEEE Trans. Comput. 42, 8 (August 1993), 1010-1015.
|
}
|
||||||
* DOI=http://dx.doi.org/10.1109/12.238496
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Henri Cohen, Gerhard Frey, Roberto Avanzi, Christophe Doche, Tanja Lange,
|
|
||||||
* Kim Nguyen, and Frederik Vercauteren. 2012.
|
|
||||||
* Handbook of Elliptic and Hyperelliptic Curve Cryptography,
|
|
||||||
* Second Edition (2nd ed.). Chapman & Hall/CRC.
|
|
||||||
* (Chapter 11 -- Algorithm 11.44 -- pag 223)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]) { /* in^{-1} mod x^P-1 */
|
|
||||||
|
|
||||||
int i;
|
/* returns -1 mask if x < 0 else 0 */
|
||||||
int delta = 0;
|
static inline int negative(int x) {
|
||||||
DIGIT u[NUM_DIGITS_GF2X_ELEMENT] = {0};
|
uint32_t u = x;
|
||||||
DIGIT v[NUM_DIGITS_GF2X_ELEMENT] = {0};
|
u >>= 31;
|
||||||
DIGIT s[NUM_DIGITS_GF2X_MODULUS] = {0};
|
return -(int)u;
|
||||||
DIGIT f[NUM_DIGITS_GF2X_MODULUS] = {0}; // alignas(32)?
|
}
|
||||||
|
|
||||||
DIGIT mask;
|
/* return f(0) as digit */
|
||||||
u[NUM_DIGITS_GF2X_ELEMENT - 1] = 0x1;
|
static inline DIGIT lsb(const DIGIT *p) {
|
||||||
v[NUM_DIGITS_GF2X_ELEMENT - 1] = 0x0;
|
DIGIT mask = (DIGIT)1;
|
||||||
|
return p[NUM_DIGITS_GF2X_ELEMENT - 1] & mask;
|
||||||
|
}
|
||||||
|
|
||||||
s[NUM_DIGITS_GF2X_MODULUS - 1] = 0x1;
|
/* multiply poly with scalar and accumulate, expects s all-zero of all-one mask */
|
||||||
|
static void gf2x_mult_scalar_acc(DIGIT *f, const DIGIT *g, const DIGIT s) {
|
||||||
|
for (size_t i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
|
f[i] = f[i] ^ (s & g[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mask = (((DIGIT)0x1) << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);
|
/* constant-time inverse, source: gcd.cr.yp.to */
|
||||||
s[0] |= mask;
|
int PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_inverse(DIGIT out[], const DIGIT in[]) {
|
||||||
|
int i, loop, swap, delta = 1;
|
||||||
|
DIGIT g0_mask;
|
||||||
|
|
||||||
for (i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= 0 && in[i] == 0; i--) { };
|
DIGIT f[NUM_DIGITS_GF2X_MODULUS] = {0}; // f = x^P + 1
|
||||||
if (i < 0) {
|
DIGIT g[NUM_DIGITS_GF2X_ELEMENT]; // g = in
|
||||||
return 0;
|
DIGIT *v = out; // v = 0, save space
|
||||||
|
DIGIT r[NUM_DIGITS_GF2X_ELEMENT] = {0}; // r = 1
|
||||||
|
|
||||||
|
f[NUM_DIGITS_GF2X_MODULUS - 1] = 1;
|
||||||
|
f[0] |= ((DIGIT)1 << MSb_POSITION_IN_MSB_DIGIT_OF_MODULUS);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
|
g[i] = in[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = NUM_DIGITS_GF2X_MODULUS - 1; i >= 0 ; i--) {
|
for (i = 0; i < NUM_DIGITS_GF2X_ELEMENT; i++) {
|
||||||
f[i] = in[i];
|
v[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i <= 2 * P; i++) {
|
r[NUM_DIGITS_GF2X_ELEMENT - 1] = 1;
|
||||||
if ( (f[0] & mask) == 0 ) {
|
|
||||||
left_bit_shift(NUM_DIGITS_GF2X_MODULUS, f);
|
for (loop = 0; loop < 2 * P - 1; ++loop) {
|
||||||
rotate_bit_left(u);
|
|
||||||
delta += 1;
|
swap = negative(-delta) & nonzero(lsb(g)); // swap = -1 if -delta < 0 AND g(0) != 0
|
||||||
} else {
|
delta ^= swap & (delta ^ -delta); // cond swap delta with -delta if swap
|
||||||
if ( (s[0] & mask) != 0) {
|
delta++;
|
||||||
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_add(s, s, f, NUM_DIGITS_GF2X_MODULUS);
|
|
||||||
PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_add(v, v, u);
|
gf2x_cswap(f, g, swap);
|
||||||
}
|
gf2x_cswap(v, r, swap);
|
||||||
left_bit_shift(NUM_DIGITS_GF2X_MODULUS, s);
|
|
||||||
if ( delta == 0 ) {
|
g0_mask = -lsb(g);
|
||||||
gf2x_swap(NUM_DIGITS_GF2X_MODULUS, f, s);
|
|
||||||
gf2x_swap(NUM_DIGITS_GF2X_ELEMENT, u, v);
|
// g = (g - g0 * f) / x
|
||||||
rotate_bit_left(u);
|
gf2x_mult_scalar_acc(g, f, g0_mask);
|
||||||
delta = 1;
|
right_bit_shift(NUM_DIGITS_GF2X_ELEMENT, g);
|
||||||
} else {
|
|
||||||
rotate_bit_right(u);
|
// r = (r - g0 * v) / x
|
||||||
delta = delta - 1;
|
gf2x_mult_scalar_acc(r, v, g0_mask);
|
||||||
}
|
rotate_bit_right(r);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = NUM_DIGITS_GF2X_ELEMENT - 1; i >= 0 ; i--) {
|
return nonzero(delta); // -1 if fail, 0 if success
|
||||||
out[i] = u[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (delta == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {
|
void PQCLEAN_LEDAKEMLT52_LEAKTIME_gf2x_mod_mul(DIGIT Res[], const DIGIT A[], const DIGIT B[]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user