/* Multiply P by e in group G2 */ void PAIR_G2mul(ECP2 *P,BIG e) { #ifdef USE_GS_G2 /* Well I didn't patent it :) */ int i,np,nn; ECP2 Q[4]; FP2 X; BIG x,y; BIG u[4]; BIG_rcopy(x,CURVE_Fra); BIG_rcopy(y,CURVE_Frb); FP2_from_BIGs(&X,x,y); BIG_rcopy(y,CURVE_Order); gs(u,e); ECP2_affine(P); ECP2_copy(&Q[0],P); for (i=1; i<4; i++) { ECP2_copy(&Q[i],&Q[i-1]); ECP2_frob(&Q[i],&X); } for (i=0; i<4; i++) { np=BIG_nbits(u[i]); BIG_modneg(x,u[i],y); nn=BIG_nbits(x); if (nn<np) { BIG_copy(u[i],x); ECP2_neg(&Q[i]); } } ECP2_mul4(P,Q,u); #else ECP2_mul(P,e); #endif }
/* Multiply P by e in group G1 */ void PAIR_G1mul(ECP *P,BIG e) { #ifdef USE_GLV /* Note this method is patented */ int i,np,nn; ECP Q; BIG cru,t,q; BIG u[2]; BIG_rcopy(q,CURVE_Order); glv(u,e); ECP_affine(P); ECP_copy(&Q,P); BIG_rcopy(cru,CURVE_Cru); FP_nres(cru); FP_mul(Q.x,Q.x,cru); /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */ np=BIG_nbits(u[0]); BIG_modneg(t,u[0],q); nn=BIG_nbits(t); if (nn<np) { BIG_copy(u[0],t); ECP_neg(P); } np=BIG_nbits(u[1]); BIG_modneg(t,u[1],q); nn=BIG_nbits(t); if (nn<np) { BIG_copy(u[1],t); ECP_neg(&Q); } ECP_mul2(P,&Q,u[0],u[1]); #else ECP_mul(P,e); #endif }
/* f=f^e */ void PAIR_GTpow(FP12 *f,BIG e) { #ifdef USE_GS_GT /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see fp4.c */ int i,np,nn; FP12 g[4]; FP2 X; BIG t,q,x,y; BIG u[4]; BIG_rcopy(x,CURVE_Fra); BIG_rcopy(y,CURVE_Frb); FP2_from_BIGs(&X,x,y); BIG_rcopy(q,CURVE_Order); gs(u,e); FP12_copy(&g[0],f); for (i=1; i<4; i++) { FP12_copy(&g[i],&g[i-1]); FP12_frob(&g[i],&X); } for (i=0; i<4; i++) { np=BIG_nbits(u[i]); BIG_modneg(t,u[i],q); nn=BIG_nbits(t); if (nn<np) { BIG_copy(u[i],t); FP12_conj(&g[i],&g[i]); } } FP12_pow4(f,g,u); #else FP12_pow(f,f,e); #endif }
/* output a */ void BIG_output(BIG a) { BIG b; int i,len; len=BIG_nbits(a); if (len%4==0) len/=4; else {len/=4; len++;} if (len<MODBYTES*2) len=MODBYTES*2; for (i=len-1;i>=0;i--) { BIG_copy(b,a); BIG_shr(b,i*4); printf("%01x",(unsigned int)(b[0]&15)); } }
/* 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); }
/* Optimal R-ate pairing r=e(P,Q) */ void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q) { FP2 X; BIG x,n,Qx,Qy; int i,nb; ECP2 A; FP12 lv; #if CHOICE<BLS_CURVES ECP2 KA; #endif BIG_rcopy(Qx,CURVE_Fra); BIG_rcopy(Qy,CURVE_Frb); FP2_from_BIGs(&X,Qx,Qy); BIG_rcopy(x,CURVE_Bnx); #if CHOICE<BLS_CURVES BIG_pmul(n,x,6); BIG_dec(n,2); #else BIG_copy(n,x); #endif BIG_norm(n); ECP2_affine(P); ECP_affine(Q); BIG_copy(Qx,Q->x); BIG_copy(Qy,Q->y); ECP2_copy(&A,P); FP12_one(r); nb=BIG_nbits(n); /* Main Miller Loop */ for (i=nb-2; i>=1; i--) { PAIR_line(&lv,&A,&A,Qx,Qy); FP12_smul(r,&lv); if (BIG_bit(n,i)) { PAIR_line(&lv,&A,P,Qx,Qy); FP12_smul(r,&lv); } FP12_sqr(r,r); } PAIR_line(&lv,&A,&A,Qx,Qy); FP12_smul(r,&lv); if (BIG_parity(n)) { PAIR_line(&lv,&A,P,Qx,Qy); FP12_smul(r,&lv); } /* R-ate fixup required for BN curves */ #if CHOICE<BLS_CURVES ECP2_copy(&KA,P); ECP2_frob(&KA,&X); ECP2_neg(&A); FP12_conj(r,r); PAIR_line(&lv,&A,&KA,Qx,Qy); FP12_smul(r,&lv); ECP2_frob(&KA,&X); ECP2_neg(&KA); PAIR_line(&lv,&A,&KA,Qx,Qy); FP12_smul(r,&lv); #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); }
/* Optimal R-ate pairing r=e(P,Q) */ void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q) { FP2 X; BIG x,n,Qx,Qy; int i,nb; ECP2 A,KA; FP12 lv; BIG_rcopy(Qx,CURVE_Fra); BIG_rcopy(Qy,CURVE_Frb); FP2_from_BIGs(&X,Qx,Qy); BIG_rcopy(x,CURVE_Bnx); BIG_pmul(n,x,6); BIG_dec(n,2); BIG_norm(n); ECP2_affine(P); ECP_affine(Q); BIG_copy(Qx,Q->x); BIG_copy(Qy,Q->y); ECP2_copy(&A,P); FP12_one(r); nb=BIG_nbits(n); /* Main Miller Loop */ for (i=nb-2;i>=1;i--) { PAIR_line(&lv,&A,&A,Qx,Qy); FP12_smul(r,&lv); if (BIG_bit(n,i)) { PAIR_line(&lv,&A,P,Qx,Qy); FP12_smul(r,&lv); } FP12_sqr(r,r); } PAIR_line(&lv,&A,&A,Qx,Qy); FP12_smul(r,&lv); /* R-ate fixup */ ECP2_copy(&KA,P); ECP2_frob(&KA,&X); ECP2_neg(&A); FP12_conj(r,r); PAIR_line(&lv,&A,&KA,Qx,Qy); FP12_smul(r,&lv); ECP2_frob(&KA,&X); ECP2_neg(&KA); PAIR_line(&lv,&A,&KA,Qx,Qy); FP12_smul(r,&lv); }