void ec_double (ec_point *p) /* sets p := 2*p */ { gf_point lambda, t1, t2; /* evaluate lambda = x + y/x: */ gf_invert (t1, p->x); gf_multiply (lambda, p->y, t1); gf_add (lambda, lambda, p->x); /* evaluate x3 = lambda^2 + lambda: */ gf_square (t1, lambda); gf_add (t1, t1, lambda); /* now t1 = x3 */ /* evaluate y3 = x^2 + lambda*x3 + x3: */ gf_square (p->y, p->x); gf_multiply (t2, lambda, t1); gf_add (p->y, p->y, t2); gf_add (p->y, p->y, t1); /* deposit the value of x3: */ gf_copy (p->x, t1); } /* ec_double */
// carré de p modulo un certain polynôme g, sq[] contient les carrés // modulo g de la base canonique des polynômes de degré < d, où d est // le degré de g. La table sq[] sera calculée par poly_sqmod_init() void poly_sqmod(poly_t res, poly_t p, poly_t * sq, int d) { int i, j; gf_t a; poly_set_to_zero(res); // termes de bas degré for (i = 0; i < d / 2; ++i) poly_set_coeff(res, i * 2, gf_square(poly_coeff(p, i))); // termes de haut degré for (; i < d; ++i) { if (poly_coeff(p, i) != gf_zero()) { a = gf_square(poly_coeff(p, i)); for (j = 0; j < d; ++j) poly_addto_coeff(res, j, gf_mul_fast(a, poly_coeff(sq[i], j))); } } // mise à jour du degré poly_set_deg(res, d - 1); while ((poly_deg(res) >= 0) && (poly_coeff(res, poly_deg(res)) == gf_zero())) poly_set_deg(res, poly_deg(res) - 1); }
void poly_sqmod(poly_t res, poly_t p, poly_t * sq, int d) { int i, j; gf_t a; poly_set_to_zero(res); // terms of low degree for (i = 0; i < d / 2; ++i) poly_set_coeff(res, i * 2, gf_square(poly_coeff(p, i))); // terms of high degree for (; i < d; ++i) { if (poly_coeff(p, i) != gf_zero()) { a = gf_square(poly_coeff(p, i)); for (j = 0; j < d; ++j) poly_addto_coeff(res, j, gf_mul_fast(a, poly_coeff(sq[i], j))); } } // Update degre poly_set_deg(res, d - 1); while ((poly_deg(res) >= 0) && (poly_coeff(res, poly_deg(res)) == gf_zero())) poly_set_deg(res, poly_deg(res) - 1); }
void ec_add (ec_point *p, const ec_point *q) /* sets p := p + q */ { gf_point lambda, t, tx, ty, x3; /* first check if there is indeed work to do (q != 0): */ if (q->x[0] != 0 || q->y[0] != 0) { if (p->x[0] != 0 || p->y[0] != 0) { /* p != 0 and q != 0 */ if (gf_equal (p->x, q->x)) { /* either p == q or p == -q: */ if (gf_equal (p->y, q->y)) { /* points are equal; double p: */ ec_double (p); } else { /* must be inverse: result is zero */ /* (should assert that q->y = p->x + p->y) */ p->x[0] = p->y[0] = 0; } } else { /* p != 0, q != 0, p != q, p != -q */ /* evaluate lambda = (y1 + y2)/(x1 + x2): */ gf_add (ty, p->y, q->y); gf_add (tx, p->x, q->x); gf_invert (t, tx); gf_multiply (lambda, ty, t); /* evaluate x3 = lambda^2 + lambda + x1 + x2: */ gf_square (x3, lambda); gf_add (x3, x3, lambda); gf_add (x3, x3, tx); /* evaluate y3 = lambda*(x1 + x3) + x3 + y1: */ gf_add (tx, p->x, x3); gf_multiply (t, lambda, tx); gf_add (t, t, x3); gf_add (p->y, t, p->y); /* deposit the value of x3: */ gf_copy (p->x, x3); } } else { /* just copy q into p: */ gf_copy (p->x, q->x); gf_copy (p->y, q->y); } } } /* ec_add */
int ec_calcy (ec_point *p, int ybit) /* given the x coordinate of p, evaluate y such that y^2 + x*y = x^3 + EC_B */ { gf_point a, b, t; b[0] = 1; b[1] = EC_B; if (p->x[0] == 0) { /* elliptic equation reduces to y^2 = EC_B: */ gf_squareroot (p->y, EC_B); return 1; } /* evaluate alpha = x^3 + b = (x^2)*x + EC_B: */ gf_square (t, p->x); /* keep t = x^2 for beta evaluation */ gf_multiply (a, t, p->x); gf_add (a, a, b); /* now a == alpha */ if (a[0] == 0) { p->y[0] = 0; /* destroy potentially sensitive data: */ gf_clear (a); gf_clear (t); return 1; } /* evaluate beta = alpha/x^2 = x + EC_B/x^2 */ gf_smalldiv (t, EC_B); gf_invert (a, t); gf_add (a, p->x, a); /* now a == beta */ /* check if a solution exists: */ if (gf_trace (a) != 0) { /* destroy potentially sensitive data: */ gf_clear (a); gf_clear (t); return 0; /* no solution */ } /* solve equation t^2 + t + beta = 0 so that gf_ybit(t) == ybit: */ gf_quadsolve (t, a); if (gf_ybit (t) != ybit) { t[1] ^= 1; } /* compute y = x*t: */ gf_multiply (p->y, p->x, t); /* destroy potentially sensitive data: */ gf_clear (a); gf_clear (t); return 1; } /* ec_calcy */