/* 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 */ }
void FP12_pow(FP12 *r,FP12 *a,BIG b) { FP12 w; BIG z,zilch; int bt; BIG_zero(zilch); BIG_norm(b); BIG_copy(z,b); FP12_copy(&w,a); FP12_one(r); while(1) { bt=BIG_parity(z); BIG_shr(z,1); if (bt) FP12_mul(r,&w); if (BIG_comp(z,zilch)==0) break; FP12_usqr(&w,&w); } FP12_reduce(r); }
/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ void PAIR_fexp(FP12 *r) { FP2 X; BIG x,a,b; FP12 t0,y0,y1,y2,y3; BIG_rcopy(x,CURVE_Bnx); BIG_rcopy(a,CURVE_Fra); BIG_rcopy(b,CURVE_Frb); FP2_from_BIGs(&X,a,b); /* Easy part of final exp */ FP12_inv(&t0,r); FP12_conj(r,r); FP12_mul(r,&t0); FP12_copy(&t0,r); FP12_frob(r,&X); FP12_frob(r,&X); FP12_mul(r,&t0); /* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */ #if CHOICE<BLS_CURVES FP12_pow(&t0,r,x); // t0=f^-u FP12_usqr(&y3,&t0); // y3=t0^2 FP12_copy(&y0,&t0); FP12_mul(&y0,&y3); // y0=t0*y3 FP12_copy(&y2,&y3); FP12_frob(&y2,&X); // y2=y3^p FP12_mul(&y2,&y3); //y2=y2*y3 FP12_usqr(&y2,&y2); //y2=y2^2 FP12_mul(&y2,&y3); // y2=y2*y3 FP12_pow(&t0,&y0,x); //t0=y0^-u FP12_conj(&y0,r); //y0=~r FP12_copy(&y1,&t0); FP12_frob(&y1,&X); FP12_frob(&y1,&X); //y1=t0^p^2 FP12_mul(&y1,&y0); // y1=y0*y1 FP12_conj(&t0,&t0); // t0=~t0 FP12_copy(&y3,&t0); FP12_frob(&y3,&X); //y3=t0^p FP12_mul(&y3,&t0); // y3=t0*y3 FP12_usqr(&t0,&t0); // t0=t0^2 FP12_mul(&y1,&t0); // y1=t0*y1 FP12_pow(&t0,&y3,x); // t0=y3^-u FP12_usqr(&t0,&t0); //t0=t0^2 FP12_conj(&t0,&t0); //t0=~t0 FP12_mul(&y3,&t0); // y3=t0*y3 FP12_frob(r,&X); FP12_copy(&y0,r); FP12_frob(r,&X); FP12_mul(&y0,r); FP12_frob(r,&X); FP12_mul(&y0,r); FP12_usqr(r,&y3); //r=y3^2 FP12_mul(r,&y2); //r=y2*r FP12_copy(&y3,r); FP12_mul(&y3,&y0); // y3=r*y0 FP12_mul(r,&y1); // r=r*y1 FP12_usqr(r,r); // r=r^2 FP12_mul(r,&y3); // r=r*y3 FP12_reduce(r); #else // Ghamman & Fouotsa Method FP12_usqr(&y0,r); FP12_pow(&y1,&y0,x); BIG_fshr(x,1); FP12_pow(&y2,&y1,x); BIG_fshl(x,1); // x must be even FP12_conj(&y3,r); FP12_mul(&y1,&y3); FP12_conj(&y1,&y1); FP12_mul(&y1,&y2); FP12_pow(&y2,&y1,x); FP12_pow(&y3,&y2,x); FP12_conj(&y1,&y1); FP12_mul(&y3,&y1); FP12_conj(&y1,&y1); FP12_frob(&y1,&X); FP12_frob(&y1,&X); FP12_frob(&y1,&X); FP12_frob(&y2,&X); FP12_frob(&y2,&X); FP12_mul(&y1,&y2); FP12_pow(&y2,&y3,x); FP12_mul(&y2,&y0); FP12_mul(&y2,r); FP12_mul(&y1,&y2); FP12_copy(&y2,&y3); FP12_frob(&y2,&X); FP12_mul(&y1,&y2); FP12_copy(r,&y1); FP12_reduce(r); // Aranha et al method as described by Ghamman & Fouotsa /* FP12_usqr(&y0,r); // t0=f^2 FP12_conj(&y3,&y0); // t0=f^-2 FP12_pow(&t0,r,x); // t5=f^u FP12_usqr(&y1,&t0); // t1=t5^2 FP12_mul(&y3,&t0); // t3=t0*t5 FP12_pow(&y0,&y3,x); FP12_pow(&y2,&y0,x); FP12_pow(&y4,&y2,x); FP12_mul(&y4,&y1); FP12_pow(&y1,&y4,x); FP12_conj(&y3,&y3); FP12_mul(&y1,&y3); FP12_mul(&y1,r); FP12_conj(&y3,r); FP12_mul(&y0,r); FP12_frob(&y0,&X); FP12_frob(&y0,&X); FP12_frob(&y0,&X); FP12_mul(&y4,&y3); FP12_frob(&y4,&X); FP12_mul(&t0,&y2); FP12_frob(&t0,&X); FP12_frob(&t0,&X); FP12_mul(&t0,&y0); FP12_mul(&t0,&y4); FP12_mul(&t0,&y1); FP12_copy(r,&t0); FP12_reduce(r);*/ //----------------------------------- /* FP12_copy(&y0,r); // y0=r; FP12_copy(&y1,r); // y1=r; FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_conj(&y3,&t0); FP12_mul(&y1,&y3); // y1*=inverse(t0); FP12_frob(&t0,&X); FP12_frob(&t0,&X); // t0=Frobenius(t0,X,2); FP12_mul(&y1,&t0); // y1*=t0; FP12_pow(r,r,x); // r=pow(r,x); FP12_conj(&y3,r); FP12_mul(&y1,&y3); // y1*=inverse(r); FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_mul(&y0,&t0); // y0*=t0; FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_mul(&y1,&t0); // y1*=t0; FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_conj(&y3,&t0); FP12_mul(&y0,&y3); // y0*=inverse(t0); FP12_pow(r,r,x); // r=pow(r,x); FP12_mul(&y0,r); // y0*=r; FP12_copy(&t0,r); FP12_frob(&t0,&X); FP12_frob(&t0,&X); // t0=Frobenius(r,X,2); FP12_conj(&y3,&t0); FP12_mul(&y0,&y3); // y0*=inverse(t0); FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_mul(&y1,&t0); // y1*=t0; FP12_pow(r,r,x); // r=pow(r,x); // r^x3 FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_conj(&y3,&t0); FP12_mul(&y0,&y3); // y0*=inverse(t0); FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_mul(&y1,&t0); // y1*=t0; FP12_pow(r,r,x); // r=pow(r,x); // r^x4 FP12_conj(&y3,r); FP12_mul(&y0,&y3); // y0*=inverse(r); FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_mul(&y1,&t0); //y1*=t0; FP12_pow(r,r,x); // r=pow(r,x); // r^x5 FP12_mul(&y1,r); // y1*=r; FP12_usqr(&y0,&y0); // r=y0*y0*y1; FP12_mul(&y0,&y1); FP12_copy(r,&y0); FP12_reduce(r); */ #endif }
void FP12_pow4(FP12 *p,FP12 *q,BIG u[4]) { int i,j,a[4],nb,m; FP12 g[8],c,s[2]; BIG t[4],mt; sign8 w[NLEN*BASEBITS+1]; for (i=0;i<4;i++) BIG_copy(t[i],u[i]); FP12_copy(&g[0],&q[0]); FP12_conj(&s[0],&q[1]); FP12_mul(&g[0],&s[0]); /* P/Q */ FP12_copy(&g[1],&g[0]); FP12_copy(&g[2],&g[0]); FP12_copy(&g[3],&g[0]); FP12_copy(&g[4],&q[0]); FP12_mul(&g[4],&q[1]); /* P*Q */ FP12_copy(&g[5],&g[4]); FP12_copy(&g[6],&g[4]); FP12_copy(&g[7],&g[4]); FP12_copy(&s[1],&q[2]); FP12_conj(&s[0],&q[3]); FP12_mul(&s[1],&s[0]); /* R/S */ FP12_conj(&s[0],&s[1]); FP12_mul(&g[1],&s[0]); FP12_mul(&g[2],&s[1]); FP12_mul(&g[5],&s[0]); FP12_mul(&g[6],&s[1]); FP12_copy(&s[1],&q[2]); FP12_mul(&s[1],&q[3]); /* R*S */ FP12_conj(&s[0],&s[1]); FP12_mul(&g[0],&s[0]); FP12_mul(&g[3],&s[1]); FP12_mul(&g[4],&s[0]); FP12_mul(&g[7],&s[1]); /* if power is even add 1 to power, and add q to correction */ FP12_one(&c); BIG_zero(mt); for (i=0;i<4;i++) { if (BIG_parity(t[i])==0) { BIG_inc(t[i],1); BIG_norm(t[i]); FP12_mul(&c,&q[i]); } BIG_add(mt,mt,t[i]); BIG_norm(mt); } FP12_conj(&c,&c); nb=1+BIG_nbits(mt); /* convert exponent to signed 1-bit window */ for (j=0;j<nb;j++) { for (i=0;i<4;i++) { a[i]=BIG_lastbits(t[i],2)-2; BIG_dec(t[i],a[i]); BIG_norm(t[i]); BIG_fshr(t[i],1); } w[j]=8*a[0]+4*a[1]+2*a[2]+a[3]; } w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2); FP12_copy(p,&g[(w[nb]-1)/2]); for (i=nb-1;i>=0;i--) { m=w[i]>>7; j=(w[i]^m)-m; /* j=abs(w[i]) */ j=(j-1)/2; FP12_copy(&s[0],&g[j]); FP12_conj(&s[1],&g[j]); FP12_usqr(p,p); FP12_mul(p,&s[m&1]); } FP12_mul(p,&c); /* apply correction */ FP12_reduce(p); }
/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ void PAIR_fexp(FP12 *r) { FP2 X; BIG x,a,b; FP12 t0,y0,y1,y2,y3; BIG_rcopy(x,CURVE_Bnx); BIG_rcopy(a,CURVE_Fra); BIG_rcopy(b,CURVE_Frb); FP2_from_BIGs(&X,a,b); /* Easy part of final exp */ FP12_inv(&t0,r); FP12_conj(r,r); FP12_mul(r,&t0); FP12_copy(&t0,r); FP12_frob(r,&X); FP12_frob(r,&X); FP12_mul(r,&t0); /* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */ FP12_pow(&t0,r,x); // t0=f^-u FP12_usqr(&y3,&t0); // y3=t0^2 FP12_copy(&y0,&t0); FP12_mul(&y0,&y3); // y0=t0*y3 FP12_copy(&y2,&y3); FP12_frob(&y2,&X); // y2=y3^p FP12_mul(&y2,&y3); //y2=y2*y3 FP12_usqr(&y2,&y2); //y2=y2^2 FP12_mul(&y2,&y3); // y2=y2*y3 FP12_pow(&t0,&y0,x); //t0=y0^-u FP12_conj(&y0,r); //y0=~r FP12_copy(&y1,&t0); FP12_frob(&y1,&X); FP12_frob(&y1,&X); //y1=t0^p^2 FP12_mul(&y1,&y0); // y1=y0*y1 FP12_conj(&t0,&t0); // t0=~t0 FP12_copy(&y3,&t0); FP12_frob(&y3,&X); //y3=t0^p FP12_mul(&y3,&t0); // y3=t0*y3 FP12_usqr(&t0,&t0); // t0=t0^2 FP12_mul(&y1,&t0); // y1=t0*y1 FP12_pow(&t0,&y3,x); // t0=y3^-u FP12_usqr(&t0,&t0); //t0=t0^2 FP12_conj(&t0,&t0); //t0=~t0 FP12_mul(&y3,&t0); // y3=t0*y3 FP12_frob(r,&X); FP12_copy(&y0,r); FP12_frob(r,&X); FP12_mul(&y0,r); FP12_frob(r,&X); FP12_mul(&y0,r); FP12_usqr(r,&y3); //r=y3^2 FP12_mul(r,&y2); //r=y2*r FP12_copy(&y3,r); FP12_mul(&y3,&y0); // y3=r*y0 FP12_mul(r,&y1); // r=r*y1 FP12_usqr(r,r); // r=r^2 FP12_mul(r,&y3); // r=r*y3 FP12_reduce(r); /* our way */ /* // FP12 lv,x0,x1,x2,x3,x4,x5; FP12_copy(&lv,r); FP12_frob(&lv,&X); FP12_copy(&x0,&lv); FP12_frob(&x0,&X); FP12_mul(&lv,r); FP12_mul(&x0,&lv); FP12_frob(&x0,&X); FP12_conj(&x1,r); FP12_pow(&x4,r,x); FP12_copy(&x3,&x4); FP12_frob(&x3,&X); FP12_pow(&x2,&x4,x); FP12_conj(&x5,&x2); FP12_pow(&lv,&x2,x); FP12_frob(&x2,&X); FP12_conj(r,&x2); FP12_mul(&x4,r); FP12_frob(&x2,&X); FP12_copy(r,&lv); FP12_frob(r,&X); FP12_mul(&lv,r); FP12_usqr(&lv,&lv); FP12_mul(&lv,&x4); FP12_mul(&lv,&x5); FP12_copy(r,&x3); FP12_mul(r,&x5); FP12_mul(r,&lv); FP12_mul(&lv,&x2); FP12_usqr(r,r); FP12_mul(r,&lv); FP12_usqr(r,r); FP12_copy(&lv,r); FP12_mul(&lv,&x1); FP12_mul(r,&x0); FP12_usqr(&lv,&lv); FP12_mul(r,&lv); FP12_reduce(r); */ }