void zzn4_inv(_MIPD_ zzn4 *w) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zzn2 t1,t2; if (mr_mip->ERNUM) return; if (w->unitary) { zzn4_conj(_MIPP_ w,w); return; } MR_IN(FUNC_BASE+10) t1.a=mr_mip->w8; t1.b=mr_mip->w9; t2.a=mr_mip->w10; t2.b=mr_mip->w11; zzn2_mul(_MIPP_ &(w->a),&(w->a),&t1); zzn2_mul(_MIPP_ &(w->b),&(w->b),&t2); zzn2_txx(_MIPP_ &t2); zzn2_sub(_MIPP_ &t1,&t2,&t1); zzn2_inv(_MIPP_ &t1); zzn2_mul(_MIPP_ &(w->a),&t1,&(w->a)); zzn2_negate(_MIPP_ &t1,&t1); zzn2_mul(_MIPP_ &(w->b),&t1,&(w->b)); MR_OUT }
void zzn4_mul(_MIPD_ zzn4 *x,zzn4 *y,zzn4 *w) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zzn2 t1,t2,t3; if (mr_mip->ERNUM) return; if (x==y) {zzn4_sqr(_MIPP_ x,w); return; } MR_IN(FUNC_BASE+9) t1.a=mr_mip->w12; t1.b=mr_mip->w13; t2.a=mr_mip->w8; t2.b=mr_mip->w9; t3.a=mr_mip->w10; t3.b=mr_mip->w11; zzn2_copy(&(x->a),&t1); zzn2_copy(&(x->b),&t2); zzn2_mul(_MIPP_ &t1,&(y->a),&t1); /* t1= x->a * y->a */ zzn2_mul(_MIPP_ &t2,&(y->b),&t2); /* t2 = x->b * y->b */ zzn2_copy(&(y->a),&t3); zzn2_add(_MIPP_ &t3,&(y->b),&t3); /* y->a + y->b */ zzn2_add(_MIPP_ &(x->b),&(x->a),&(w->b)); /* x->a + x->b */ zzn2_mul(_MIPP_ &(w->b),&t3,&(w->b)); /* t3= (x->a + x->b)*(y->a + y->b) */ zzn2_sub(_MIPP_ &(w->b),&t1,&(w->b)); zzn2_sub(_MIPP_ &(w->b),&t2,&(w->b)); /* w->b = t3-(t1+t2) */ zzn2_copy(&t1,&(w->a)); zzn2_txx(_MIPP_ &t2); zzn2_add(_MIPP_ &(w->a),&t2,&(w->a)); /* w->a = t1+tx(t2) */ if (x->unitary && y->unitary) w->unitary=TRUE; else w->unitary=FALSE; MR_OUT }
void zzn2_powl(_MIPD_ zzn2 *x,big e,zzn2 *w) { int i,s; zzn2 t1,t3,t4; t1.a=mr_mip->w7; t1.b=mr_mip->w8; t3.a=mr_mip->w10; t3.b=mr_mip->w11; t4.a=mr_mip->w13; t4.b=mr_mip->w14; zzn2_from_int(_MIPP_ 1,&t1); s=size(e); if (s==0) { zzn2_copy(&t1,w); return; } zzn2_copy(x,w); if (s==1 || s==(-1)) return; i=logb2(_MIPP_ e)-1; zzn2_copy(w,&t3); zzn2_mul(_MIPP_ w,w,&t4); zzn2_add(_MIPP_ &t4,&t4,&t4); zzn2_sub(_MIPP_ &t4,&t1,&t4); while (i--) { if (mr_testbit(_MIPP_ e,i)) { zzn2_mul(_MIPP_ &t3,&t4,&t3); zzn2_add(_MIPP_ &t3,&t3,&t3); zzn2_sub(_MIPP_ &t3,w,&t3); zzn2_mul(_MIPP_ &t4,&t4,&t4); zzn2_add(_MIPP_ &t4,&t4,&t4); zzn2_sub(_MIPP_ &t4,&t1,&t4); } else { zzn2_mul(_MIPP_ &t4,&t3,&t4); zzn2_add(_MIPP_ &t4,&t4,&t4); zzn2_sub(_MIPP_ &t4,w,&t4); zzn2_mul(_MIPP_ &t3,&t3,&t3); zzn2_add(_MIPP_ &t3,&t3,&t3); zzn2_sub(_MIPP_ &t3,&t1,&t3); } } zzn2_copy(&t3,w); }
void zzn4_sqr(_MIPD_ zzn4 *x,zzn4 *w) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zzn2 t1,t2; if (mr_mip->ERNUM) return; MR_IN(FUNC_BASE+8) t1.a=mr_mip->w10; t1.b=mr_mip->w11; t2.a=mr_mip->w8; t2.b=mr_mip->w9; zzn4_copy(x,w); if (x->unitary) { /* this is a lot faster.. - see Lenstra & Stam */ zzn2_mul(_MIPP_ &(w->b),&(w->b),&t1); zzn2_add(_MIPP_ &(w->b),&(w->a),&(w->b)); zzn2_mul(_MIPP_ &(w->b),&(w->b),&(w->b)); zzn2_sub(_MIPP_ &(w->b),&t1,&(w->b)); zzn2_txx(_MIPP_ &t1); zzn2_copy(&t1,&(w->a)); zzn2_sub(_MIPP_ &(w->b),&(w->a),&(w->b)); zzn2_add(_MIPP_ &(w->a),&(w->a),&(w->a)); zzn2_sadd(_MIPP_ &(w->a),mr_mip->one,&(w->a)); zzn2_ssub(_MIPP_ &(w->b),mr_mip->one,&(w->b)); } else { zzn2_copy(&(w->b),&t2); // t2=b; zzn2_add(_MIPP_ &(w->a),&t2,&t1); // t1=a+b zzn2_txx(_MIPP_ &t2); zzn2_add(_MIPP_ &t2,&(w->a),&t2); // t2=a+txx(b) zzn2_mul(_MIPP_ &(w->b),&(w->a),&(w->b)); // b*=a zzn2_mul(_MIPP_ &t1,&t2,&(w->a)); // a=t1*t2 zzn2_copy(&(w->b),&t2); //t2=b zzn2_sub(_MIPP_ &(w->a),&t2,&(w->a)); //a-=b zzn2_txx(_MIPP_ &t2); // t2=txx(b) zzn2_sub(_MIPP_ &(w->a),&t2,&(w->a)); // a-=txx(b); zzn2_add(_MIPP_ &(w->b),&(w->b),&(w->b)); // b+=b; } MR_OUT }
void zzn4_smul(_MIPD_ zzn4 *x,zzn2 *y,zzn4 *w) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(FUNC_BASE+7) if (!zzn2_iszero(&(x->a))) zzn2_mul(_MIPP_ &(x->a),y,&(w->a)); else zzn2_zero(&(w->a)); if (!zzn2_iszero(&(x->b))) zzn2_mul(_MIPP_ &(x->b),y,&(w->b)); else zzn2_zero(&(w->b)); w->unitary=FALSE; MR_OUT }
void zzn4_powq(_MIPD_ zzn2 *fr,zzn4 *w) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif MR_IN(FUNC_BASE+12) zzn2_conj(_MIPP_ &(w->a),&(w->a)); zzn2_conj(_MIPP_ &(w->b),&(w->b)); zzn2_mul(_MIPP_ &(w->b),fr,&(w->b)); MR_OUT }
void zzn4_inv(_MIPD_ zzn4 *u) { zzn2 t1,t2; if (u->unitary) { zzn4_conj(_MIPP_ u,u); return; } t1.a=mr_mip->w8; t1.b=mr_mip->w9; t2.a=mr_mip->w3; t2.b=mr_mip->w4; zzn2_mul(_MIPP_ &(u->x),&(u->x),&t1); zzn2_mul(_MIPP_ &(u->y),&(u->y),&t2); zzn2_times_irp(_MIPP_ &t2); zzn2_sub(_MIPP_ &t1,&t2,&t1); zzn2_inv(_MIPP_ &t1); zzn2_mul(_MIPP_ &(u->x),&t1,&(u->x)); zzn2_negate(_MIPP_ &t1,&t1); zzn2_mul(_MIPP_ &(u->y),&t1,&(u->y)); }
void g(_MIPD_ zzn2 *Ax,zzn2 *Ay,zzn2 *Az,zzn2 *Bx,zzn2 *By,zzn2 *Bz,big Px,big Py,zzn4 *w) { BOOL Doubling; zzn2 lam,extra1,extra2,Kx,nn,dd; #ifndef MR_STATIC char *mem = memalloc(_MIPP_ 12); #else char mem[MR_BIG_RESERVE(12)]; memset(mem, 0, MR_BIG_RESERVE(12)); #endif lam.a=mirvar_mem(_MIPP_ mem,0); lam.b=mirvar_mem(_MIPP_ mem,1); extra1.a=mirvar_mem(_MIPP_ mem,2); extra1.b=mirvar_mem(_MIPP_ mem,3); extra2.a=mirvar_mem(_MIPP_ mem,4); extra2.b=mirvar_mem(_MIPP_ mem,5); Kx.a=mirvar_mem(_MIPP_ mem,6); Kx.b=mirvar_mem(_MIPP_ mem,7); nn.a=mirvar_mem(_MIPP_ mem,8); nn.b=mirvar_mem(_MIPP_ mem,9); dd.a=mirvar_mem(_MIPP_ mem,10); dd.b=mirvar_mem(_MIPP_ mem,11); zzn2_copy(Ax,&Kx); Doubling=ecurve_fp2_add(_MIPP_ Bx,By,Bz,Ax,Ay,Az,&lam,&extra1,&extra2); /* Get extra information from the point addition, for use in the line functions */ if (!Doubling) { zzn2_smul(_MIPP_ Az,Py,&nn); zzn2_timesi(_MIPP_ &nn); zzn2_copy(Bx,&dd); zzn2_timesi(_MIPP_ &dd); zzn2_sadd(_MIPP_ &dd,Px,&dd); zzn2_mul(_MIPP_ &lam,&dd,&lam); zzn2_copy(By,&dd); zzn2_timesi(_MIPP_ &dd); zzn2_mul(_MIPP_ &dd,Az,&dd); zzn2_sub(_MIPP_ &lam,&dd,&dd); } else { zzn2_smul(_MIPP_ &extra2,Py,&nn); zzn2_mul(_MIPP_ &nn,Az,&nn); zzn2_timesi(_MIPP_ &nn); zzn2_timesi(_MIPP_ &Kx); zzn2_smul(_MIPP_ &extra2,Px,&dd); zzn2_add(_MIPP_ &dd,&Kx,&dd); zzn2_mul(_MIPP_ &lam,&dd,&lam); zzn2_timesi(_MIPP_ &extra1); zzn2_sub(_MIPP_ &lam,&extra1,&dd); } zzn2_copy(&nn,&(w->x)); zzn2_copy(&dd,&(w->y)); #ifndef MR_STATIC memkill(_MIPP_ mem,12); #else memset(mem,0,MR_BIG_RESERVE(12)); #endif return; }
BOOL ecurve_fp2_add(_MIPD_ zzn2 *Zx, zzn2 *Zy, zzn2 *Zz, zzn2 *x, zzn2 *y, zzn2 *z, zzn2 *lam,zzn2 *ex1,zzn2 *ex2) { BOOL doubling,normed; zzn2 Xzz, Yzzz, xZZ, yZZZ, zz, ZZ; zzn2 t1, t2, t3, x3; #ifndef MR_STATIC char *mem = memalloc(_MIPP_ 20); #else char mem[MR_BIG_RESERVE(20)]; memset(mem, 0, MR_BIG_RESERVE(20)); #endif Xzz.a = mirvar_mem(_MIPP_ mem, 0); Xzz.b = mirvar_mem(_MIPP_ mem, 1); Yzzz.a = mirvar_mem(_MIPP_ mem, 2); Yzzz.b = mirvar_mem(_MIPP_ mem, 3); xZZ.a = mirvar_mem(_MIPP_ mem, 4); xZZ.b = mirvar_mem(_MIPP_ mem, 5); yZZZ.a = mirvar_mem(_MIPP_ mem, 6); yZZZ.b = mirvar_mem(_MIPP_ mem, 7); zz.a = mirvar_mem(_MIPP_ mem, 8); zz.b = mirvar_mem(_MIPP_ mem, 9); ZZ.a = mirvar_mem(_MIPP_ mem, 10); ZZ.b = mirvar_mem(_MIPP_ mem, 11); t1.a = mirvar_mem(_MIPP_ mem, 12); t1.b = mirvar_mem(_MIPP_ mem, 13); t2.a = mirvar_mem(_MIPP_ mem, 14); t2.b = mirvar_mem(_MIPP_ mem, 15); t3.a = mirvar_mem(_MIPP_ mem, 16); t3.b = mirvar_mem(_MIPP_ mem, 17); x3.a = mirvar_mem(_MIPP_ mem, 18); x3.b = mirvar_mem(_MIPP_ mem, 19); doubling=FALSE; if (z==Zz) doubling=TRUE; if (!doubling) { // maybe we are really doubling? Or P-=P? if (!zzn2_isunity(_MIPP_ Zz)) { zzn2_mul(_MIPP_ Zz, Zz, &ZZ); // ZZ = Zz^2 zzn2_mul(_MIPP_ x, &ZZ, &xZZ); // xZZ = x * Zz^2 zzn2_mul(_MIPP_ &ZZ, Zz, &yZZZ); // yZZZ = Zz^3 zzn2_mul(_MIPP_ &yZZZ, y, &yZZZ); // yZZZ = y * Zz^3 normed=FALSE; } else { zzn2_copy(x,&xZZ); zzn2_copy(y,&yZZZ); normed=TRUE; } if (!zzn2_isunity(_MIPP_ z)) { zzn2_mul(_MIPP_ z, z, &zz); // zz = z^2 zzn2_mul(_MIPP_ Zx, &zz, &Xzz); // Xzz = Zx * z^2 zzn2_mul(_MIPP_ &zz, z, &Yzzz); // Yzzz = z^3 zzn2_mul(_MIPP_ &Yzzz, Zy, &Yzzz); // Yzzz = Zy * z^3 } else { zzn2_copy(Zx,&Xzz); zzn2_copy(Zy,&Yzzz); } if (zzn2_compare(&Xzz,&xZZ)) { if (!zzn2_compare(&Yzzz,&yZZZ) || zzn2_iszero(y)) { zzn2_zero(x); zzn2_zero(y); zzn2_zero(z); zzn2_from_int(_MIPP_ 1,lam); #ifndef MR_STATIC memkill(_MIPP_ mem, 20); #else memset(mem, 0, MR_BIG_RESERVE(20)); #endif return doubling; } else doubling=TRUE; } } if (!doubling) { // point addition zzn2_sub(_MIPP_ &xZZ, &Xzz, &t1); // t1 = Xzz - xZZ zzn2_sub(_MIPP_ &yZZZ, &Yzzz, lam); // lam = yZZZ - yZZZ zzn2_mul(_MIPP_ z,&t1,z); if (!normed) zzn2_mul(_MIPP_ z,&ZZ,z); zzn2_mul(_MIPP_ &t1,&t1,&t2); zzn2_add(_MIPP_ &xZZ,&Xzz,&t3); zzn2_mul(_MIPP_ &t3,&t2,&t3); zzn2_mul(_MIPP_ lam, lam, &x3); // x3 = lam^2 zzn2_sub(_MIPP_ &x3,&t3,&x3); zzn2_sub(_MIPP_ &t3,&x3,&t3); zzn2_sub(_MIPP_ &t3,&x3,&t3); zzn2_mul(_MIPP_ &t3,lam,&t3); zzn2_mul(_MIPP_ &t2,&t1,&t2); zzn2_add(_MIPP_ &yZZZ,&Yzzz,&t1); zzn2_mul(_MIPP_ &t1,&t2,&t1); zzn2_sub(_MIPP_ &t3,&t1,y); zzn2_div2(_MIPP_ y); zzn2_copy(&x3,x); } else { // point doubling zzn2_mul(_MIPP_ y, y, &t2); // t2 = y^2 /* its on the twist so A=6! */ zzn2_mul(_MIPP_ z,z,ex2); zzn2_mul(_MIPP_ x,x,lam); zzn2_mul(_MIPP_ ex2,ex2,&t1); zzn2_add(_MIPP_ &t1,&t1,&t1); zzn2_add(_MIPP_ lam,&t1,lam); zzn2_copy(lam,&t1); zzn2_add(_MIPP_ lam,lam,lam); zzn2_add(_MIPP_ lam,&t1,lam); zzn2_mul(_MIPP_ x, &t2, &t1); // t1 = x * y^2 zzn2_add(_MIPP_ &t1, &t1, &t1); // t1 = 2(x*y^2) zzn2_add(_MIPP_ &t1, &t1, &t1); // t1 = 4(x*y^2) // x = lam^2 - t1 - t1 zzn2_mul(_MIPP_ lam, lam, x); // x = lam^2 zzn2_sub(_MIPP_ x, &t1, x); // x = lam^2 - t1 zzn2_sub(_MIPP_ x, &t1, x); // x = lam^2 - 2t1 zzn2_mul(_MIPP_ z, y , z); // z = yz zzn2_add(_MIPP_ z, z, z); // z = 2yz // 8 * y^2 zzn2_add(_MIPP_ &t2, &t2, &t2); // t2 = 2y^2 zzn2_copy(&t2,ex1); zzn2_mul(_MIPP_ &t2, &t2, &t2); // t2 = 4y^2 zzn2_add(_MIPP_ &t2, &t2, &t2); // t2 = 8y^2 // y = lam*(t - x) - y^2 zzn2_sub(_MIPP_ &t1, x, y); // y = t1 - x zzn2_mul(_MIPP_ y, lam, y); // y = lam(t1 - x) zzn2_sub(_MIPP_ y, &t2, y); // y = lam(t1 - x) * y^2 } #ifndef MR_STATIC memkill(_MIPP_ mem, 20); #else memset(mem, 0, MR_BIG_RESERVE(20)); #endif return doubling; }
void zzn4_mul(_MIPD_ zzn4 *u,zzn4 *v,zzn4 *w) { zzn2 t1,t2,t3; t1.a=mr_mip->w3; t1.b=mr_mip->w4; t2.a=mr_mip->w8; t2.b=mr_mip->w9; if (u==v) { if (u->unitary) { /* this is faster.. - see Lenstra & Stam */ zzn4_copy(u,w); zzn2_mul(_MIPP_ &(w->y),&(w->y),&t1); zzn2_add(_MIPP_ &(w->y),&(w->x),&(w->y)); zzn2_mul(_MIPP_ &(w->y),&(w->y),&(w->y)); zzn2_sub(_MIPP_ &(w->y),&t1,&(w->y)); zzn2_timesi(_MIPP_ &t1); zzn2_copy(&t1,&(w->x)); zzn2_sub(_MIPP_ &(w->y),&(w->x),&(w->y)); zzn2_add(_MIPP_ &(w->x),&(w->x),&(w->x)); zzn2_sadd(_MIPP_ &(w->x),mr_mip->one,&(w->x)); zzn2_ssub(_MIPP_ &(w->y),mr_mip->one,&(w->y)); } else { zzn4_copy(u,w); zzn2_copy(&(w->y),&t2); // t2=b; zzn2_add(_MIPP_ &(w->x),&t2,&t1); // t1=a+b zzn2_times_irp(_MIPP_ &t2); // t2=txx(b); zzn2_add(_MIPP_ &t2,&(w->x),&t2); // t2=a+txx(b) zzn2_mul(_MIPP_ &(w->y),&(w->x),&(w->y)); // b*=a zzn2_mul(_MIPP_ &t1,&t2,&(w->x)); // a=t1*t2 zzn2_copy(&(w->y),&t2); //t2=b zzn2_sub(_MIPP_ &(w->x),&t2,&(w->x)); //a-=b zzn2_times_irp(_MIPP_ &t2); // t2=txx(b) zzn2_sub(_MIPP_ &(w->x),&t2,&(w->x)); // a-=txx(b); zzn2_add(_MIPP_ &(w->y),&(w->y),&(w->y)); // b+=b; } } else { t3.a=mr_mip->w10; t3.b=mr_mip->w11; zzn2_copy(&(u->x),&t1); zzn2_copy(&(u->y),&t2); zzn2_mul(_MIPP_ &t1,&(v->x),&t1); zzn2_mul(_MIPP_ &t2,&(v->y),&t2); zzn2_copy(&(v->x),&t3); zzn2_add(_MIPP_ &t3,&(v->y),&t3); zzn2_add(_MIPP_ &(u->y),&(u->x),&(w->y)); zzn2_mul(_MIPP_ &(w->y),&t3,&(w->y)); zzn2_sub(_MIPP_ &(w->y),&t1,&(w->y)); zzn2_sub(_MIPP_ &(w->y),&t2,&(w->y)); zzn2_copy(&t1,&(w->x)); zzn2_times_irp(_MIPP_ &t2); zzn2_add(_MIPP_ &(w->x),&t2,&(w->x)); if (u->unitary && v->unitary) w->unitary=TRUE; else w->unitary=FALSE; } }