/* SU= 16 */ void FP12_copy(FP12 *w,FP12 *x) { if (x==w) return; FP4_copy(&(w->a),&(x->a)); FP4_copy(&(w->b),&(x->b)); FP4_copy(&(w->c),&(x->c)); }
/* XTR xtr_d function */ void FP4_xtr_D(FP4 *r,FP4 *x) { FP4 w; FP4_copy(r,x); FP4_conj(&w,r); FP4_add(&w,&w,&w); FP4_sqr(r,r); FP4_sub(r,r,&w); FP4_reduce(r); /* reduce here as multiple calls trigger automatic reductions */ }
/* r=x^n using XTR method on traces of FP12s */ void FP4_xtr_pow(FP4 *r,FP4 *x,BIG n) { int i,par,nb; BIG v; FP2 w; FP4 t,a,b,c; BIG_zero(v); BIG_inc(v,3); FP2_from_BIG(&w,v); FP4_from_FP2(&a,&w); FP4_copy(&b,x); FP4_xtr_D(&c,x); BIG_norm(n); par=BIG_parity(n); BIG_copy(v,n); BIG_shr(v,1); if (par==0) {BIG_dec(v,1); BIG_norm(v);} nb=BIG_nbits(v); for (i=nb-1;i>=0;i--) { if (!BIG_bit(v,i)) { FP4_copy(&t,&b); FP4_conj(x,x); FP4_conj(&c,&c); FP4_xtr_A(&b,&a,&b,x,&c); FP4_conj(x,x); FP4_xtr_D(&c,&t); FP4_xtr_D(&a,&a); } else { FP4_conj(&t,&a); FP4_xtr_D(&a,&b); FP4_xtr_A(&b,&c,&b,x,&t); FP4_xtr_D(&c,&c); } } if (par==0) FP4_copy(r,&c); else FP4_copy(r,&b); FP4_reduce(r); }
/* 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); }
/* XTR xtr_a function */ void FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z) { FP4 t1,t2; FP4_copy(r,x); FP4_sub(&t1,w,y); FP4_pmul(&t1,&t1,&(r->a)); FP4_add(&t2,w,y); FP4_pmul(&t2,&t2,&(r->b)); FP4_times_i(&t2); FP4_add(r,&t1,&t2); FP4_add(r,r,z); FP4_norm(r); }
/* SU= 600 */ void FP12_usqr(FP12 *w,FP12 *x) { FP4 A,B,C,D; FP4_copy(&A,&(x->a)); FP4_sqr(&(w->a),&(x->a)); FP4_add(&D,&(w->a),&(w->a)); FP4_add(&(w->a),&D,&(w->a)); #if CHUNK<64 FP4_norm(&(w->a)); #endif FP4_nconj(&A,&A); FP4_add(&A,&A,&A); FP4_add(&(w->a),&(w->a),&A); FP4_sqr(&B,&(x->c)); FP4_times_i(&B); FP4_add(&D,&B,&B); FP4_add(&B,&B,&D); #if CHUNK<64 FP4_norm(&B); #endif FP4_sqr(&C,&(x->b)); FP4_add(&D,&C,&C); FP4_add(&C,&C,&D); #if CHUNK<64 FP4_norm(&C); #endif FP4_conj(&(w->b),&(x->b)); FP4_add(&(w->b),&(w->b),&(w->b)); FP4_nconj(&(w->c),&(x->c)); FP4_add(&(w->c),&(w->c),&(w->c)); FP4_add(&(w->b),&B,&(w->b)); FP4_add(&(w->c),&C,&(w->c)); FP12_reduce(w); /* reduce here as in pow function repeated squarings would trigger multiple reductions */ }
/* SU= 240 */ void FP4_pow(FP4 *r,FP4* a,BIG b) { FP4 w; BIG z,zilch; int bt; BIG_zero(zilch); BIG_norm(b); BIG_copy(z,b); FP4_copy(&w,a); FP4_one(r); while(1) { bt=BIG_parity(z); BIG_shr(z,1); if (bt) FP4_mul(r,r,&w); if (BIG_comp(z,zilch)==0) break; FP4_sqr(&w,&w); } FP4_reduce(r); }
/* SU= 600 */ void FP12_sqr(FP12 *w,FP12 *x) { /* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */ FP4 A,B,C,D; FP4_sqr(&A,&(x->a)); FP4_mul(&B,&(x->b),&(x->c)); FP4_add(&B,&B,&B); FP4_sqr(&C,&(x->c)); FP4_mul(&D,&(x->a),&(x->b)); FP4_add(&D,&D,&D); FP4_add(&(w->c),&(x->a),&(x->c)); FP4_add(&(w->c),&(x->b),&(w->c)); FP4_sqr(&(w->c),&(w->c)); FP4_copy(&(w->a),&A); FP4_add(&A,&A,&B); #if CHUNK<64 FP4_norm(&A); #endif FP4_add(&A,&A,&C); FP4_add(&A,&A,&D); #if CHUNK<64 FP4_norm(&A); #endif FP4_neg(&A,&A); FP4_times_i(&B); FP4_times_i(&C); FP4_add(&(w->a),&(w->a),&B); FP4_add(&(w->b),&C,&D); FP4_add(&(w->c),&(w->c),&A); FP12_norm(w); }
/* SU= 16 */ void FP12_from_FP4s(FP12 *w,FP4 *a,FP4 *b,FP4 *c) { FP4_copy(&(w->a),a); FP4_copy(&(w->b),b); FP4_copy(&(w->c),c); }
/* SU= 8 */ void FP12_from_FP4(FP12 *w,FP4 *a) { FP4_copy(&(w->a),a); FP4_zero(&(w->b)); FP4_zero(&(w->c)); }
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ void FP4_xtr_pow2(FP4 *r,FP4 *ck,FP4 *cl,FP4 *ckml,FP4 *ckm2l,BIG a,BIG b) { int i,f2,nb; BIG d,e,w; FP4 t,cu,cv,cumv,cum2v; BIG_norm(a); BIG_norm(b); BIG_copy(e,a); BIG_copy(d,b); FP4_copy(&cu,ck); FP4_copy(&cv,cl); FP4_copy(&cumv,ckml); FP4_copy(&cum2v,ckm2l); f2=0; while (BIG_parity(d)==0 && BIG_parity(e)==0) { BIG_shr(d,1); BIG_shr(e,1); f2++; } while (BIG_comp(d,e)!=0) { if (BIG_comp(d,e)>0) { BIG_imul(w,e,4); BIG_norm(w); if (BIG_comp(d,w)<=0) { BIG_copy(w,d); BIG_copy(d,e); BIG_sub(e,w,e); BIG_norm(e); FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v); FP4_conj(&cum2v,&cumv); FP4_copy(&cumv,&cv); FP4_copy(&cv,&cu); FP4_copy(&cu,&t); } else if (BIG_parity(d)==0) { BIG_shr(d,1); FP4_conj(r,&cum2v); FP4_xtr_A(&t,&cu,&cumv,&cv,r); FP4_xtr_D(&cum2v,&cumv); FP4_copy(&cumv,&t); FP4_xtr_D(&cu,&cu); } else if (BIG_parity(e)==1) { BIG_sub(d,d,e); BIG_norm(d); BIG_shr(d,1); FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v); FP4_xtr_D(&cu,&cu); FP4_xtr_D(&cum2v,&cv); FP4_conj(&cum2v,&cum2v); FP4_copy(&cv,&t); } else { BIG_copy(w,d); BIG_copy(d,e); BIG_shr(d,1); BIG_copy(e,w); FP4_xtr_D(&t,&cumv); FP4_conj(&cumv,&cum2v); FP4_conj(&cum2v,&t); FP4_xtr_D(&t,&cv); FP4_copy(&cv,&cu); FP4_copy(&cu,&t); } } if (BIG_comp(d,e)<0) { BIG_imul(w,d,4); BIG_norm(w); if (BIG_comp(e,w)<=0) { BIG_sub(e,e,d); BIG_norm(e); FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v); FP4_copy(&cum2v,&cumv); FP4_copy(&cumv,&cu); FP4_copy(&cu,&t); } else if (BIG_parity(e)==0) { BIG_copy(w,d); BIG_copy(d,e); BIG_shr(d,1); BIG_copy(e,w); FP4_xtr_D(&t,&cumv); FP4_conj(&cumv,&cum2v); FP4_conj(&cum2v,&t); FP4_xtr_D(&t,&cv); FP4_copy(&cv,&cu); FP4_copy(&cu,&t); } else if (BIG_parity(d)==1) { BIG_copy(w,e); BIG_copy(e,d); BIG_sub(w,w,d); BIG_norm(w); BIG_copy(d,w); BIG_shr(d,1); FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v); FP4_conj(&cumv,&cumv); FP4_xtr_D(&cum2v,&cu); FP4_conj(&cum2v,&cum2v); FP4_xtr_D(&cu,&cv); FP4_copy(&cv,&t); } else { BIG_shr(d,1); FP4_conj(r,&cum2v); FP4_xtr_A(&t,&cu,&cumv,&cv,r); FP4_xtr_D(&cum2v,&cumv); FP4_copy(&cumv,&t); FP4_xtr_D(&cu,&cu); } } } FP4_xtr_A(r,&cu,&cv,&cumv,&cum2v); for (i=0;i<f2;i++) FP4_xtr_D(r,r); FP4_xtr_pow(r,r,d); }