poly_t * poly_syndrome_init(poly_t generator, gf_t *support, int n) { int i,j,t; gf_t a; poly_t * F; F = malloc(n * sizeof (poly_t)); t = poly_deg(generator); //g(z)=g_t+g_(t-1).z^(t-1)+......+g_1.z+g_0 //f(z)=f_(t-1).z^(t-1)+......+f_1.z+f_0 for(j=0; j<n; j++) { F[j] = poly_alloc(t-1); poly_set_coeff(F[j],t-1,gf_unit()); for(i=t-2; i>=0; i--) { poly_set_coeff(F[j],i,gf_add(poly_coeff(generator,i+1), gf_mul(support[j],poly_coeff(F[j],i+1)))); } a = gf_add(poly_coeff(generator,0),gf_mul(support[j],poly_coeff(F[j],0))); for(i=0; i<t; i++) { poly_set_coeff(F[j],i, gf_div(poly_coeff(F[j],i),a)); } } return F; }
static void pt_to_pniels(pniels_t b, const curve448_point_t a) { gf_sub(b->n->a, a->y, a->x); gf_add(b->n->b, a->x, a->y); gf_mulw(b->n->c, a->t, 2 * TWISTED_D); gf_add(b->z, a->z, a->z); }
static void niels_to_pt(curve448_point_t e, const niels_t n) { gf_add(e->y, n->b, n->a); gf_sub(e->x, n->b, n->a); gf_mul(e->t, e->y, e->x); gf_copy(e->z, ONE); }
void ec_sub (ec_point *p, const ec_point *r) /* sets p := p - r */ { ec_point t; gf_copy (t.x, r->x); gf_add (t.y, r->x, r->y); ec_add (p, &t); } /* ec_sub */
// p = p * x mod g // p de degré <= deg(g)-1 void poly_shiftmod(poly_t p, poly_t g) { int i, t; gf_t a; t = poly_deg(g); a = gf_div(p->coeff[t-1], g->coeff[t]); for (i = t - 1; i > 0; --i) p->coeff[i] = gf_add(p->coeff[i - 1], gf_mul(a, g->coeff[i])); p->coeff[0] = gf_mul(a, g->coeff[0]); }
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 */
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 */
static void pniels_to_pt(curve448_point_t e, const pniels_t d) { gf eu; gf_add(eu, d->n->b, d->n->a); gf_sub(e->y, d->n->b, d->n->a); gf_mul(e->t, e->y, eu); gf_mul(e->x, d->z, e->y); gf_mul(e->y, d->z, eu); gf_sqr(e->z, d->z); }
gf_t poly_eval_aux(gf_t * coeff, gf_t a, int d) { gf_t b; b = coeff[d--]; for (; d >= 0; --d) if (b != gf_zero()) b = gf_add(gf_mul(b, a), coeff[d]); else b = coeff[d]; return b; }
gf gf_poly(gf p[], int n, gf a) { int i = n-1; gf acc = 0; while(i>=0) { acc = gf_mul(acc, a); acc = gf_add(acc, p[i]); i--; } return acc; }
// C=AB // A: nxp // B: pxm // C: nxm void matrix_mul(unsigned char *A, unsigned char *B, unsigned char *C, int n, int p, int m) { int i; int j; int k; for(i=0; i<n; i++) { for(j=0; j<m; j++) { for(k=0; k<p; k++) { C[i*m+j] = gf_add(C[i*m+j], gf_mul(A[i*p+k],B[k*m+j])); } } } }
c448_bool_t curve448_point_valid(const curve448_point_t p) { mask_t out; gf a, b, c; gf_mul(a, p->x, p->y); gf_mul(b, p->z, p->t); out = gf_eq(a, b); gf_sqr(a, p->x); gf_sqr(b, p->y); gf_sub(a, b, a); gf_sqr(b, p->t); gf_mulw(c, b, TWISTED_D); gf_sqr(b, p->z); gf_add(b, b, c); out &= gf_eq(a, b); out &= ~gf_eq(p->z, ZERO); return mask_to_bool(out); }
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 */
void test_distributive_law() { suite("distributive law"); SOME3( test(gf_mult(gf_add(a,b), c) == gf_add(gf_mult(a,c), gf_mult(b,c))); ) }
uint8_t gf_sub(uint8_t a, uint8_t b) { return gf_add(a, b); }
GFn_el_t & GFn_el_t::operator += (unsigned int _a) { comp[0] = gf_add(prime, comp[0], _a%prime); return *this; }
GFn_el_t & GFn_el_t::operator += (int _a) { comp[0] = gf_add(prime, comp[0], gf_int(prime, _a)); return *this; }
void ec_negate (ec_point *p) /* sets p := -p */ { gf_add (p->y, p->x, p->y); } /* ec_negate */
void test_add_associates() { suite("addition associates"); SOME3( test(gf_add(gf_add(a,b), c) == gf_add(a, gf_add(b,c))); ) }
void test_add_commutes() { suite("addition commutes"); ALL2( test(gf_add(a,b) == gf_add(b,a)); ) }