void fpinv_mont(felm_t a) { // Field inversion using Montgomery arithmetic, a = a^(-1)*R mod p. felm_t tt; fpcopy(a, tt); fpinv_chain_mont(tt); fpsqr_mont(tt, tt); fpsqr_mont(tt, tt); fpmul_mont(a, tt, a); }
static void LADDER3PT(const f2elm_t xP, const f2elm_t xQ, const f2elm_t xPQ, const digit_t* m, const unsigned int AliceOrBob, point_proj_t R, const f2elm_t A) { point_proj_t R0 = {0}, R2 = {0}; f2elm_t A24 = {0}; digit_t mask; int i, nbits, bit, swap, prevbit = 0; if (AliceOrBob == ALICE) { nbits = OALICE_BITS; } else { nbits = OBOB_BITS; } // Initializing constant fpcopy((digit_t*)&Montgomery_one, A24[0]); fp2add(A24, A24, A24); fp2add(A, A24, A24); fp2div2(A24, A24); fp2div2(A24, A24); // A24 = (A+2)/4 // Initializing points fp2copy(xQ, R0->X); fpcopy((digit_t*)&Montgomery_one, (digit_t*)R0->Z); fp2copy(xPQ, R2->X); fpcopy((digit_t*)&Montgomery_one, (digit_t*)R2->Z); fp2copy(xP, R->X); fpcopy((digit_t*)&Montgomery_one, (digit_t*)R->Z); fpzero((digit_t*)(R->Z)[1]); // Main loop for (i = 0; i < nbits; i++) { bit = (m[i >> LOG2RADIX] >> (i & (RADIX-1))) & 1; swap = bit ^ prevbit; prevbit = bit; mask = 0 - (digit_t)swap; swap_points(R, R2, mask); xDBLADD(R0, R2, R->X, A24); fp2mul_mont(R2->X, R->Z, R2->X); } }
void get_A(const f2elm_t xP, const f2elm_t xQ, const f2elm_t xR, f2elm_t A) { // Given the x-coordinates of P, Q, and R, returns the value A corresponding to the Montgomery curve E_A: y^2=x^3+A*x^2+x such that R=Q-P on E_A. // Input: the x-coordinates xP, xQ, and xR of the points P, Q and R. // Output: the coefficient A corresponding to the curve E_A: y^2=x^3+A*x^2+x. f2elm_t t0, t1, one = {0}; fpcopy((digit_t *) &Montgomery_one, one[0]); fp2add(xP, xQ, t1); // t1 = xP+xQ fp2mul_mont(xP, xQ, t0); // t0 = xP*xQ fp2mul_mont(xR, t1, A); // A = xR*t1 fp2add(t0, A, A); // A = A+t0 fp2mul_mont(t0, xR, t0); // t0 = t0*xR fp2sub(A, one, A); // A = A-1 fp2add(t0, t0, t0); // t0 = t0+t0 fp2add(t1, xR, t1); // t1 = t1+xR fp2add(t0, t0, t0); // t0 = t0+t0 fp2sqr_mont(A, A); // A = A^2 fp2inv_mont(t0); // t0 = 1/t0 fp2mul_mont(A, t0, A); // A = A*t0 fp2sub(A, t1, A); // Afinal = A-t1 }
void fp2copy(const f2elm_t *a, f2elm_t *c) { // Copy a GF(p^2) element, c = a. fpcopy(a->e[0], c->e[0]); fpcopy(a->e[1], c->e[1]); }
void fpinv_chain_mont(felm_t a) { // Chain to compute a^(p-3)/4 using Montgomery arithmetic. unsigned int i, j; felm_t t[15], tt; // Precomputed table fpsqr_mont(a, tt); fpmul_mont(a, tt, t[0]); for (i = 0; i <= 13; i++) fpmul_mont(t[i], tt, t[i+1]); fpcopy(a, tt); for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); fpmul_mont(a, tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[8], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[6], tt, tt); for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); fpmul_mont(t[9], tt, tt); for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); fpmul_mont(t[0], tt, tt); for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); fpmul_mont(a, tt, tt); for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); fpmul_mont(t[6], tt, tt); for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); fpmul_mont(t[2], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[8], tt, tt); for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); fpmul_mont(a, tt, tt); for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); fpmul_mont(t[10], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[0], tt, tt); for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); fpmul_mont(t[10], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[10], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[5], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[2], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[6], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[3], tt, tt); for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); fpmul_mont(t[5], tt, tt); for (i = 0; i < 12; i++) fpsqr_mont(tt, tt); fpmul_mont(t[12], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[8], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[6], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[12], tt, tt); for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); fpmul_mont(t[11], tt, tt); for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); fpmul_mont(t[6], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[5], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[14], tt, tt); for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); fpmul_mont(t[14], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[5], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[6], tt, tt); for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); fpmul_mont(t[8], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(a, tt, tt); for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); fpmul_mont(t[4], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[6], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[5], tt, tt); for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); fpmul_mont(t[7], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(a, tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[0], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[11], tt, tt); for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[13], tt, tt); for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); fpmul_mont(t[1], tt, tt); for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); fpmul_mont(t[10], tt, tt); for (j = 0; j < 49; j++) { for (i = 0; i < 5; i++) fpsqr_mont(tt, tt); fpmul_mont(t[14], tt, tt); } fpcopy(tt, a); }