int ecCheck (const ecPoint *p) /* confirm that y^2 + x*y = x^3 + EC_B for point p */ { gfPoint t1, t2, t3, b; b[0] = 1; b[1] = EC_B; gfSquare (t1, p->y); gfMultiply (t2, p->x, p->y); gfAdd (t1, t1, t2); /* t1 := y^2 + x*y */ gfSquare (t2, p->x); gfMultiply (t3, t2, p->x); gfAdd (t2, t3, b); /*/ t2 := x^3 + EC_B */ return gfEqual (t1, t2); } /* ecCheck */
void ecDouble (ecPoint *p) /* sets p := 2*p */ { gfPoint lambda, t1, t2; /* evaluate lambda = x + y/x: */ gfInvert (t1, p->x); gfMultiply (lambda, p->y, t1); gfAdd (lambda, lambda, p->x); /* evaluate x3 = lambda^2 + lambda: */ gfSquare (t1, lambda); gfAdd (t1, t1, lambda); /* now t1 = x3 */ /* evaluate y3 = x^2 + lambda*x3 + x3: */ gfSquare (p->y, p->x); gfMultiply (t2, lambda, t1); gfAdd (p->y, p->y, t2); gfAdd (p->y, p->y, t1); /* deposit the value of x3: */ gfCopy (p->x, t1); } /* ecDouble */
void gfSquareRoot (gfPoint p, lunit b) /* sets p := sqrt(b) = b^(2^(GF_M-1)) */ { int i; gfPoint q; assert (logt != NULL && expt != NULL); assert (p != NULL); q[0] = 1; q[1] = b; if ((GF_M - 1) & 1) { /* GF_M - 1 is odd */ gfSquare (p, q); i = GF_M - 2; } else { /* GF_M - 1 is even */ gfCopy (p, q); i = GF_M - 1; } while (i) { gfSquare (p, p); gfSquare (p, p); i -= 2; } } /* gfSquareRoot */
static int gfSlowTrace (const gfPoint p) /* slowly evaluates to the trace of p (or an error code) */ { int i; gfPoint t; assert (logt != NULL && expt != NULL); assert (p != NULL); gfCopy (t, p); for (i = 1; i < GF_M; i++) { gfSquare (t, t); gfAdd (t, t, p); } return t[0] != 0; } /* gfSlowTrace */
void ecAdd (ecPoint *p, const ecPoint *q) /* sets p := p + q */ { gfPoint 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 (gfEqual (p->x, q->x)) { /* either p == q or p == -q: */ if (gfEqual (p->y, q->y)) { /* points are equal; double p: */ ecDouble (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): */ gfAdd (ty, p->y, q->y); gfAdd (tx, p->x, q->x); gfInvert (t, tx); gfMultiply (lambda, ty, t); /* evaluate x3 = lambda^2 + lambda + x1 + x2: */ gfSquare (x3, lambda); gfAdd (x3, x3, lambda); gfAdd (x3, x3, tx); /* evaluate y3 = lambda*(x1 + x3) + x3 + y1: */ gfAdd (tx, p->x, x3); gfMultiply (t, lambda, tx); gfAdd (t, t, x3); gfAdd (p->y, t, p->y); /* deposit the value of x3: */ gfCopy (p->x, x3); } } else { /* just copy q into p: */ gfCopy (p->x, q->x); gfCopy (p->y, q->y); } } } /* ecAdd */
int ecCalcY (ecPoint *p, int ybit) /* given the x coordinate of p, evaluate y such that y^2 + x*y = x^3 + EC_B */ { gfPoint a, b, t; b[0] = 1; b[1] = EC_B; if (p->x[0] == 0) { /* elliptic equation reduces to y^2 = EC_B: */ gfSquareRoot (p->y, EC_B); return 1; } /* evaluate alpha = x^3 + b = (x^2)*x + EC_B: */ gfSquare (t, p->x); /* keep t = x^2 for beta evaluation */ gfMultiply (a, t, p->x); gfAdd (a, a, b); /* now a == alpha */ if (a[0] == 0) { p->y[0] = 0; /* destroy potentially sensitive data: */ gfClear (a); gfClear (t); return 1; } /* evaluate beta = alpha/x^2 = x + EC_B/x^2 */ gfSmallDiv (t, EC_B); gfInvert (a, t); gfAdd (a, p->x, a); /* now a == beta */ /* check if a solution exists: */ if (gfTrace (a) != 0) { /* destroy potentially sensitive data: */ gfClear (a); gfClear (t); return 0; /* no solution */ } /* solve equation t^2 + t + beta = 0 so that gfYbit(t) == ybit: */ gfQuadSolve (t, a); if (gfYbit (t) != ybit) { t[1] ^= 1; } /* compute y = x*t: */ gfMultiply (p->y, p->x, t); /* destroy potentially sensitive data: */ gfClear (a); gfClear (t); return 1; } /* ecCalcY */