const ec_group_t *ec_curve_lookup(ec_curve_t curve) { ec_group_t *grp = NULL; switch (curve) { case ECC_CURVE_E521: default: grp = &ecc_curve_e521; if (0 == ecc_curve_e521_is_init) { /* Set our prime p = 2^521 - 1 */ { ul one; ul_set_ui(one, 1); ul_set_ui(grp->p->n, 0); ul_setbit(521, grp->p->n); ul_sub(grp->p->n, grp->p->n, one); mod_set(grp->p, grp->p->n); } /* Set our c = 1*/ ul_set_ui(grp->c, 1); ul_to_montgomery(grp->c, grp->c, grp->p); /* Set our d = -376014 */ { ul zero; ul_set_ui(zero, 0); ul_to_montgomery(zero, zero, grp->p); ul_set_ui(grp->d, 376014); ul_to_montgomery(grp->d, grp->d, grp->p); ul_modsub(grp->d, zero, grp->d, grp->p); } /* set the generator */ { ul_set_fullui(grp->g->X, 0x75, 0x2cb45c48, 0x648b189d, 0xf90cb229, 0x6b2878a3, 0xbfd9f42f, 0xc6c818ec, 0x8bf3c9c0, 0xc6203913, 0xf6ecc5cc, 0xc72434b1, 0xae949d56, 0x8fc99c60, 0x59d0fb13, 0x364838aa, 0x302a940a, 0x2f19ba6c); ul_to_montgomery(grp->g->X, grp->g->X, grp->p); ul_set_ui(grp->g->Y, 0xc); ul_to_montgomery(grp->g->Y, grp->g->Y, grp->p); ul_set_ui(grp->g->Z, 0x1); ul_to_montgomery(grp->g->Z, grp->g->Z, grp->p); } /* set the group order */ { ul_set_fullui(grp->n, 0x7f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffd, 0x15b6c647, 0x46fc85f7, 0x36b8af5e, 0x7ec53f04, 0xfbd8c456, 0x9a8f1f45, 0x40ea2435, 0xf5180d6b); } ecc_curve_e521_is_init = 1; } return grp; } }
// 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; }