// Convert a point on the elliptic curve in compressed form into an edwards_point_t void uncompress_point(edwards_point_t dst, ul pt, uint8_t y_sign, const ec_group_t* grp) { ul one; ul_set_ui(one, 1); ul_to_montgomery(one, one, grp->p); // Set the X and Z coordinates of the EC point ul_set(dst->X, pt); ul_set(dst->Z, one); // Need to compute the Y coordinate as [y^2] = = (1 - [x]^2) / (1 + 376014[x]^2) // First compute x^2 ul x2; ul_modmul(x2, pt, pt, grp->p); // Compute the numerator ul numer; ul_modsub(numer, one, x2, grp->p); // Compute the denominator ul coeff; ul_set_ui(coeff, 376014); ul_to_montgomery(coeff, coeff, grp->p); ul prod; ul_modmul(prod, coeff, x2, grp->p); ul denom; ul_modadd(denom, one, prod, grp->p); // Compute the inverse of the denominator // The mod-inv function needs a non-montgomery-form number ul_from_montgomery(denom, denom, grp->p); ul denom_inv; ul_modinv(denom_inv, denom, grp->p->n); ul_to_montgomery(denom_inv, denom_inv, grp->p); // Compute y^2 ul y2; ul_modmul(y2, numer, denom_inv, grp->p); // Find the two roots of y^2, and then pick the appropriate one based on the given sign ul r1; ul r2; ul_modsqrt_S1(r1, r2, y2, grp->p); ul unroot; ul_from_montgomery(unroot, r1, grp->p); if (ul_testbit(0, unroot) == y_sign) ul_set(dst->Y, r1); else ul_set(dst->Y, r2); }
int pm1_stage1(ul f, ul X, mod m, pm1_plan_t *plan) { int i, bt; u_int64_t *E_ptr, e, mask; ul one, two, t, x; bt = 0; ul_init(one); ul_init(two); ul_init(t); ul_init(x); ul_set_ui(one, 1); ul_to_montgomery(one, one, m); ul_modadd(two, one, one, m); /* stage1 - compute 2^E (mod n) */ ul_set(t, two); i = plan->E_n_words - 1; E_ptr = &plan->E[i]; mask = plan->E_mask; mask >>= 1; for(; i >= 0; i--, E_ptr--) { e = *E_ptr; for(; mask; mask >>= 1) { ul_modmul(t, t, t, m); if(e & mask) { ul_modadd(t, t, t, m); } } mask = 1ULL << 63; } ul_set(x, t); for(i = 0; i < plan->exp2; i++) { ul_modmul(x, x, x, m); #if PM1_BACKTRACKING if(ul_cmp(x, one) == 0) { ul_set(x, t); bt = 1; break; } ul_set(t, x); #endif } ul_modsub(t, x, one, m); ul_gcd(f, t, m->n); if(ul_cmp_ui(f, 1) > 0 || plan->B1 >= plan->stage2.B2) { ul_clear(one); ul_clear(two); ul_clear(t); ul_clear(x); return 0; } /* Compute X = x + 1/x */ ul_from_montgomery(x, x, m); ul_modinv(X, x, m->n); ul_modadd(X, X, x, m); ul_to_montgomery(X, X, m); ul_clear(one); ul_clear(two); ul_clear(t); ul_clear(x); return bt; /* pp1_stage2(t, X, &plan->stage2, two, m); ul_gcd(f, t, m); pp1_stage2 (t, X, &(plan->stage2), two, m); mod_gcd (f, t, m); mod_clear (one, m); mod_clear (two, m); mod_clear (t, m); mod_clear (X, m); mod_clear (x, m); return bt; */ return bt; }
static void edwards_double(edwards_point_t dst, const edwards_point_t p, const ec_group_t *grp) { /* R1 = X1 */ ul R1; ul_set(R1, p->X); /* R2 = Y1 */ ul R2; ul_set(R2, p->Y); /* R3 = Z1 */ ul R3; ul_set(R3, p->Z); /* R3 = c*R3 */ ul_modmul(R3, grp->c, R3, grp->p); /* R4 = R1^2 */ ul R4; ul_modmul(R4, R1, R1, grp->p); /* R1 = R1+R2 */ ul_modadd(R1, R1, R2, grp->p); /* R1 = R1^2 */ ul_modmul(R1, R1, R1, grp->p); /* R2 = R2^2 */ ul_modmul(R2, R2, R2, grp->p); /* R3 = R3^2 */ ul_modmul(R3, R3, R3, grp->p); /* R3 = 2*R3 */ ul_modadd(R3, R3, R3, grp->p); /* R4 = R2+R4 */ ul_modadd(R4, R2, R4, grp->p); /* R2 = 2*R2 */ ul_modadd(R2, R2, R2, grp->p); /* R2 = R4-R2 */ ul_modsub(R2, R4, R2, grp->p); /* R1 = R1-R4 */ ul_modsub(R1, R1, R4, grp->p); /* R2 = R2*R4 */ ul_modmul(R2, R2, R4, grp->p); /* R3 = R4-R3 */ ul_modsub(R3, R4, R3, grp->p); /* R1 = R1*R3 */ ul_modmul(R1, R1, R3, grp->p); /* R3 = R3*R4 */ ul_modmul(R3, R3, R4, grp->p); /* R1 = c*R1 */ ul_modmul(R1, grp->c, R1, grp->p); /* R2 = c*R2 */ ul_modmul(R2, grp->c, R2, grp->p); /* X3 = R1 */ ul_set(dst->X, R1); /* Y3 = R2 */ ul_set(dst->Y, R2); /* Z3 = R3 */ ul_set(dst->Z, R3); }
static void edwards_add(edwards_point_t dst, const edwards_point_t src1, const edwards_point_t src2, const ec_group_t *grp) { /* R1 = X1 */ ul R1; ul_set(R1, src1->X); /* R2 = Y1 */ ul R2; ul_set(R2, src1->Y); /* R3 = Z1 */ ul R3; ul_set(R3, src1->Z); /* R4 = X2 */ ul R4; ul_set(R4, src2->X); /* R5 = Y2 */ ul R5; ul_set(R5, src2->Y); /* R6 = Z2 */ ul R6; ul_set(R6, src2->Z); /* R3 = R3*R6 */ ul_modmul(R3, R3, R6, grp->p); /* R7 = R1+R2 */ ul R7; ul_modadd(R7, R1, R2, grp->p); /* R8 = R4+R5 */ ul R8; ul_modadd(R8, R4, R5, grp->p); /* R1 = R1*R4 */ ul_modmul(R1, R1, R4, grp->p); /* R2 = R2*R5 */ ul_modmul(R2, R2, R5, grp->p); /* R7 = R7*R8 */ ul_modmul(R7, R7, R8, grp->p); /* R7 = R7-R1 */ ul_modsub(R7, R7, R1, grp->p); /* R7 = R7-R2 */ ul_modsub(R7, R7, R2, grp->p); /* R7 = R7*R3 */ ul_modmul(R7, R7, R3, grp->p); /* R8 = R1*R2 */ ul_modmul(R8, R1, R2, grp->p); /* R8 = d*R8 */ ul_modmul(R8, grp->d, R8, grp->p); /* R2 = R2-R1 */ ul_modsub(R2, R2, R1, grp->p); /* R2 = R2*R3 */ ul_modmul(R2, R2, R3, grp->p); /* R3 = R3^2 */ ul_modmul(R3, R3, R3, grp->p); /* R1 = R3-R8 */ ul_modsub(R1, R3, R8, grp->p); /* R3 = R3+R8 */ ul_modadd(R3, R3, R8, grp->p); /* R2 = R2*R3 */ ul_modmul(R2, R2, R3, grp->p); /* R3 = R3*R1 */ ul_modmul(R3, R3, R1, grp->p); /* R1 = R1*R7 */ ul_modmul(R1, R1, R7, grp->p); /* R3 = c*R3 */ ul_modmul(R3, grp->c, R3, grp->p); /* X3 = R1 */ ul_set(dst->X, R1); /* Y3 = R2 */ ul_set(dst->Y, R2); /* Z3 = R3 */ ul_set(dst->Z, R3); }