/* * MIRACL E(F_p^2) support functions * mrecn2.c * */ #include #include "miracl.h" #ifdef MR_STATIC #include #endif static inline void zzn2_div2_i(zzn2 *w) { moddiv2(w->a->w); w->a->len=2; moddiv2(w->b->w); w->b->len=2; } static inline void zzn2_tim2_i(zzn2 *w) { #ifdef MR_COUNT_OPS fpa+=2; #endif modtim2(w->a->w); modtim2(w->b->w); w->a->len=2; w->b->len=2; } static inline void zzn2_tim3_i(zzn2 *w) { #ifdef MR_COUNT_OPS fpa+=4; #endif modtim3(w->a->w); modtim3(w->b->w); w->a->len=2; w->b->len=2; } static inline void zzn2_copy_i(zzn2 *x,zzn2 *w) { if (x==w) return; w->a->len=x->a->len; w->a->w[0]=x->a->w[0]; w->a->w[1]=x->a->w[1]; w->b->len=x->b->len; w->b->w[0]=x->b->w[0]; w->b->w[1]=x->b->w[1]; } static inline void zzn2_add_i(zzn2 *x,zzn2 *y,zzn2 *w) { #ifdef MR_COUNT_OPS fpa+=2; #endif modadd(x->a->w,y->a->w,w->a->w); modadd(x->b->w,y->b->w,w->b->w); w->a->len=2; w->b->len=2; } static inline void zzn2_sub_i(zzn2 *x,zzn2 *y,zzn2 *w) { #ifdef MR_COUNT_OPS fpa+=2; #endif modsub(x->a->w,y->a->w,w->a->w); modsub(x->b->w,y->b->w,w->b->w); w->a->len=2; w->b->len=2; } static inline void zzn2_timesi_i(zzn2 *u) { mr_small w1[2]; w1[0]=u->a->w[0]; w1[1]=u->a->w[1]; u->a->w[0]=u->b->w[0]; u->a->w[1]=u->b->w[1]; modneg(u->a->w); u->b->w[0]=w1[0]; u->b->w[1]=w1[1]; } static inline void zzn2_txx_i(zzn2 *u) { /* multiply w by t^2 where x^2-t is irreducible polynomial for ZZn4 for p=5 mod 8 t=sqrt(sqrt(-2)), qnr=-2 for p=3 mod 8 t=sqrt(1+sqrt(-1)), qnr=-1 for p=7 mod 8 and p=2,3 mod 5 t=sqrt(2+sqrt(-1)), qnr=-1 */ zzn2 t; struct bigtype aa,bb; big a,b; mr_small w3[2],w4[2]; a=&aa; b=&bb; a->len=2; b->len=2; a->w=w3; b->w=w4; t.a=a; t.b=b; zzn2_copy_i(u,&t); zzn2_timesi_i(u); zzn2_add_i(u,&t,u); zzn2_add_i(u,&t,u); u->a->len=2; u->b->len=2; } static inline void zzn2_pmul_i(int i,zzn2 *x) { modpmul(i,x->a->w); modpmul(i,x->b->w); } static inline void zzn2_sqr_i(zzn2 *x,zzn2 *w) { static mr_small w1[2],w2[2]; #ifdef MR_COUNT_OPS fpa+=3; fpc+=2; #endif modadd(x->a->w,x->b->w,w1); modsub(x->a->w,x->b->w,w2); modmult(x->a->w,x->b->w,w->b->w); modmult(w1,w2,w->a->w); // routine that calculates (a+b)(a-b) ?? modtim2(w->b->w); w->a->len=2; w->b->len=2; } static inline void zzn2_dblsub_i(zzn2 *x,zzn2 *y,zzn2 *w) { #ifdef MR_COUNT_OPS fpa+=4; #endif moddblsub(w->a->w,x->a->w,y->a->w); moddblsub(w->b->w,x->b->w,y->b->w); w->a->len=2; w->b->len=2; } static inline void zzn2_mul_i(zzn2 *x,zzn2 *y,zzn2 *w) { static mr_small w1[2],w2[2],w5[2]; #ifdef MR_COUNT_OPS fpa+=5; fpc+=3; #endif /*#pragma omp parallel sections { #pragma omp section */ modmult(x->a->w,y->a->w,w1); /* #pragma omp section */ modmult(x->b->w,y->b->w,w2); /*}*/ modadd(x->a->w,x->b->w,w5); modadd(y->a->w,y->b->w,w->b->w); modmult(w->b->w,w5,w->b->w); moddblsub(w->b->w,w1,w2); /* w->b->w - w1 -w2 */ modsub(w1,w2,w->a->w); w->a->len=2; w->b->len=2; } void zzn2_inv_i(_MIPD_ zzn2 *w) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; #ifdef MR_COUNT_OPS fpc+=4; fpa+=1; #endif MR_IN(163) modsqr(w->a->w,mr_mip->w1->w); modsqr(w->b->w,mr_mip->w2->w); modadd(mr_mip->w1->w,mr_mip->w2->w,mr_mip->w1->w); mr_mip->w1->len=2; /* redc(_MIPP_ mr_mip->w1,mr_mip->w6); */ copy(mr_mip->w1,mr_mip->w6); xgcd(_MIPP_ mr_mip->w6,mr_mip->modulus,mr_mip->w6,mr_mip->w6,mr_mip->w6); /* nres(_MIPP_ mr_mip->w6,mr_mip->w6); */ modmult(w->a->w,mr_mip->w6->w,w->a->w); modneg(mr_mip->w6->w); modmult(w->b->w,mr_mip->w6->w,w->b->w); MR_OUT } BOOL nres_sqroot(_MIPD_ big x,big w) { /* w=sqrt(x) mod p. This depends on p being prime! */ int i,t,js; #ifdef MR_COUNT_OPS fpc+=125; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return FALSE; copy(x,w); if (size(w)==0) return TRUE; copy(w,mr_mip->w1); for (i=0;i<25;i++) { modsqr(w->w,w->w); modsqr(w->w,w->w); modsqr(w->w,w->w); modsqr(w->w,w->w); modsqr(w->w,w->w); } w->len=2; modsqr(w->w,mr_mip->w2->w); mr_mip->w2->len=2; if (mr_compare(mr_mip->w1,mr_mip->w2)!=0) {zero(w);return FALSE;} return TRUE; } BOOL zzn2_sqrt(_MIPD_ zzn2 *u,zzn2 *w) { /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) where i*i=n */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifdef MR_COUNT_OPS fpc+=2; fpa+=1; #endif if (mr_mip->ERNUM) return FALSE; zzn2_copy(u,w); if (zzn2_iszero(w)) return TRUE; MR_IN(204) modsqr(w->b->w,mr_mip->w7->w); modsqr(w->a->w,mr_mip->w1->w); modadd(mr_mip->w1->w,mr_mip->w7->w,mr_mip->w7->w); mr_mip->w7->len=2; // nres_modmult(_MIPP_ w->b,w->b,mr_mip->w7); // nres_modmult(_MIPP_ w->a,w->a,mr_mip->w1); // nres_modadd(_MIPP_ mr_mip->w7,mr_mip->w1,mr_mip->w7); if (!nres_sqroot(_MIPP_ mr_mip->w7,mr_mip->w7)) /* s=w7 */ { zzn2_zero(w); MR_OUT return FALSE; } #ifdef MR_COUNT_OPS fpa+=1; #endif modadd(w->a->w,mr_mip->w7->w,mr_mip->w15->w); moddiv2(mr_mip->w15->w); mr_mip->w15->len=2; // nres_modadd(_MIPP_ w->a,mr_mip->w7,mr_mip->w15); // nres_div2(_MIPP_ mr_mip->w15,mr_mip->w15); if (!nres_sqroot(_MIPP_ mr_mip->w15,mr_mip->w15)) { #ifdef MR_COUNT_OPS fpa+=1; #endif modsub(w->a->w,mr_mip->w7->w,mr_mip->w15->w); moddiv2(mr_mip->w15->w); mr_mip->w15->len=2; // nres_modsub(_MIPP_ w->a,mr_mip->w7,mr_mip->w15); // nres_div2(_MIPP_ mr_mip->w15,mr_mip->w15); if (!nres_sqroot(_MIPP_ mr_mip->w15,mr_mip->w15)) { zzn2_zero(w); MR_OUT return FALSE; } // else printf("BBBBBBBBBBBBBBBBBB\n"); } // else printf("AAAAAAAAAAAAAAAAAAA\n"); #ifdef MR_COUNT_OPS fpa+=1; #endif copy(mr_mip->w15,w->a); modadd(mr_mip->w15->w,mr_mip->w15->w,mr_mip->w15->w); nres_moddiv(_MIPP_ w->b,mr_mip->w15,w->b); MR_OUT return TRUE; } /* BOOL zzn2_multi_inverse(_MIPD_ int m,zzn2 *x,zzn2 *w) { int i; zzn2 t1,t2; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (m==0) return TRUE; if (m<0) return FALSE; MR_IN(214) if (x==w) { mr_berror(_MIPP_ MR_ERR_BAD_PARAMETERS); MR_OUT return FALSE; } if (m==1) { zzn2_copy_i(&x[0],&w[0]); zzn2_inv_i(_MIPP_ &w[0]); MR_OUT return TRUE; } zzn2_from_int(_MIPP_ 1,&w[0]); zzn2_copy_i(&x[0],&w[1]); for (i=2;iw8; t1.b=mr_mip->w9; t2.a=mr_mip->w10; t2.b=mr_mip->w11; zzn2_mul_i(&w[m-1],&x[m-1],&t1); if (zzn2_iszero(&t1)) { mr_berror(_MIPP_ MR_ERR_DIV_BY_ZERO); MR_OUT return FALSE; } zzn2_inv_i(_MIPP_ &t1); zzn2_copy_i(&x[m-1],&t2); zzn2_mul_i(&w[m-1],&t1,&w[m-1]); for (i=m-2;;i--) { if (i==0) { zzn2_mul_i(&t2,&t1,&w[0]); break; } zzn2_mul_i(&w[i],&t2,&w[i]); zzn2_mul_i(&w[i],&t1,&w[i]); if (!zzn2_isunity(_MIPP_ &x[i])) zzn2_mul_i(&t2,&x[i],&t2); } MR_OUT return TRUE; } */ BOOL ecn2_iszero(ecn2 *a) { if (a->marker==MR_EPOINT_INFINITY) return TRUE; return FALSE; } void ecn2_copy(ecn2 *a,ecn2 *b) { zzn2_copy_i(&(a->x),&(b->x)); zzn2_copy_i(&(a->y),&(b->y)); #ifndef MR_AFFINE_ONLY if (a->marker==MR_EPOINT_GENERAL) zzn2_copy_i(&(a->z),&(b->z)); #endif b->marker=a->marker; } void ecn2_zero(ecn2 *a) { zzn2_zero(&(a->x)); zzn2_zero(&(a->y)); #ifndef MR_AFFINE_ONLY if (a->marker==MR_EPOINT_GENERAL) zzn2_zero(&(a->z)); #endif a->marker=MR_EPOINT_INFINITY; } BOOL ecn2_compare(_MIPD_ ecn2 *a,ecn2 *b) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return FALSE; MR_IN(193) ecn2_norm(_MIPP_ a); ecn2_norm(_MIPP_ b); MR_OUT if (zzn2_compare(&(a->x),&(b->x)) && zzn2_compare(&(a->y),&(b->y)) && a->marker==b->marker) return TRUE; return FALSE; } void ecn2_norm(_MIPD_ ecn2 *a) { zzn2 t; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifndef MR_AFFINE_ONLY if (mr_mip->ERNUM) return; if (a->marker!=MR_EPOINT_GENERAL) return; MR_IN(194) zzn2_inv_i(_MIPP_ &(a->z)); t.a=mr_mip->w3; t.b=mr_mip->w4; zzn2_copy_i(&(a->z),&t); zzn2_sqr_i( &(a->z),&(a->z)); zzn2_mul_i( &(a->x),&(a->z),&(a->x)); zzn2_mul_i( &(a->z),&t,&(a->z)); zzn2_mul_i( &(a->y),&(a->z),&(a->y)); zzn2_from_int(_MIPP_ 1,&(a->z)); a->marker=MR_EPOINT_NORMALIZED; MR_OUT #endif } void ecn2_get(_MIPD_ ecn2 *e,zzn2 *x,zzn2 *y,zzn2 *z) { zzn2_copy_i(&(e->x),x); zzn2_copy_i(&(e->y),y); #ifndef MR_AFFINE_ONLY if (e->marker==MR_EPOINT_GENERAL) zzn2_copy_i(&(e->z),z); else zzn2_from_zzn(mr_mip->one,z); #endif } void ecn2_getxy(ecn2 *e,zzn2 *x,zzn2 *y) { zzn2_copy_i(&(e->x),x); zzn2_copy_i(&(e->y),y); } void ecn2_getx(ecn2 *e,zzn2 *x) { zzn2_copy_i(&(e->x),x); } inline void zzn2_conj_i(zzn2 *x,zzn2 *w) { zzn2_copy_i(x,w); modneg(w->b->w); } void ecn2_psi(_MIPD_ zzn2 *psi,ecn2 *P) { ecn2_norm(_MIPP_ P); zzn2_conj_i(&(P->x),&(P->x)); zzn2_conj_i(&(P->y),&(P->y)); zzn2_mul_i(&(P->x),&psi[0],&(P->x)); zzn2_mul_i(&(P->y),&psi[1],&(P->y)); } #ifndef MR_AFFINE_ONLY void ecn2_getz(_MIPD_ ecn2 *e,zzn2 *z) { if (e->marker==MR_EPOINT_GENERAL) zzn2_copy_i(&(e->z),z); else zzn2_from_zzn(mr_mip->one,z); } #endif void ecn2_rhs(_MIPD_ zzn2 *x,zzn2 *rhs) { /* calculate RHS of elliptic curve equation */ BOOL twist; zzn2 A,B; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; twist=mr_mip->TWIST; MR_IN(202) A.a=mr_mip->w10; A.b=mr_mip->w11; B.a=mr_mip->w12; B.b=mr_mip->w13; if (mr_abs(mr_mip->Asize)Asize,&A); else zzn2_from_zzn(mr_mip->A,&A); if (mr_abs(mr_mip->Bsize)Bsize,&B); else zzn2_from_zzn(mr_mip->B,&B); if (twist) { if (mr_mip->Asize==0 || mr_mip->Bsize==0) { if (mr_mip->Asize==0) { zzn2_txd(_MIPP_ &B); } if (mr_mip->Bsize==0) { zzn2_mul_i( &A,x,&B); zzn2_txd(_MIPP_ &B); } zzn2_negate(_MIPP_ &B,&B); } else { zzn2_txx_i(&B); zzn2_txx_i(&B); zzn2_txx_i(&B); zzn2_mul_i( &A,x,&A); zzn2_txx_i(&A); zzn2_txx_i(&A); zzn2_add_i(&B,&A,&B); } } else { zzn2_mul_i( &A,x,&A); zzn2_add_i(&B,&A,&B); } zzn2_sqr_i( x,&A); zzn2_mul_i( &A,x,&A); zzn2_add_i(&B,&A,rhs); MR_OUT } BOOL ecn2_set(_MIPD_ zzn2 *x,zzn2 *y,ecn2 *e) { zzn2 lhs,rhs; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return FALSE; MR_IN(195) lhs.a=mr_mip->w10; lhs.b=mr_mip->w11; rhs.a=mr_mip->w12; rhs.b=mr_mip->w13; ecn2_rhs(_MIPP_ x,&rhs); zzn2_sqr_i( y,&lhs); if (!zzn2_compare(&lhs,&rhs)) { MR_OUT return FALSE; } zzn2_copy_i(x,&(e->x)); zzn2_copy_i(y,&(e->y)); e->marker=MR_EPOINT_NORMALIZED; MR_OUT return TRUE; } #ifndef MR_NOSUPPORT_COMPRESSION BOOL ecn2_setx(_MIPD_ zzn2 *x,ecn2 *e) { zzn2 rhs; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return FALSE; MR_IN(201) rhs.a=mr_mip->w12; rhs.b=mr_mip->w13; ecn2_rhs(_MIPP_ x,&rhs); if (!zzn2_iszero(&rhs)) { if (!zzn2_sqrt(_MIPP_ &rhs,&rhs)) { MR_OUT return FALSE; } } zzn2_copy_i(x,&(e->x)); zzn2_copy_i(&rhs,&(e->y)); e->marker=MR_EPOINT_NORMALIZED; MR_OUT return TRUE; } #endif #ifndef MR_AFFINE_ONLY void ecn2_setxyz(zzn2 *x,zzn2 *y,zzn2 *z,ecn2 *e) { zzn2_copy_i(x,&(e->x)); zzn2_copy_i(y,&(e->y)); zzn2_copy_i(z,&(e->z)); e->marker=MR_EPOINT_GENERAL; } #endif void ecn2_negate(_MIPD_ ecn2 *u,ecn2 *w) { ecn2_copy(u,w); if (!w->marker!=MR_EPOINT_INFINITY) zzn2_negate(_MIPP_ &(w->y),&(w->y)); } /* BOOL ecn2_add2(_MIPD_ ecn2 *Q,ecn2 *P,zzn2 *lam,zzn2 *ex1) { BOOL Doubling; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif Doubling=ecn2_add3(_MIPP_ Q,P,lam,ex1,NULL); return Doubling; } BOOL ecn2_add1(_MIPD_ ecn2 *Q,ecn2 *P,zzn2 *lam) { BOOL Doubling; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif Doubling=ecn2_add3(_MIPP_ Q,P,lam,NULL,NULL); return Doubling; } */ BOOL ecn2_sub(_MIPD_ ecn2 *Q,ecn2 *P) { BOOL Doubling; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif ecn2_negate(_MIPP_ Q,Q); Doubling=ecn2_add(_MIPP_ Q,P); ecn2_negate(_MIPP_ Q,Q); return Doubling; } /* static void zzn2_print(_MIPD_ char *label, zzn2 *x) { char s1[1024], s2[1024]; big a, b; #ifdef MR_STATIC char mem_big[MR_BIG_RESERVE(2)]; memset(mem_big, 0, MR_BIG_RESERVE(2)); a=mirvar_mem(_MIPP_ mem_big,0); b=mirvar_mem(_MIPP_ mem_big,1); #else a = mirvar(_MIPP_ 0); b = mirvar(_MIPP_ 0); #endif redc(_MIPP_ x->a, a); otstr(_MIPP_ a, s1); redc(_MIPP_ x->b, b); otstr(_MIPP_ b, s2); printf("%s: [%s,%s]\n", label, s1, s2); #ifndef MR_STATIC mr_free(a); mr_free(b); #endif } static void nres_print(_MIPD_ char *label, big x) { char s[1024]; big a; a = mirvar(_MIPP_ 0); redc(_MIPP_ x, a); otstr(_MIPP_ a, s); printf("%s: %s\n", label, s); mr_free(a); } */ BOOL ecn2_add_sub(_MIPD_ ecn2 *P,ecn2 *Q,ecn2 *PP,ecn2 *PM) { /* PP=P+Q, PM=P-Q. Assumes P and Q are both normalized, and P!=Q */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zzn2 t1,t2,lam; if (mr_mip->ERNUM) return FALSE; MR_IN(211) if (P->marker==MR_EPOINT_GENERAL || P->marker==MR_EPOINT_GENERAL) { /* Sorry, some restrictions.. */ mr_berror(_MIPP_ MR_ERR_BAD_PARAMETERS); MR_OUT return FALSE; } if (zzn2_compare(&(P->x),&(Q->x))) { /* P=Q or P=-Q - shouldn't happen */ ecn2_copy(P,PP); ecn2_add(_MIPP_ Q,PP); ecn2_copy(P,PM); ecn2_sub(_MIPP_ Q,PM); MR_OUT return TRUE; } t1.a = mr_mip->w8; t1.b = mr_mip->w9; t2.a = mr_mip->w10; t2.b = mr_mip->w11; lam.a = mr_mip->w12; lam.b = mr_mip->w13; zzn2_copy_i(&(P->x),&t2); zzn2_sub_i(&t2,&(Q->x),&t2); zzn2_inv_i(_MIPP_ &t2); /* only one inverse required */ zzn2_add_i(&(P->x),&(Q->x),&(PP->x)); zzn2_copy_i(&(PP->x),&(PM->x)); zzn2_copy_i(&(P->y),&t1); zzn2_sub_i(&t1,&(Q->y),&t1); zzn2_copy_i(&t1,&lam); zzn2_mul_i( &lam,&t2,&lam); zzn2_copy_i(&lam,&t1); zzn2_sqr_i( &t1,&t1); zzn2_sub_i(&t1,&(PP->x),&(PP->x)); zzn2_copy_i(&(Q->x),&(PP->y)); zzn2_sub_i(&(PP->y),&(PP->x),&(PP->y)); zzn2_mul_i( &(PP->y),&lam,&(PP->y)); zzn2_sub_i(&(PP->y),&(Q->y),&(PP->y)); zzn2_copy_i(&(P->y),&t1); zzn2_add_i(&t1,&(Q->y),&t1); zzn2_copy_i(&t1,&lam); zzn2_mul_i( &lam,&t2,&lam); zzn2_copy_i(&lam,&t1); zzn2_sqr_i( &t1,&t1); zzn2_sub_i(&t1,&(PM->x),&(PM->x)); zzn2_copy_i(&(Q->x),&(PM->y)); zzn2_sub_i(&(PM->y),&(PM->x),&(PM->y)); zzn2_mul_i( &(PM->y),&lam,&(PM->y)); zzn2_add_i(&(PM->y),&(Q->y),&(PM->y)); PP->marker=MR_EPOINT_NORMALIZED; PM->marker=MR_EPOINT_NORMALIZED; MR_OUT return TRUE; } BOOL ecn2_add(_MIPD_ ecn2 *Q,ecn2 *P) { /* P+=Q */ BOOL Doubling=FALSE; BOOL twist; int iA; zzn2 t1,t2,t3,lam; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif t1.a = mr_mip->w8; t1.b = mr_mip->w9; t2.a = mr_mip->w10; t2.b = mr_mip->w11; t3.a = mr_mip->w12; t3.b = mr_mip->w13; lam.a = mr_mip->w14; lam.b = mr_mip->w15; twist=mr_mip->TWIST; if (mr_mip->ERNUM) return FALSE; if (P->marker==MR_EPOINT_INFINITY) { ecn2_copy(Q,P); return Doubling; } if (Q->marker==MR_EPOINT_INFINITY) return Doubling; MR_IN(205) if (Q!=P && Q->marker==MR_EPOINT_GENERAL) { /* Sorry, this code is optimized for mixed addition only */ mr_berror(_MIPP_ MR_ERR_BAD_PARAMETERS); MR_OUT return Doubling; } #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { #endif if (!zzn2_compare(&(P->x),&(Q->x))) { zzn2_copy_i(&(P->y),&t1); zzn2_sub_i(&t1,&(Q->y),&t1); zzn2_copy_i(&(P->x),&t2); zzn2_sub_i(&t2,&(Q->x),&t2); zzn2_copy_i(&t1,&lam); zzn2_inv_i(_MIPP_ &t2); zzn2_mul_i( &lam,&t2,&lam); zzn2_add_i(&(P->x),&(Q->x),&(P->x)); zzn2_copy_i(&lam,&t1); zzn2_sqr_i( &t1,&t1); zzn2_sub_i(&t1,&(P->x),&(P->x)); zzn2_copy_i(&(Q->x),&(P->y)); zzn2_sub_i(&(P->y),&(P->x),&(P->y)); zzn2_mul_i( &(P->y),&lam,&(P->y)); zzn2_sub_i(&(P->y),&(Q->y),&(P->y)); } else { if (!zzn2_compare(&(P->y),&(Q->y)) || zzn2_iszero(&(P->y))) { ecn2_zero(P); zzn2_from_int(_MIPP_ 1,&lam); MR_OUT return Doubling; } zzn2_copy_i(&(P->x),&t1); zzn2_copy_i(&(P->x),&t2); zzn2_copy_i(&(P->x),&lam); zzn2_sqr_i( &lam,&lam); zzn2_copy_i(&lam,&t3); zzn2_tim2_i(&t3); zzn2_add_i(&lam,&t3,&lam); if (mr_abs(mr_mip->Asize)Asize,&t3); else zzn2_from_zzn(mr_mip->A,&t3); if (twist) { zzn2_txx_i(&t3); zzn2_txx_i(&t3); } zzn2_add_i(&lam,&t3,&lam); zzn2_copy_i(&(P->y),&t3); zzn2_tim2_i(&t3); zzn2_inv_i(_MIPP_ &t3); zzn2_mul_i( &lam,&t3,&lam); zzn2_add_i(&t2,&(P->x),&t2); zzn2_copy_i(&lam,&(P->x)); zzn2_sqr_i( &(P->x),&(P->x)); zzn2_sub_i(&(P->x),&t2,&(P->x)); zzn2_sub_i(&t1,&(P->x),&t1); zzn2_mul_i( &t1,&lam,&t1); zzn2_sub_i(&t1,&(P->y),&(P->y)); } #ifndef MR_AFFINE_ONLY zzn2_from_int(_MIPP_ 1,&(P->z)); #endif P->marker=MR_EPOINT_NORMALIZED; MR_OUT return Doubling; #ifndef MR_AFFINE_ONLY } if (Q==P) Doubling=TRUE; if (!Doubling) { if (P->marker!=MR_EPOINT_NORMALIZED) { zzn2_sqr_i(&(P->z),&t1); zzn2_mul_i(&t1,&(P->z),&t2); zzn2_mul_i(&t1,&(Q->x),&t1); zzn2_mul_i(&t2,&(Q->y),&t2); // zzn2_sqr_i( &(P->z),&t1); /* 1S */ // zzn2_mul_i( &t3,&t1,&t3); /* 1M */ // zzn2_mul_i( &t1,&(P->z),&t1); /* 1M */ // zzn2_mul_i( &Yzzz,&t1,&Yzzz); /* 1M */ } else { zzn2_copy(&(Q->x),&t1); zzn2_copy(&(Q->y),&t2); } if (zzn2_compare(&t1,&(P->x))) /*?*/ { if (!zzn2_compare(&t2,&(P->y)) || zzn2_iszero(&(P->y))) { ecn2_zero(P); zzn2_from_int(_MIPP_ 1,&lam); MR_OUT return Doubling; } else Doubling=TRUE; } } if (!Doubling) { /* Addition */ zzn2_sub_i(&t1,&(P->x),&t1); zzn2_sub_i(&t2,&(P->y),&t2); if (P->marker==MR_EPOINT_NORMALIZED) zzn2_copy_i(&t1,&(P->z)); else zzn2_mul_i(&(P->z),&t1,&(P->z)); zzn2_sqr_i(&t1,&t3); zzn2_mul_i(&t3,&t1,&lam); zzn2_mul_i(&t3,&(P->x),&t3); zzn2_copy_i(&t3,&t1); zzn2_tim2_i(&t1); zzn2_sqr_i(&t2,&(P->x)); zzn2_dblsub_i(&t1,&lam,&(P->x)); zzn2_sub_i(&t3,&(P->x),&t3); zzn2_mul_i(&t3,&t2,&t3); zzn2_mul_i(&lam,&(P->y),&lam); zzn2_sub_i(&t3,&lam,&(P->y)); } else { /* doubling */ if (P->marker==MR_EPOINT_NORMALIZED) zzn2_from_int(_MIPP_ 1,&t1); else zzn2_sqr_i(&(P->z),&t1); if (twist) zzn2_txx_i(&t1); zzn2_sub_i(&(P->x),&t1,&t2); zzn2_add_i(&t1,&(P->x),&t1); zzn2_mul_i(&t2,&t1,&t2); zzn2_tim3_i(&t2); zzn2_tim2_i(&(P->y)); if (P->marker==MR_EPOINT_NORMALIZED) zzn2_copy_i(&(P->y),&(P->z)); else zzn2_mul_i(&(P->z),&(P->y),&(P->z)); zzn2_sqr_i(&(P->y),&(P->y)); zzn2_mul_i(&(P->y),&(P->x),&t3); zzn2_sqr_i(&(P->y),&(P->y)); zzn2_div2_i(&(P->y)); zzn2_sqr_i(&t2,&(P->x)); zzn2_copy_i(&t3,&t1); zzn2_tim2_i(&t1); zzn2_sub_i(&(P->x),&t1,&(P->x)); zzn2_sub_i(&t3,&(P->x),&t1); zzn2_mul_i(&t1,&t2,&t1); zzn2_sub_i(&t1,&(P->y),&(P->y)); } P->marker=MR_EPOINT_GENERAL; MR_OUT return Doubling; #endif } static int calc_n(int w) { /* number of precomputed values needed for given window size */ if (w==3) return 3; if (w==4) return 5; if (w==5) return 11; if (w==6) return 41; return 0; } /* Dahmen, Okeya and Schepers "Affine Precomputation with Sole Inversion in Elliptic Curve Cryptography" */ /* Precomputes table into T. Assumes first P has been copied to P[0], then calculates 3P, 5P, 7P etc. into T */ #define MR_DOS_2 (14+4*MR_STR_SZ_2P) static void ecn2_dos(_MIPD_ int win,ecn2 *PT) { BOOL twist; int i,j,sz; zzn2 A,B,C,D,E,T,W,d[MR_STR_SZ_2P],e[MR_STR_SZ_2P]; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifndef MR_STATIC char *mem = memalloc(_MIPP_ MR_DOS_2); #else char mem[MR_BIG_RESERVE(MR_DOS_2)]; memset(mem, 0, MR_BIG_RESERVE(MR_DOS_2)); #endif twist=mr_mip->TWIST; j=0; sz=calc_n(win); A.a= mirvar_mem(_MIPP_ mem, j++); A.b= mirvar_mem(_MIPP_ mem, j++); B.a= mirvar_mem(_MIPP_ mem, j++); B.b= mirvar_mem(_MIPP_ mem, j++); C.a= mirvar_mem(_MIPP_ mem, j++); C.b= mirvar_mem(_MIPP_ mem, j++); D.a= mirvar_mem(_MIPP_ mem, j++); D.b= mirvar_mem(_MIPP_ mem, j++); E.a= mirvar_mem(_MIPP_ mem, j++); E.b= mirvar_mem(_MIPP_ mem, j++); T.a= mirvar_mem(_MIPP_ mem, j++); T.b= mirvar_mem(_MIPP_ mem, j++); W.a= mirvar_mem(_MIPP_ mem, j++); W.b= mirvar_mem(_MIPP_ mem, j++); for (i=0;iAsize)Asize,&A); else zzn2_from_zzn(mr_mip->A,&A); if (twist) { zzn2_txx_i(&A); zzn2_txx_i(&A); } zzn2_add_i(&A,&T,&A); /* 3. A=3x^2+a */ zzn2_copy_i(&A,&W); zzn2_add_i(&C,&C,&B); zzn2_add_i(&B,&C,&B); zzn2_mul_i(&B,&(PT[0].x),&B); /* 4. B=3C.x */ zzn2_sqr_i(&A,&d[1]); zzn2_sub_i(&d[1],&B,&d[1]); /* 5. d_1=A^2-B */ zzn2_sqr_i(&d[1],&E); /* 6. E=d_1^2 */ zzn2_mul_i(&B,&E,&B); /* 7. B=E.B */ zzn2_sqr_i(&C,&C); /* 8. C=C^2 */ zzn2_mul_i(&E,&d[1],&D); /* 9. D=E.d_1 */ zzn2_mul_i(&A,&d[1],&A); zzn2_add_i(&A,&C,&A); zzn2_negate(_MIPP_ &A,&A); /* 10. A=-d_1*A-C */ zzn2_add_i(&D,&D,&T); zzn2_sqr_i(&A,&d[2]); zzn2_sub_i(&d[2],&T,&d[2]); zzn2_sub_i(&d[2],&B,&d[2]); /* 11. d_2=A^2-2D-B */ if (sz>3) { zzn2_sqr_i(&d[2],&E); /* 12. E=d_2^2 */ zzn2_add_i(&T,&D,&T); zzn2_add_i(&T,&B,&T); zzn2_mul_i(&T,&E,&B); /* 13. B=E(B+3D) */ zzn2_add_i(&A,&A,&T); zzn2_add_i(&C,&T,&C); zzn2_mul_i(&C,&D,&C); /* 14. C=D(2A+C) */ zzn2_mul_i(&d[2],&E,&D); /* 15. D=E.d_2 */ zzn2_mul_i(&A,&d[2],&A); zzn2_add_i(&A,&C,&A); zzn2_negate(_MIPP_ &A,&A); /* 16. A=-d_2*A-C */ zzn2_sqr_i(&A,&d[3]); zzn2_sub_i(&d[3],&D,&d[3]); zzn2_sub_i(&d[3],&B,&d[3]); /* 17. d_3=A^2-D-B */ for (i=4;i0;i--) { zzn2_copy_i(&d[i],&B); zzn2_mul_i(&e[i-1],&A,&d[i]); zzn2_mul_i(&A,&B,&A); } zzn2_copy_i(&A,&d[0]); for (i=1;i=1;) { if (mr_mip->user!=NULL) (*mr_mip->user)(); n=mr_naf_window(_MIPP_ k,h,i,&nbs,&nzs,MR_WIN_SZ_2); for (j=0;j0) {nadds++; ecn2_add(_MIPP_ &T[n/2],P);} if (n<0) {nadds++; ecn2_sub(_MIPP_ &T[(-n)/2],P);} i-=nbs; if (nzs) { for (j=0;j0) bb=logb2(_MIPP_ e)-1; else bb=logb2(_MIPP_ f)-1; ecn2_add_sub(_MIPP_ &P1,&P2,&PS,&PD); ecn2_zero(R); nadds=0; while (bb>=0) { /* add/subtract method */ if (mr_mip->user!=NULL) (*mr_mip->user)(); ecn2_add(_MIPP_ R,R); e1=h1=e2=h2=0; if (mr_testbit(_MIPP_ d,bb)) e2=1; if (mr_testbit(_MIPP_ e,bb)) h2=1; if (mr_testbit(_MIPP_ c,bb)) e1=1; if (mr_testbit(_MIPP_ f,bb)) h1=1; if (e1!=h1) { if (e2==h2) { if (h1==1) {ecn2_add(_MIPP_ &P1,R); nadds++;} else {ecn2_sub(_MIPP_ &P1,R); nadds++;} } else { if (h1==1) { if (h2==1) {ecn2_add(_MIPP_ &PS,R); nadds++;} else {ecn2_add(_MIPP_ &PD,R); nadds++;} } else { if (h2==1) {ecn2_sub(_MIPP_ &PD,R); nadds++;} else {ecn2_sub(_MIPP_ &PS,R); nadds++;} } } } else if (e2!=h2) { if (h2==1) {ecn2_add(_MIPP_ &P2,R); nadds++;} else {ecn2_sub(_MIPP_ &P2,R); nadds++;} } bb-=1; } ecn2_norm(_MIPP_ R); MR_OUT #ifndef MR_STATIC memkill(_MIPP_ mem, MR_MUL2_JSF_RESERVE); #else memset(mem, 0, MR_BIG_RESERVE(MR_MUL2_JSF_RESERVE)); #endif return nadds; } /* General purpose multi-exponentiation engine, using inter-leaving algorithm. Calculate aP+bQ+cR+dS... Inputs are divided into two groups of sizes wa<4 and wb<4. For the first group if the points are fixed the first precomputed Table Ta[] may be taken from ROM. For the second group if the points are variable Tb[j] will have to computed online. Each group has its own window size, wina (=5?) and winb (=4?) respectively. The values a,b,c.. are provided in ma[] and mb[], and 3.a,3.b,3.c (as required by the NAF) are provided in ma3[] and mb3[]. If only one group is required, set wb=0 and pass NULL pointers. */ int ecn2_muln_engine(_MIPD_ int wa,int wina,int wb,int winb,big *ma,big *ma3,big *mb,big *mb3,ecn2 *Ta,ecn2 *Tb,ecn2 *R) { /* general purpose interleaving algorithm engine for multi-exp */ int i,j,tba[4],pba[4],na[4],sa[4],tbb[4],pbb[4],nb[4],sb[4],nbits,nbs,nzs; int sza,szb,nadds; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif sza=calc_n(wina); szb=calc_n(winb); ecn2_zero(R); nbits=0; for (i=0;inbits) nbits=j; } for (i=0;inbits) nbits=j; } nadds=0; for (i=nbits-1;i>=1;i--) { if (mr_mip->user!=NULL) (*mr_mip->user)(); if (R->marker!=MR_EPOINT_INFINITY) ecn2_add(_MIPP_ R,R); for (j=0;j0) {ecn2_add(_MIPP_ &Ta[j*sza+na[j]/2],R); nadds++;} if (na[j]<0) {ecn2_sub(_MIPP_ &Ta[j*sza+(-na[j])/2],R); nadds++;} } else { if (na[j]>0) {ecn2_sub(_MIPP_ &Ta[j*sza+na[j]/2],R); nadds++;} if (na[j]<0) {ecn2_add(_MIPP_ &Ta[j*sza+(-na[j])/2],R); nadds++;} } } } for (j=0;j0) {ecn2_add(_MIPP_ &Tb[j*szb+nb[j]/2],R); nadds++;} if (nb[j]<0) {ecn2_sub(_MIPP_ &Tb[j*szb+(-nb[j])/2],R); nadds++;} } else { if (nb[j]>0) {ecn2_sub(_MIPP_ &Tb[j*szb+nb[j]/2],R); nadds++;} if (nb[j]<0) {ecn2_add(_MIPP_ &Tb[j*szb+(-nb[j])/2],R); nadds++;} } } } } ecn2_norm(_MIPP_ R); return nadds; } /* Routines to support Galbraith, Lin, Scott (GLS) method for ECC */ /* requires an endomorphism psi */ /* *********************** */ /* Precompute T - first half from i.P, second half from i.psi(P) */ void ecn2_precomp_gls(_MIPD_ int win,ecn2 *P,zzn2 *psi,ecn2 *T) { int i,j,sz; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif j=0; sz=calc_n(win); MR_IN(219) ecn2_norm(_MIPP_ P); ecn2_copy(P,&T[0]); ecn2_dos(_MIPP_ win,T); /* precompute table */ for (i=sz;inb || mr_mip->ERNUM) return FALSE; t=MR_ROUNDUP(nb,window); if (t<2) return FALSE; MR_IN(221) #ifndef MR_ALWAYS_BINARY if (mr_mip->base != mr_mip->base2) { mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED); MR_OUT return FALSE; } #endif B->window=window; B->max=nb; table=mr_alloc(_MIPP_ (1<a=mirvar(_MIPP_ 0); B->b=mirvar(_MIPP_ 0); B->n=mirvar(_MIPP_ 0); copy(a,B->a); copy(b,B->b); copy(n,B->n); ecurve_init(_MIPP_ a,b,n,MR_AFFINE); mr_mip->TWIST=TRUE; w.x.a=mirvar(_MIPP_ 0); w.x.b=mirvar(_MIPP_ 0); w.y.a=mirvar(_MIPP_ 0); w.y.b=mirvar(_MIPP_ 0); w.marker=MR_EPOINT_INFINITY; ecn2_set(_MIPP_ x,y,&w); table[0].x.a=mirvar(_MIPP_ 0); table[0].x.b=mirvar(_MIPP_ 0); table[0].y.a=mirvar(_MIPP_ 0); table[0].y.b=mirvar(_MIPP_ 0); table[0].marker=MR_EPOINT_INFINITY; table[1].x.a=mirvar(_MIPP_ 0); table[1].x.b=mirvar(_MIPP_ 0); table[1].y.a=mirvar(_MIPP_ 0); table[1].y.b=mirvar(_MIPP_ 0); table[1].marker=MR_EPOINT_INFINITY; ecn2_copy(&w,&table[1]); for (j=0;jlen; bptr=0; B->table=mr_alloc(_MIPP_ 4*len*(1<table[bptr++]=table[i].x.a->w[j]; for (j=0;jtable[bptr++]=table[i].x.b->w[j]; for (j=0;jtable[bptr++]=table[i].y.a->w[j]; for (j=0;jtable[bptr++]=table[i].y.b->w[j]; mr_free(table[i].x.a); mr_free(table[i].x.b); mr_free(table[i].y.a); mr_free(table[i].y.b); } mr_free(table); MR_OUT return TRUE; } void ecn2_brick_end(ebrick *B) { mirkill(B->n); mirkill(B->b); mirkill(B->a); mr_free(B->table); } #else /* use precomputated table in ROM */ void ecn2_brick_init(ebrick *B,const mr_small* rom,big a,big b,big n,int window,int nb) { B->table=rom; B->a=a; /* just pass a pointer */ B->b=b; B->n=n; B->window=window; /* 2^4=16 stored values */ B->max=nb; } #endif /* void ecn2_mul_brick(_MIPD_ ebrick *B,big e,zzn2 *x,zzn2 *y) { int i,j,t,len,maxsize,promptr; ecn2 w,z; #ifdef MR_STATIC char mem[MR_BIG_RESERVE(10)]; #else char *mem; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (size(e)<0) mr_berror(_MIPP_ MR_ERR_NEG_POWER); t=MR_ROUNDUP(B->max,B->window); MR_IN(116) #ifndef MR_ALWAYS_BINARY if (mr_mip->base != mr_mip->base2) { mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED); MR_OUT return; } #endif if (logb2(_MIPP_ e) > B->max) { mr_berror(_MIPP_ MR_ERR_EXP_TOO_BIG); MR_OUT return; } ecurve_init(_MIPP_ B->a,B->b,B->n,MR_BEST); mr_mip->TWIST=TRUE; #ifdef MR_STATIC memset(mem,0,MR_BIG_RESERVE(10)); #else mem=memalloc(_MIPP_ 10); #endif w.x.a=mirvar_mem(_MIPP_ mem, 0); w.x.b=mirvar_mem(_MIPP_ mem, 1); w.y.a=mirvar_mem(_MIPP_ mem, 2); w.y.b=mirvar_mem(_MIPP_ mem, 3); w.z.a=mirvar_mem(_MIPP_ mem, 4); w.z.b=mirvar_mem(_MIPP_ mem, 5); w.marker=MR_EPOINT_INFINITY; z.x.a=mirvar_mem(_MIPP_ mem, 6); z.x.b=mirvar_mem(_MIPP_ mem, 7); z.y.a=mirvar_mem(_MIPP_ mem, 8); z.y.b=mirvar_mem(_MIPP_ mem, 9); z.marker=MR_EPOINT_INFINITY; len=B->n->len; maxsize=4*(1<window)*len; for (i=t-1;i>=0;i--) { j=recode(_MIPP_ e,t,B->window,i); ecn2_add(_MIPP_ &w,&w); if (j>0) { promptr=4*j*len; init_big_from_rom(z.x.a,len,B->table,maxsize,&promptr); init_big_from_rom(z.x.b,len,B->table,maxsize,&promptr); init_big_from_rom(z.y.a,len,B->table,maxsize,&promptr); init_big_from_rom(z.y.b,len,B->table,maxsize,&promptr); z.marker=MR_EPOINT_NORMALIZED; ecn2_add(_MIPP_ &z,&w); } } ecn2_norm(_MIPP_ &w); ecn2_getxy(&w,x,y); #ifndef MR_STATIC memkill(_MIPP_ mem,10); #else memset(mem,0,MR_BIG_RESERVE(10)); #endif MR_OUT } */ void ecn2_mul_brick_gls(_MIPD_ ebrick *B,big *e,zzn2 *psi,zzn2 *x,zzn2 *y) { int i,j,k,t,len,maxsize,promptr,se[2]; ecn2 w,z; #ifdef MR_STATIC char mem[MR_BIG_RESERVE(10)]; #else char *mem; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif for (k=0;k<2;k++) se[k]=exsign(e[k]); t=MR_ROUNDUP(B->max,B->window); MR_IN(222) #ifndef MR_ALWAYS_BINARY if (mr_mip->base != mr_mip->base2) { mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED); MR_OUT return; } #endif if (logb2(_MIPP_ e[0])>B->max || logb2(_MIPP_ e[1])>B->max) { mr_berror(_MIPP_ MR_ERR_EXP_TOO_BIG); MR_OUT return; } ecurve_init(_MIPP_ B->a,B->b,B->n,MR_BEST); mr_mip->TWIST=TRUE; #ifdef MR_STATIC memset(mem,0,MR_BIG_RESERVE(10)); #else mem=memalloc(_MIPP_ 10); #endif z.x.a=mirvar_mem(_MIPP_ mem, 0); z.x.b=mirvar_mem(_MIPP_ mem, 1); z.y.a=mirvar_mem(_MIPP_ mem, 2); z.y.b=mirvar_mem(_MIPP_ mem, 3); z.marker=MR_EPOINT_INFINITY; w.x.a=mirvar_mem(_MIPP_ mem, 4); w.x.b=mirvar_mem(_MIPP_ mem, 5); w.y.a=mirvar_mem(_MIPP_ mem, 6); w.y.b=mirvar_mem(_MIPP_ mem, 7); #ifndef MR_AFFINE_ONLY w.z.a=mirvar_mem(_MIPP_ mem, 8); w.z.b=mirvar_mem(_MIPP_ mem, 9); #endif w.marker=MR_EPOINT_INFINITY; len=B->n->len; maxsize=4*(1<window)*len; for (i=t-1;i>=0;i--) { ecn2_add(_MIPP_ &w,&w); for (k=0;k<2;k++) { j=recode(_MIPP_ e[k],t,B->window,i); if (j>0) { promptr=4*j*len; init_big_from_rom(z.x.a,len,B->table,maxsize,&promptr); init_big_from_rom(z.x.b,len,B->table,maxsize,&promptr); init_big_from_rom(z.y.a,len,B->table,maxsize,&promptr); init_big_from_rom(z.y.b,len,B->table,maxsize,&promptr); z.marker=MR_EPOINT_NORMALIZED; if (k==1) ecn2_psi(_MIPP_ psi,&z); if (se[k]==PLUS) ecn2_add(_MIPP_ &z,&w); else ecn2_sub(_MIPP_ &z,&w); } } } ecn2_norm(_MIPP_ &w); ecn2_getxy(&w,x,y); #ifndef MR_STATIC memkill(_MIPP_ mem,10); #else memset(mem,0,MR_BIG_RESERVE(10)); #endif MR_OUT }