/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* AMCL BN Curve pairing functions */ //#define HAS_MAIN #include "pair_FP256BN.h" /* Line function */ static void PAIR_FP256BN_line(FP12_FP256BN *v,ECP2_FP256BN *A,ECP2_FP256BN *B,FP_FP256BN *Qx,FP_FP256BN *Qy) { FP2_FP256BN X1,Y1,T1,T2; FP2_FP256BN XX,YY,ZZ,YZ; FP4_FP256BN a,b,c; if (A==B) { /* doubling */ FP2_FP256BN_copy(&XX,&(A->x)); //FP2 XX=new FP2(A.getx()); //X FP2_FP256BN_copy(&YY,&(A->y)); //FP2 YY=new FP2(A.gety()); //Y FP2_FP256BN_copy(&ZZ,&(A->z)); //FP2 ZZ=new FP2(A.getz()); //Z FP2_FP256BN_copy(&YZ,&YY); //FP2 YZ=new FP2(YY); //Y FP2_FP256BN_mul(&YZ,&YZ,&ZZ); //YZ.mul(ZZ); //YZ FP2_FP256BN_sqr(&XX,&XX); //XX.sqr(); //X^2 FP2_FP256BN_sqr(&YY,&YY); //YY.sqr(); //Y^2 FP2_FP256BN_sqr(&ZZ,&ZZ); //ZZ.sqr(); //Z^2 FP2_FP256BN_imul(&YZ,&YZ,4); //YZ.imul(4); FP2_FP256BN_neg(&YZ,&YZ); //YZ.neg(); FP2_FP256BN_norm(&YZ); //YZ.norm(); //-4YZ FP2_FP256BN_imul(&XX,&XX,6); //6X^2 FP2_FP256BN_pmul(&XX,&XX,Qx); //6X^2.Xs FP2_FP256BN_imul(&ZZ,&ZZ,3*CURVE_B_I_FP256BN); //3Bz^2 FP2_FP256BN_pmul(&YZ,&YZ,Qy); //-4YZ.Ys #if SEXTIC_TWIST_FP256BN==D_TYPE FP2_FP256BN_div_ip2(&ZZ); //6(b/i)z^2 #endif #if SEXTIC_TWIST_FP256BN==M_TYPE FP2_FP256BN_mul_ip(&ZZ); FP2_FP256BN_add(&ZZ,&ZZ,&ZZ); // 6biz^2 FP2_FP256BN_mul_ip(&YZ); FP2_FP256BN_norm(&YZ); #endif FP2_FP256BN_norm(&ZZ); // 6bi.Z^2 FP2_FP256BN_add(&YY,&YY,&YY); // 2y^2 FP2_FP256BN_sub(&ZZ,&ZZ,&YY); // FP2_FP256BN_norm(&ZZ); // 6b.Z^2-2Y^2 FP4_FP256BN_from_FP2s(&a,&YZ,&ZZ); // -4YZ.Ys | 6b.Z^2-2Y^2 | 6X^2.Xs #if SEXTIC_TWIST_FP256BN==D_TYPE FP4_FP256BN_from_FP2(&b,&XX); FP4_FP256BN_zero(&c); #endif #if SEXTIC_TWIST_FP256BN==M_TYPE FP4_FP256BN_zero(&b); FP4_FP256BN_from_FP2H(&c,&XX); #endif ECP2_FP256BN_dbl(A); //A.dbl(); } else { /* addition */ FP2_FP256BN_copy(&X1,&(A->x)); //FP2 X1=new FP2(A.getx()); // X1 FP2_FP256BN_copy(&Y1,&(A->y)); //FP2 Y1=new FP2(A.gety()); // Y1 FP2_FP256BN_copy(&T1,&(A->z)); //FP2 T1=new FP2(A.getz()); // Z1 FP2_FP256BN_copy(&T2,&T1); //FP2 T2=new FP2(A.getz()); // Z1 FP2_FP256BN_mul(&T1,&T1,&(B->y)); //T1.mul(B.gety()); // T1=Z1.Y2 FP2_FP256BN_mul(&T2,&T2,&(B->x)); //T2.mul(B.getx()); // T2=Z1.X2 FP2_FP256BN_sub(&X1,&X1,&T2); //X1.sub(T2); FP2_FP256BN_norm(&X1); //X1.norm(); // X1=X1-Z1.X2 FP2_FP256BN_sub(&Y1,&Y1,&T1); //Y1.sub(T1); FP2_FP256BN_norm(&Y1); //Y1.norm(); // Y1=Y1-Z1.Y2 FP2_FP256BN_copy(&T1,&X1); //T1.copy(X1); // T1=X1-Z1.X2 FP2_FP256BN_pmul(&X1,&X1,Qy); //X1.pmul(Qy); // X1=(X1-Z1.X2).Ys #if SEXTIC_TWIST_FP256BN==M_TYPE FP2_FP256BN_mul_ip(&X1); FP2_FP256BN_norm(&X1); #endif FP2_FP256BN_mul(&T1,&T1,&(B->y)); //T1.mul(B.gety()); // T1=(X1-Z1.X2).Y2 FP2_FP256BN_copy(&T2,&Y1); //T2.copy(Y1); // T2=Y1-Z1.Y2 FP2_FP256BN_mul(&T2,&T2,&(B->x)); //T2.mul(B.getx()); // T2=(Y1-Z1.Y2).X2 FP2_FP256BN_sub(&T2,&T2,&T1); //T2.sub(T1); FP2_FP256BN_norm(&T2); //T2.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 FP2_FP256BN_pmul(&Y1,&Y1,Qx); //Y1.pmul(Qx); FP2_FP256BN_neg(&Y1,&Y1); //Y1.neg(); FP2_FP256BN_norm(&Y1); //Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs FP4_FP256BN_from_FP2s(&a,&X1,&T2); // (X1-Z1.X2).Ys | (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 | - (Y1-Z1.Y2).Xs #if SEXTIC_TWIST_FP256BN==D_TYPE FP4_FP256BN_from_FP2(&b,&Y1); //b=new FP4(Y1); FP4_FP256BN_zero(&c); #endif #if SEXTIC_TWIST_FP256BN==M_TYPE FP4_FP256BN_zero(&b); FP4_FP256BN_from_FP2H(&c,&Y1); //b=new FP4(Y1); #endif ECP2_FP256BN_add(A,B); //A.add(B); } FP12_FP256BN_from_FP4s(v,&a,&b,&c); // FP12_FP256BN_norm(v); } /* Optimal R-ate pairing r=e(P,Q) */ void PAIR_FP256BN_ate(FP12_FP256BN *r,ECP2_FP256BN *P,ECP_FP256BN *Q) { FP2_FP256BN X; BIG_256_56 x,n,n3; FP_FP256BN Qx,Qy; int i,nb,bt; ECP2_FP256BN A; FP12_FP256BN lv; #if PAIRING_FRIENDLY_FP256BN==BN ECP2_FP256BN KA; #endif FP_FP256BN_rcopy(&Qx,Fra_FP256BN); FP_FP256BN_rcopy(&Qy,Frb_FP256BN); FP2_FP256BN_from_FPs(&X,&Qx,&Qy); #if SEXTIC_TWIST_FP256BN==M_TYPE FP2_FP256BN_inv(&X,&X); FP2_FP256BN_norm(&X); #endif BIG_256_56_rcopy(x,CURVE_Bnx_FP256BN); #if PAIRING_FRIENDLY_FP256BN==BN BIG_256_56_pmul(n,x,6); #if SIGN_OF_X_FP256BN==POSITIVEX BIG_256_56_inc(n,2); #else BIG_256_56_dec(n,2); #endif #else BIG_256_56_copy(n,x); #endif BIG_256_56_norm(n); BIG_256_56_pmul(n3,n,3); BIG_256_56_norm(n3); // ECP2_FP256BN_affine(P); // ECP_FP256BN_affine(Q); FP_FP256BN_copy(&Qx,&(Q->x)); FP_FP256BN_copy(&Qy,&(Q->y)); ECP2_FP256BN_copy(&A,P); FP12_FP256BN_one(r); nb=BIG_256_56_nbits(n3); //n /* Main Miller Loop */ for (i=nb-2; i>=1; i--) //0 { FP12_FP256BN_sqr(r,r); PAIR_FP256BN_line(&lv,&A,&A,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); //bt=BIG_256_56_bit(n,i); bt=BIG_256_56_bit(n3,i)-BIG_256_56_bit(n,i); if (bt==1) { PAIR_FP256BN_line(&lv,&A,P,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); } if (bt==-1) { ECP2_FP256BN_neg(P); PAIR_FP256BN_line(&lv,&A,P,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); ECP2_FP256BN_neg(P); } // FP12_FP256BN_sqr(r,r); } // PAIR_FP256BN_line(&lv,&A,&A,&Qx,&Qy); // FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); // if (BIG_256_56_parity(n)) // { // PAIR_FP256BN_line(&lv,&A,P,&Qx,&Qy); // FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); //} /* R-ate fixup required for BN curves */ #if PAIRING_FRIENDLY_FP256BN==BN ECP2_FP256BN_copy(&KA,P); ECP2_FP256BN_frob(&KA,&X); #if SIGN_OF_X_FP256BN==NEGATIVEX ECP2_FP256BN_neg(&A); FP12_FP256BN_conj(r,r); #endif PAIR_FP256BN_line(&lv,&A,&KA,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); ECP2_FP256BN_frob(&KA,&X); ECP2_FP256BN_neg(&KA); PAIR_FP256BN_line(&lv,&A,&KA,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); #endif } /* Optimal R-ate double pairing e(P,Q).e(R,S) */ void PAIR_FP256BN_double_ate(FP12_FP256BN *r,ECP2_FP256BN *P,ECP_FP256BN *Q,ECP2_FP256BN *R,ECP_FP256BN *S) { FP2_FP256BN X; BIG_256_56 x,n,n3; FP_FP256BN Qx,Qy,Sx,Sy; int i,nb,bt; ECP2_FP256BN A,B; FP12_FP256BN lv; #if PAIRING_FRIENDLY_FP256BN==BN ECP2_FP256BN K; #endif FP_FP256BN_rcopy(&Qx,Fra_FP256BN); FP_FP256BN_rcopy(&Qy,Frb_FP256BN); FP2_FP256BN_from_FPs(&X,&Qx,&Qy); #if SEXTIC_TWIST_FP256BN==M_TYPE FP2_FP256BN_inv(&X,&X); FP2_FP256BN_norm(&X); #endif BIG_256_56_rcopy(x,CURVE_Bnx_FP256BN); #if PAIRING_FRIENDLY_FP256BN==BN BIG_256_56_pmul(n,x,6); #if SIGN_OF_X_FP256BN==POSITIVEX BIG_256_56_inc(n,2); #else BIG_256_56_dec(n,2); #endif #else BIG_256_56_copy(n,x); #endif BIG_256_56_norm(n); BIG_256_56_pmul(n3,n,3); BIG_256_56_norm(n3); FP_FP256BN_copy(&Qx,&(Q->x)); FP_FP256BN_copy(&Qy,&(Q->y)); FP_FP256BN_copy(&Sx,&(S->x)); FP_FP256BN_copy(&Sy,&(S->y)); ECP2_FP256BN_copy(&A,P); ECP2_FP256BN_copy(&B,R); FP12_FP256BN_one(r); nb=BIG_256_56_nbits(n3); /* Main Miller Loop */ for (i=nb-2; i>=1; i--) { FP12_FP256BN_sqr(r,r); PAIR_FP256BN_line(&lv,&A,&A,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); PAIR_FP256BN_line(&lv,&B,&B,&Sx,&Sy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); bt=BIG_256_56_bit(n3,i)-BIG_256_56_bit(n,i); //bt=BIG_256_56_bit(n,i); if (bt==1) { PAIR_FP256BN_line(&lv,&A,P,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); PAIR_FP256BN_line(&lv,&B,R,&Sx,&Sy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); } if (bt==-1) { ECP2_FP256BN_neg(P); PAIR_FP256BN_line(&lv,&A,P,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); ECP2_FP256BN_neg(P); ECP2_FP256BN_neg(R); PAIR_FP256BN_line(&lv,&B,R,&Sx,&Sy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); ECP2_FP256BN_neg(R); } //FP12_FP256BN_sqr(r,r); } // PAIR_FP256BN_line(&lv,&A,&A,&Qx,&Qy); // FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); // PAIR_FP256BN_line(&lv,&B,&B,&Sx,&Sy); // FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); // if (BIG_256_56_parity(n)) // { // PAIR_FP256BN_line(&lv,&A,P,&Qx,&Qy); // FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); // PAIR_FP256BN_line(&lv,&B,R,&Sx,&Sy); // FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); // } /* R-ate fixup required for BN curves */ #if PAIRING_FRIENDLY_FP256BN==BN #if SIGN_OF_X_FP256BN==NEGATIVEX FP12_FP256BN_conj(r,r); ECP2_FP256BN_neg(&A); ECP2_FP256BN_neg(&B); #endif ECP2_FP256BN_copy(&K,P); ECP2_FP256BN_frob(&K,&X); PAIR_FP256BN_line(&lv,&A,&K,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); ECP2_FP256BN_frob(&K,&X); ECP2_FP256BN_neg(&K); PAIR_FP256BN_line(&lv,&A,&K,&Qx,&Qy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); ECP2_FP256BN_copy(&K,R); ECP2_FP256BN_frob(&K,&X); PAIR_FP256BN_line(&lv,&B,&K,&Sx,&Sy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); ECP2_FP256BN_frob(&K,&X); ECP2_FP256BN_neg(&K); PAIR_FP256BN_line(&lv,&B,&K,&Sx,&Sy); FP12_FP256BN_smul(r,&lv,SEXTIC_TWIST_FP256BN); #endif } /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ void PAIR_FP256BN_fexp(FP12_FP256BN *r) { FP2_FP256BN X; BIG_256_56 x; FP_FP256BN a,b; FP12_FP256BN t0,y0,y1,y2,y3; BIG_256_56_rcopy(x,CURVE_Bnx_FP256BN); FP_FP256BN_rcopy(&a,Fra_FP256BN); FP_FP256BN_rcopy(&b,Frb_FP256BN); FP2_FP256BN_from_FPs(&X,&a,&b); /* Easy part of final exp */ FP12_FP256BN_inv(&t0,r); FP12_FP256BN_conj(r,r); FP12_FP256BN_mul(r,&t0); FP12_FP256BN_copy(&t0,r); FP12_FP256BN_frob(r,&X); FP12_FP256BN_frob(r,&X); FP12_FP256BN_mul(r,&t0); /* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */ #if PAIRING_FRIENDLY_FP256BN==BN FP12_FP256BN_pow(&t0,r,x); // t0=f^-u #if SIGN_OF_X_FP256BN==POSITIVEX FP12_FP256BN_conj(&t0,&t0); #endif FP12_FP256BN_usqr(&y3,&t0); // y3=t0^2 FP12_FP256BN_copy(&y0,&t0); FP12_FP256BN_mul(&y0,&y3); // y0=t0*y3 FP12_FP256BN_copy(&y2,&y3); FP12_FP256BN_frob(&y2,&X); // y2=y3^p FP12_FP256BN_mul(&y2,&y3); //y2=y2*y3 FP12_FP256BN_usqr(&y2,&y2); //y2=y2^2 FP12_FP256BN_mul(&y2,&y3); // y2=y2*y3 FP12_FP256BN_pow(&t0,&y0,x); //t0=y0^-u #if SIGN_OF_X_FP256BN==POSITIVEX FP12_FP256BN_conj(&t0,&t0); #endif FP12_FP256BN_conj(&y0,r); //y0=~r FP12_FP256BN_copy(&y1,&t0); FP12_FP256BN_frob(&y1,&X); FP12_FP256BN_frob(&y1,&X); //y1=t0^p^2 FP12_FP256BN_mul(&y1,&y0); // y1=y0*y1 FP12_FP256BN_conj(&t0,&t0); // t0=~t0 FP12_FP256BN_copy(&y3,&t0); FP12_FP256BN_frob(&y3,&X); //y3=t0^p FP12_FP256BN_mul(&y3,&t0); // y3=t0*y3 FP12_FP256BN_usqr(&t0,&t0); // t0=t0^2 FP12_FP256BN_mul(&y1,&t0); // y1=t0*y1 FP12_FP256BN_pow(&t0,&y3,x); // t0=y3^-u #if SIGN_OF_X_FP256BN==POSITIVEX FP12_FP256BN_conj(&t0,&t0); #endif FP12_FP256BN_usqr(&t0,&t0); //t0=t0^2 FP12_FP256BN_conj(&t0,&t0); //t0=~t0 FP12_FP256BN_mul(&y3,&t0); // y3=t0*y3 FP12_FP256BN_frob(r,&X); FP12_FP256BN_copy(&y0,r); FP12_FP256BN_frob(r,&X); FP12_FP256BN_mul(&y0,r); FP12_FP256BN_frob(r,&X); FP12_FP256BN_mul(&y0,r); FP12_FP256BN_usqr(r,&y3); //r=y3^2 FP12_FP256BN_mul(r,&y2); //r=y2*r FP12_FP256BN_copy(&y3,r); FP12_FP256BN_mul(&y3,&y0); // y3=r*y0 FP12_FP256BN_mul(r,&y1); // r=r*y1 FP12_FP256BN_usqr(r,r); // r=r^2 FP12_FP256BN_mul(r,&y3); // r=r*y3 FP12_FP256BN_reduce(r); #else // Ghamman & Fouotsa Method FP12_FP256BN_usqr(&y0,r); FP12_FP256BN_pow(&y1,&y0,x); #if SIGN_OF_X_FP256BN==NEGATIVEX FP12_FP256BN_conj(&y1,&y1); #endif BIG_256_56_fshr(x,1); FP12_FP256BN_pow(&y2,&y1,x); #if SIGN_OF_X_FP256BN==NEGATIVEX FP12_FP256BN_conj(&y2,&y2); #endif BIG_256_56_fshl(x,1); // x must be even FP12_FP256BN_conj(&y3,r); FP12_FP256BN_mul(&y1,&y3); FP12_FP256BN_conj(&y1,&y1); FP12_FP256BN_mul(&y1,&y2); FP12_FP256BN_pow(&y2,&y1,x); #if SIGN_OF_X_FP256BN==NEGATIVEX FP12_FP256BN_conj(&y2,&y2); #endif FP12_FP256BN_pow(&y3,&y2,x); #if SIGN_OF_X_FP256BN==NEGATIVEX FP12_FP256BN_conj(&y3,&y3); #endif FP12_FP256BN_conj(&y1,&y1); FP12_FP256BN_mul(&y3,&y1); FP12_FP256BN_conj(&y1,&y1); FP12_FP256BN_frob(&y1,&X); FP12_FP256BN_frob(&y1,&X); FP12_FP256BN_frob(&y1,&X); FP12_FP256BN_frob(&y2,&X); FP12_FP256BN_frob(&y2,&X); FP12_FP256BN_mul(&y1,&y2); FP12_FP256BN_pow(&y2,&y3,x); #if SIGN_OF_X_FP256BN==NEGATIVEX FP12_FP256BN_conj(&y2,&y2); #endif FP12_FP256BN_mul(&y2,&y0); FP12_FP256BN_mul(&y2,r); FP12_FP256BN_mul(&y1,&y2); FP12_FP256BN_copy(&y2,&y3); FP12_FP256BN_frob(&y2,&X); FP12_FP256BN_mul(&y1,&y2); FP12_FP256BN_copy(r,&y1); FP12_FP256BN_reduce(r); // Aranha et al method as described by Ghamman & Fouotsa /* FP12_FP256BN_usqr(&y0,r); // t0=f^2 FP12_FP256BN_conj(&y3,&y0); // t0=f^-2 FP12_FP256BN_pow(&t0,r,x); // t5=f^u FP12_FP256BN_usqr(&y1,&t0); // t1=t5^2 FP12_FP256BN_mul(&y3,&t0); // t3=t0*t5 FP12_FP256BN_pow(&y0,&y3,x); FP12_FP256BN_pow(&y2,&y0,x); FP12_FP256BN_pow(&y4,&y2,x); FP12_FP256BN_mul(&y4,&y1); FP12_FP256BN_pow(&y1,&y4,x); FP12_FP256BN_conj(&y3,&y3); FP12_FP256BN_mul(&y1,&y3); FP12_FP256BN_mul(&y1,r); FP12_FP256BN_conj(&y3,r); FP12_FP256BN_mul(&y0,r); FP12_FP256BN_frob(&y0,&X); FP12_FP256BN_frob(&y0,&X); FP12_FP256BN_frob(&y0,&X); FP12_FP256BN_mul(&y4,&y3); FP12_FP256BN_frob(&y4,&X); FP12_FP256BN_mul(&t0,&y2); FP12_FP256BN_frob(&t0,&X); FP12_FP256BN_frob(&t0,&X); FP12_FP256BN_mul(&t0,&y0); FP12_FP256BN_mul(&t0,&y4); FP12_FP256BN_mul(&t0,&y1); FP12_FP256BN_copy(r,&t0); FP12_FP256BN_reduce(r);*/ //----------------------------------- /* FP12_FP256BN_copy(&y0,r); // y0=r; FP12_FP256BN_copy(&y1,r); // y1=r; FP12_FP256BN_copy(&t0,r); FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_FP256BN_conj(&y3,&t0); FP12_FP256BN_mul(&y1,&y3); // y1*=inverse(t0); FP12_FP256BN_frob(&t0,&X); FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(t0,X,2); FP12_FP256BN_mul(&y1,&t0); // y1*=t0; FP12_FP256BN_pow(r,r,x); // r=pow(r,x); FP12_FP256BN_conj(&y3,r); FP12_FP256BN_mul(&y1,&y3); // y1*=inverse(r); FP12_FP256BN_copy(&t0,r); FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_FP256BN_mul(&y0,&t0); // y0*=t0; FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_FP256BN_mul(&y1,&t0); // y1*=t0; FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_FP256BN_conj(&y3,&t0); FP12_FP256BN_mul(&y0,&y3); // y0*=inverse(t0); FP12_FP256BN_pow(r,r,x); // r=pow(r,x); FP12_FP256BN_mul(&y0,r); // y0*=r; FP12_FP256BN_copy(&t0,r); FP12_FP256BN_frob(&t0,&X); FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(r,X,2); FP12_FP256BN_conj(&y3,&t0); FP12_FP256BN_mul(&y0,&y3); // y0*=inverse(t0); FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_FP256BN_mul(&y1,&t0); // y1*=t0; FP12_FP256BN_pow(r,r,x); // r=pow(r,x); // r^x3 FP12_FP256BN_copy(&t0,r); FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_FP256BN_conj(&y3,&t0); FP12_FP256BN_mul(&y0,&y3); // y0*=inverse(t0); FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_FP256BN_mul(&y1,&t0); // y1*=t0; FP12_FP256BN_pow(r,r,x); // r=pow(r,x); // r^x4 FP12_FP256BN_conj(&y3,r); FP12_FP256BN_mul(&y0,&y3); // y0*=inverse(r); FP12_FP256BN_copy(&t0,r); FP12_FP256BN_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_FP256BN_mul(&y1,&t0); //y1*=t0; FP12_FP256BN_pow(r,r,x); // r=pow(r,x); // r^x5 FP12_FP256BN_mul(&y1,r); // y1*=r; FP12_FP256BN_usqr(&y0,&y0); // r=y0*y0*y1; FP12_FP256BN_mul(&y0,&y1); FP12_FP256BN_copy(r,&y0); FP12_FP256BN_reduce(r); */ #endif } #ifdef USE_GLV_FP256BN /* GLV method */ static void glv(BIG_256_56 u[2],BIG_256_56 e) { #if PAIRING_FRIENDLY_FP256BN==BN int i,j; BIG_256_56 v[2],t,q; DBIG_256_56 d; BIG_256_56_rcopy(q,CURVE_Order_FP256BN); for (i=0; i<2; i++) { BIG_256_56_rcopy(t,CURVE_W_FP256BN[i]); //BIG_256_56_norm(t); BIG_256_56_norm(e); BIG_256_56_mul(d,t,e); BIG_256_56_ddiv(v[i],d,q); BIG_256_56_zero(u[i]); } BIG_256_56_copy(u[0],e); for (i=0; i<2; i++) for (j=0; j<2; j++) { BIG_256_56_rcopy(t,CURVE_SB_FP256BN[j][i]); BIG_256_56_modmul(t,v[j],t,q); BIG_256_56_add(u[i],u[i],q); BIG_256_56_sub(u[i],u[i],t); BIG_256_56_mod(u[i],q); } #else // -(x^2).P = (Beta.x,y) BIG_256_56 x,x2,q; BIG_256_56_rcopy(x,CURVE_Bnx_FP256BN); BIG_256_56_mul(x2,x,x); BIG_256_56_copy(u[0],e); BIG_256_56_mod(u[0],x2); BIG_256_56_copy(u[1],e); BIG_256_56_sdiv(u[1],x2); BIG_256_56_rcopy(q,CURVE_Order_FP256BN); BIG_256_56_sub(u[1],q,u[1]); #endif return; } #endif // USE_GLV /* Galbraith & Scott Method */ static void gs(BIG_256_56 u[4],BIG_256_56 e) { int i; #if PAIRING_FRIENDLY_FP256BN==BN int j; BIG_256_56 v[4],t,q; DBIG_256_56 d; BIG_256_56_rcopy(q,CURVE_Order_FP256BN); for (i=0; i<4; i++) { BIG_256_56_rcopy(t,CURVE_WB_FP256BN[i]); //BIG_256_56_norm(t); BIG_256_56_norm(e); BIG_256_56_mul(d,t,e); BIG_256_56_ddiv(v[i],d,q); BIG_256_56_zero(u[i]); } BIG_256_56_copy(u[0],e); for (i=0; i<4; i++) for (j=0; j<4; j++) { BIG_256_56_rcopy(t,CURVE_BB_FP256BN[j][i]); BIG_256_56_modmul(t,v[j],t,q); BIG_256_56_add(u[i],u[i],q); BIG_256_56_sub(u[i],u[i],t); BIG_256_56_mod(u[i],q); } #else BIG_256_56 x,w,q; BIG_256_56_rcopy(q,CURVE_Order_FP256BN); BIG_256_56_rcopy(x,CURVE_Bnx_FP256BN); BIG_256_56_copy(w,e); for (i=0; i<3; i++) { BIG_256_56_copy(u[i],w); BIG_256_56_mod(u[i],x); BIG_256_56_sdiv(w,x); } BIG_256_56_copy(u[3],w); /* */ #if SIGN_OF_X_FP256BN==NEGATIVEX BIG_256_56_modneg(u[1],u[1],q); BIG_256_56_modneg(u[3],u[3],q); #endif #endif return; } /* Multiply P by e in group G1 */ void PAIR_FP256BN_G1mul(ECP_FP256BN *P,BIG_256_56 e) { #ifdef USE_GLV_FP256BN /* Note this method is patented */ int np,nn; ECP_FP256BN Q; FP_FP256BN cru; BIG_256_56 t,q; BIG_256_56 u[2]; BIG_256_56_rcopy(q,CURVE_Order_FP256BN); glv(u,e); ECP_FP256BN_affine(P); ECP_FP256BN_copy(&Q,P); FP_FP256BN_rcopy(&cru,CURVE_Cru_FP256BN); FP_FP256BN_mul(&(Q.x),&(Q.x),&cru); /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */ np=BIG_256_56_nbits(u[0]); BIG_256_56_modneg(t,u[0],q); nn=BIG_256_56_nbits(t); if (nn