/* Line function */ static void PAIR_line(FP12 *v,ECP2 *A,ECP2 *B,BIG Qx,BIG Qy) { ECP2 P; FP2 Z3,X,Y,ZZ,T,NY; FP4 a,b,c; int D; ECP2_copy(&P,A); if (A==B) D=ECP2_dbl(A); // check these return numbers... else D=ECP2_add(A,B); if (D<0) { /* Infinity */ FP12_one(v); return; } FP2_copy(&Z3,&(A->z)); FP4_zero(&c); FP2_sqr(&ZZ,&(P.z)); /* ZZ=Z^2 */ if (D==0) { /* addition */ ECP2_get(&X,&Y,B); FP2_mul(&T,&(P.z),&Y); /* T=Z*Y2 */ FP2_mul(&ZZ,&ZZ,&T); FP2_neg(&NY,&(P.y)); FP2_add(&ZZ,&ZZ,&NY); /* ZZ=Z^3*Y2-Y (slope numerator) */ FP2_pmul(&Z3,&Z3,Qy); /* Z3*Qy */ FP2_mul(&T,&T,&(P.x)); FP2_mul(&X,&X,&NY); FP2_add(&T,&T,&X); /* Z*Y2*X-X2*Y */ FP4_from_FP2s(&a,&Z3,&T); /* a=[Z3*Qy,Z*Y2*X-X2*Y] */ FP2_neg(&ZZ,&ZZ); FP2_pmul(&ZZ,&ZZ,Qx); FP4_from_FP2(&b,&ZZ); /* b=-slope*Qx */ } else { /* doubling */ FP2_sqr(&T,&(P.x)); FP2_imul(&T,&T,3); /* T=3X^2 (slope numerator) */ FP2_sqr(&Y,&(P.y)); FP2_add(&Y,&Y,&Y); /* Y=2Y^2 */ FP2_mul(&Z3,&Z3,&ZZ); /* Z3=Z3*ZZ */ FP2_pmul(&Z3,&Z3,Qy); /* Z3=Z3*ZZ*Qy */ FP2_mul(&X,&(P.x),&T); FP2_sub(&X,&X,&Y); /* X=X*slope-2Y^2 */ FP4_from_FP2s(&a,&Z3,&X); /* a=[Z3*ZZ*Qy , X*slope-2Y^2] */ FP2_neg(&T,&T); FP2_mul(&ZZ,&ZZ,&T); FP2_pmul(&ZZ,&ZZ,Qx); FP4_from_FP2(&b,&ZZ); /* b=-slope*ZZ*Qx */ } FP12_from_FP4s(v,&a,&b,&c); }
/* SU= 160 */ void FP4_neg(FP4 *w,FP4 *x) { /* Just one field neg */ FP2 m,t; FP2_add(&m,&(x->a),&(x->b)); FP2_neg(&m,&m); FP2_norm(&m); FP2_add(&t,&m,&(x->b)); FP2_add(&(w->b),&m,&(x->a)); FP2_copy(&(w->a),&t); }
int FP6_add(const PAIRING_GROUP *group, FP6 *r, const FP6 *a, const FP6 *b) { if (!FP2_add(group, &r->f[0], &a->f[0], &b->f[0])) { return 0; } if (!FP2_add(group, &r->f[1], &a->f[1], &b->f[1])) { return 0; } if (!FP2_add(group, &r->f[2], &a->f[2], &b->f[2])) { return 0; } return 1; }
/* SU= 312 */ void FP4_mul(FP4 *w,FP4 *x,FP4 *y) { FP2 t1,t2,t3,t4; FP2_mul(&t1,&(x->a),&(y->a)); /* norms x */ FP2_mul(&t2,&(x->b),&(y->b)); /* and y */ FP2_add(&t3,&(y->b),&(y->a)); FP2_add(&t4,&(x->b),&(x->a)); FP2_mul(&t4,&t4,&t3); /* (xa+xb)(ya+yb) */ FP2_sub(&t4,&t4,&t1); #if CHUNK<64 FP2_norm(&t4); #endif FP2_sub(&(w->b),&t4,&t2); FP2_mul_ip(&t2); FP2_add(&(w->a),&t2,&t1); FP4_norm(w); }
/* SU= 232 */ void FP4_sqr(FP4 *w,FP4 *x) { FP2 t1,t2,t3; FP2_mul(&t3,&(x->a),&(x->b)); /* norms x */ FP2_copy(&t2,&(x->b)); FP2_add(&t1,&(x->a),&(x->b)); FP2_mul_ip(&t2); FP2_add(&t2,&(x->a),&t2); FP2_mul(&(w->a),&t1,&t2); FP2_copy(&t2,&t3); FP2_mul_ip(&t2); FP2_add(&t2,&t2,&t3); FP2_neg(&t2,&t2); FP2_add(&(w->a),&(w->a),&t2); /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */ FP2_add(&(w->b),&t3,&t3); /* b=2ab */ FP4_norm(w); }
/* SU= 200 */ void FP4_times_i(FP4 *w) { BIG z; FP2 s,t; #if CHUNK<64 FP4_norm(w); #endif FP2_copy(&t,&(w->b)); FP2_copy(&s,&t); BIG_copy(z,s.a); FP_neg(s.a,s.b); BIG_copy(s.b,z); FP2_add(&t,&t,&s); #if CHUNK<64 FP2_norm(&t); #endif FP2_copy(&(w->b),&(w->a)); FP2_copy(&(w->a),&t); }
/* catering for special case that arises from special form of ATE pairing line function */ void FP12_smul(FP12 *w,FP12 *y) { FP4 z0,z2,z3,t0,t1; FP4_copy(&z3,&(w->b)); FP4_mul(&z0,&(w->a),&(y->a)); FP4_pmul(&z2,&(w->b),&(y->b).a); FP4_add(&(w->b),&(w->a),&(w->b)); FP4_copy(&t1,&(y->a)); FP2_add(&t1.a,&t1.a,&(y->b).a); FP4_mul(&(w->b),&(w->b),&t1); FP4_add(&z3,&z3,&(w->c)); FP4_pmul(&z3,&z3,&(y->b).a); FP4_neg(&t0,&z0); FP4_neg(&t1,&z2); FP4_add(&(w->b),&(w->b),&t0); // z1=z1-z0 #if CHUNK<64 FP4_norm(&(w->b)); #endif FP4_add(&(w->b),&(w->b),&t1); // z1=z1-z2 FP4_add(&z3,&z3,&t1); // z3=z3-z2 FP4_add(&z2,&z2,&t0); // z2=z2-z0 FP4_add(&t0,&(w->a),&(w->c)); FP4_mul(&t0,&(y->a),&t0); FP4_add(&(w->c),&z2,&t0); FP4_times_i(&z3); FP4_add(&(w->a),&z0,&z3); FP12_norm(w); }
int FP6_inv(const PAIRING_GROUP *group, FP6 *r, const FP6 *a, BN_CTX *ctx) { FP2 v0, v1, v2, t0; int ret; FP2_init(&v0); FP2_init(&v1); FP2_init(&v2); FP2_init(&t0); /* v0 = a_0^2 - E * a_1 * a_2. */ if (!FP2_sqr(group, &t0, &a->f[0], ctx)) { goto err; } if (!FP2_mul(group, &v0, &a->f[1], &a->f[2], ctx)) { goto err; } if (!FP2_mul_nor(group, &v2, &v0, ctx)) { goto err; } if (!FP2_sub(group, &v0, &t0, &v2)) { goto err; } /* v1 = E * a_2^2 - a_0 * a_1. */ if (!FP2_sqr(group, &t0, &a->f[2], ctx)) { goto err; } if (!FP2_mul_nor(group, &v2, &t0, ctx)) { goto err; } if (!FP2_mul(group, &v1, &a->f[0], &a->f[1], ctx)) { goto err; } if (!FP2_sub(group, &v1, &v2, &v1)) { goto err; } /* v2 = a_1^2 - a_0 * a_2. */ if (!FP2_sqr(group, &t0, &a->f[1], ctx)) { goto err; } if (!FP2_mul(group, &v2, &a->f[0], &a->f[2], ctx)) { goto err; } if (!FP2_sub(group, &v2, &t0, &v2)) { goto err; } if (!FP2_mul(group, &t0, &a->f[1], &v2, ctx)) { goto err; } if (!FP2_mul_nor(group, &r->f[1], &t0, ctx)) { goto err; } if (!FP2_mul(group, &r->f[0], &a->f[0], &v0, ctx)) { goto err; } if (!FP2_mul(group, &t0, &a->f[2], &v1, ctx)) { goto err; } if (!FP2_mul_nor(group, &r->f[2], &t0, ctx)) { goto err; } if (!FP2_add(group, &t0, &r->f[0], &r->f[1])) { goto err; } if (!FP2_add(group, &t0, &t0, &r->f[2])) { goto err; } if (!FP2_inv(group, &t0, &t0, ctx)) { goto err; } if (!FP2_mul(group, &r->f[0], &v0, &t0, ctx)) { goto err; } if (!FP2_mul(group, &r->f[1], &v1, &t0, ctx)) { goto err; } if (!FP2_mul(group, &r->f[2], &v2, &t0, ctx)) { goto err; } ret = 1; err: FP2_free(&v0); FP2_free(&v1); FP2_free(&v2); FP2_free(&t0); return ret; }
int FP6_sqr2(const PAIRING_GROUP *group, FP6 *r, const FP6 *a, BN_CTX *ctx) { FP2 t0, t1, t2, t3, t4; int ret = 0; FP2_init(&t0); FP2_init(&t1); FP2_init(&t2); FP2_init(&t3); FP2_init(&t4); /* t0 = a_0^2 */ if (!FP2_sqr(group, &t0, &a->f[0], ctx)) { goto err; } /* t1 = 2 * a_0 * a_1 */ if (!FP2_mul(group, &t1, &a->f[0], &a->f[1], ctx)) { goto err; } if (!FP2_add(group, &t1, &t1, &t1)) { goto err; } /* t2 = (a_0 - a_1 + a_2)^2 */ if (!FP2_sub(group, &t2, &a->f[0], &a->f[1])) { goto err; } if (!FP2_add(group, &t2, &t2, &a->f[2])) { goto err; } if (!FP2_sqr(group, &t2, &t2, ctx)) { goto err; } /* t3 = 2 * a_1 * a_2 */ if (!FP2_mul(group, &t3, &a->f[1], &a->f[2], ctx)) { goto err; } if (!FP2_add(group, &t3, &t3, &t3)) { goto err; } /* t4 = a_2^2 */ if (!FP2_sqr(group, &t4, &a->f[2], ctx)) { goto err; } /* c_0 = t0 + E * t3 */ if (!FP2_mul_nor(group, &r->f[0], &t3, ctx)) { goto err; } if (!FP2_add(group, &r->f[0], &r->f[0], &t0)) { goto err; } /* c_1 = t1 + E * t4 */ if (!FP2_mul_nor(group, &r->f[1], &t4, ctx)) { goto err; } if (!FP2_add(group, &r->f[1], &r->f[1], &t1)) { goto err; } /* c_2 = t1 + t2 + t3 - t0 - t4 */ if (!FP2_add(group, &r->f[2], &t1, &t2)) { goto err; } if (!FP2_add(group, &r->f[2], &r->f[2], &t3)) { goto err; } if (!FP2_sub(group, &r->f[2], &r->f[2], &t0)) { goto err; } if (!FP2_sub(group, &r->f[2], &r->f[2], &t4)) { goto err; } ret = 1; err: FP2_free(&t0); FP2_free(&t1); FP2_free(&t2); FP2_free(&t3); FP2_free(&t4); return ret; }
int FP6_sqr(const PAIRING_GROUP *group, FP6 *r, const FP6 *a, BN_CTX *ctx) { FP2 t0, t1, t2, t3, t4; int ret = 0; FP2_init(&t0); FP2_init(&t1); FP2_init(&t2); FP2_init(&t3); FP2_init(&t4); /* t0 = a_0^2 */ if (!FP2_sqr(group, &t0, &a->f[0], ctx)) { goto err; } /* t1 = 2 * a_1 * a_2 */ if (!FP2_mul(group, &t1, &a->f[1], &a->f[2], ctx)) { goto err; } if (!FP2_add(group, &t1, &t1, &t1)) { goto err; } /* t2 = a_2^2. */ if (!FP2_sqr(group, &t2, &a->f[2], ctx)) { goto err; } /* c2 = a_0 + a_2. */ if (!FP2_add(group, &r->f[2], &a->f[0], &a->f[2])) { goto err; } /* t3 = (a_0 + a_2 + a_1)^2. */ if (!FP2_add(group, &t3, &r->f[2], &a->f[1])) { goto err; } if (!FP2_sqr(group, &t3, &t3, ctx)) { goto err; } /* c2 = (a_0 + a_2 - a_1)^2. */ if (!FP2_sub(group, &r->f[2], &r->f[2], &a->f[1])) { goto err; } if (!FP2_sqr(group, &r->f[2], &r->f[2], ctx)) { goto err; } /* c2 = (c2 + t3)/2. */ if (!FP2_add(group, &r->f[2], &r->f[2], &t3)) { goto err; } if (BN_is_bit_set(&r->f[2].f[0], 0)) { if (!BN_add(&r->f[2].f[0], &r->f[2].f[0], group->field)) { goto err; } } if (!BN_rshift1(&r->f[2].f[0], &r->f[2].f[0])) { goto err; } if (BN_is_bit_set(&r->f[2].f[1], 0)) { if (!BN_add(&r->f[2].f[1], &r->f[2].f[1], group->field)) { goto err; } } if (!BN_rshift1(&r->f[2].f[1], &r->f[2].f[1])) { goto err; } /* t3 = t3 - c2 - t1. */ if (!FP2_sub(group, &t3, &t3, &r->f[2])) { goto err; } if (!FP2_sub(group, &t3, &t3, &t1)) { goto err; } /* c2 = c2 - t0 - t2. */ if (!FP2_sub(group, &r->f[2], &r->f[2], &t0)) { goto err; } if (!FP2_sub(group, &r->f[2], &r->f[2], &t2)) { goto err; } /* c0 = t0 + t1 * E. */ if (!FP2_mul_nor(group, &t4, &t1, ctx)) { goto err; } if (!FP2_add(group, &r->f[0], &t0, &t4)) { goto err; } /* c1 = t3 + t2 * E. */ if (!FP2_mul_nor(group, &t4, &t2, ctx)) { goto err; } if (!FP2_add(group, &r->f[1], &t3, &t4)) { goto err; } ret = 1; err: FP2_free(&t0); FP2_free(&t1); FP2_free(&t2); FP2_free(&t3); FP2_free(&t4); return ret; }
int FP6_mul_dxs(const PAIRING_GROUP *group, FP6 *r, const FP6 *a, const FP6 *b, BN_CTX *ctx) { FP2 v0, v1, v2, t0, t1, t2; int ret = 0; FP2_init(&v0); FP2_init(&v1); FP2_init(&v2); FP2_init(&t0); FP2_init(&t1); FP2_init(&t2); /* v0 = a_0b_0 */ if (!FP2_mul(group, &v0, &a->f[0], &b->f[0], ctx)) { goto err; } /* v1 = a_1b_1 */ if (!FP2_mul(group, &v1, &a->f[1], &b->f[1], ctx)) { goto err; } /* v2 = a_2b_2 */ /* t2 (c_0) = v0 + E((a_1 + a_2)(b_1 + b_2) - v1 - v2) */ if (!FP2_add(group, &t0, &a->f[1], &a->f[2])) { goto err; } if (!FP2_mul(group, &t0, &t0, &b->f[1], ctx)) { goto err; } if (!FP2_sub(group, &t0, &t0, &v1)) { goto err; } if (!FP2_mul_nor(group, &t2, &t0, ctx)) { goto err; } if (!FP2_add(group, &t2, &t2, &v0)) { goto err; } /* c_1 = (a_0 + a_1)(b_0 + b_1) - v0 - v1 + Ev2 */ if (!FP2_add(group, &t0, &a->f[0], &a->f[1])) { goto err; } if (!FP2_add(group, &t1, &b->f[0], &b->f[1])) { goto err; } if (!FP2_mul(group, &r->f[1], &t0, &t1, ctx)) { goto err; } if (!FP2_sub(group, &r->f[1], &r->f[1], &v0)) { goto err; } if (!FP2_sub(group, &r->f[1], &r->f[1], &v1)) { goto err; } /* c_2 = (a_0 + a_2)(b_0 + b_2) - v0 + v1 - v2 */ if (!FP2_add(group, &t0, &a->f[0], &a->f[2])) { goto err; } if (!FP2_mul(group, &r->f[2], &t0, &b->f[0], ctx)) { goto err; } if (!FP2_sub(group, &r->f[2], &r->f[2], &v0)) { goto err; } if (!FP2_add(group, &r->f[2], &r->f[2], &v1)) { goto err; } /* c_0 = t2 */ FP2_copy(&r->f[0], &t2); ret = 1; err: FP2_free(&t2); FP2_free(&t1); FP2_free(&t0); FP2_free(&v2); FP2_free(&v1); FP2_free(&v0); return ret; }
/* SU= 16 */ void FP4_add(FP4 *w,FP4 *x,FP4 *y) { FP2_add(&(w->a), &(x->a), &(y->a)); FP2_add(&(w->b), &(x->b), &(y->b)); }