/*************************************************************************** * Copyright 2013 CertiVox UK Ltd. * * This file is part of CertiVox MIRACL Crypto SDK. * * The CertiVox MIRACL Crypto SDK provides developers with an * extensive and efficient set of cryptographic functions. * For further information about its features and functionalities please * refer to http://www.certivox.com * * * The CertiVox MIRACL Crypto SDK is free software: you can * redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the * Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * * The CertiVox MIRACL Crypto SDK is distributed in the hope * that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * * You should have received a copy of the GNU Affero General Public * License along with CertiVox MIRACL Crypto SDK. * If not, see . * * You can be released from the requirements of the license by purchasing * a commercial license. Buying such a license is mandatory as soon as you * develop commercial activities involving the CertiVox MIRACL Crypto SDK * without disclosing the source code of your own applications, or shipping * the CertiVox MIRACL Crypto SDK with a closed source product. * * ***************************************************************************/ /* * MIRACL E(F_p^2) support functions * mrecn2.c */ #include #include "miracl.h" #ifdef MR_STATIC #include #endif #ifndef MR_EDWARDS BOOL ecn2_iszero(ecn2 *a) { if (a->marker==MR_EPOINT_INFINITY) return TRUE; return FALSE; } void ecn2_copy(ecn2 *a,ecn2 *b) { zzn2_copy(&(a->x),&(b->x)); zzn2_copy(&(a->y),&(b->y)); #ifndef MR_AFFINE_ONLY if (a->marker==MR_EPOINT_GENERAL) zzn2_copy(&(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(_MIPP_ &(a->z)); t.a=mr_mip->w3; t.b=mr_mip->w4; zzn2_copy(&(a->z),&t); zzn2_sqr(_MIPP_ &(a->z),&(a->z)); zzn2_mul(_MIPP_ &(a->x),&(a->z),&(a->x)); zzn2_mul(_MIPP_ &(a->z),&t,&(a->z)); zzn2_mul(_MIPP_ &(a->y),&(a->z),&(a->y)); zzn2_from_zzn(mr_mip->one,&(a->z)); a->marker=MR_EPOINT_NORMALIZED; MR_OUT #endif } void ecn2_get(_MIPD_ ecn2 *e,zzn2 *x,zzn2 *y,zzn2 *z) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zzn2_copy(&(e->x),x); zzn2_copy(&(e->y),y); #ifndef MR_AFFINE_ONLY if (e->marker==MR_EPOINT_GENERAL) zzn2_copy(&(e->z),z); else zzn2_from_zzn(mr_mip->one,z); #endif } void ecn2_getxy(ecn2 *e,zzn2 *x,zzn2 *y) { zzn2_copy(&(e->x),x); zzn2_copy(&(e->y),y); } void ecn2_getx(ecn2 *e,zzn2 *x) { zzn2_copy(&(e->x),x); } void ecn2_psi(_MIPD_ zzn2 *psi,ecn2 *P) { /* apply GLS morphism to P */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif MR_IN(212) ecn2_norm(_MIPP_ P); zzn2_conj(_MIPP_ &(P->x),&(P->x)); zzn2_conj(_MIPP_ &(P->y),&(P->y)); zzn2_mul(_MIPP_ &(P->x),&psi[0],&(P->x)); zzn2_mul(_MIPP_ &(P->y),&psi[1],&(P->y)); MR_OUT } #ifndef MR_AFFINE_ONLY void ecn2_getz(_MIPD_ ecn2 *e,zzn2 *z) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (e->marker==MR_EPOINT_GENERAL) zzn2_copy(&(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 */ int 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) { /* assume its the quartic or sextic twist, if such is possible */ if (twist==MR_QUARTIC_M) { zzn2_mul(_MIPP_ &A,x,&B); zzn2_txx(_MIPP_ &B); } if (twist==MR_QUARTIC_D) { zzn2_mul(_MIPP_ &A,x,&B); zzn2_txd(_MIPP_ &B); } if (twist==MR_SEXTIC_M) { zzn2_txx(_MIPP_ &B); } if (twist==MR_SEXTIC_D) { zzn2_txd(_MIPP_ &B); } if (twist==MR_QUADRATIC) { zzn2_txx(_MIPP_ &B); zzn2_txx(_MIPP_ &B); zzn2_txx(_MIPP_ &B); zzn2_mul(_MIPP_ &A,x,&A); zzn2_txx(_MIPP_ &A); zzn2_txx(_MIPP_ &A); zzn2_add(_MIPP_ &B,&A,&B); } /* if (mr_mip->Asize==0 || mr_mip->Bsize==0) { if (mr_mip->Asize==0) { // CM Discriminant D=3 - its the sextic twist (Hope I got the right one!). This works for BN curves zzn2_txd(_MIPP_ &B); } if (mr_mip->Bsize==0) { // CM Discriminant D=1 - its the quartic twist. zzn2_mul(_MIPP_ &A,x,&B); zzn2_txx(_MIPP_ &B); } } else { // its the quadratic twist zzn2_txx(_MIPP_ &B); zzn2_txx(_MIPP_ &B); zzn2_txx(_MIPP_ &B); zzn2_mul(_MIPP_ &A,x,&A); zzn2_txx(_MIPP_ &A); zzn2_txx(_MIPP_ &A); zzn2_add(_MIPP_ &B,&A,&B); } */ } else { zzn2_mul(_MIPP_ &A,x,&A); zzn2_add(_MIPP_ &B,&A,&B); } zzn2_sqr(_MIPP_ x,&A); zzn2_mul(_MIPP_ &A,x,&A); zzn2_add(_MIPP_ &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(_MIPP_ y,&lhs); if (!zzn2_compare(&lhs,&rhs)) { MR_OUT return FALSE; } zzn2_copy(x,&(e->x)); zzn2_copy(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_qr(_MIPP_ &rhs)) { MR_OUT return FALSE; } zzn2_sqrt(_MIPP_ &rhs,&rhs); } zzn2_copy(x,&(e->x)); zzn2_copy(&rhs,&(e->y)); e->marker=MR_EPOINT_NORMALIZED; MR_OUT return TRUE; } #endif #ifndef MR_AFFINE_ONLY void ecn2_setxyz(_MIPD_ zzn2 *x,zzn2 *y,zzn2 *z,ecn2 *e) { zzn2_copy(x,&(e->x)); zzn2_copy(y,&(e->y)); zzn2_copy(z,&(e->z)); if (zzn2_isunity(_MIPP_ z)) e->marker=MR_EPOINT_NORMALIZED; else e->marker=MR_EPOINT_GENERAL; } #endif /* Normalise an array of points of length mcoord==MR_AFFINE) return TRUE; if (mr_mip->ERNUM) return FALSE; if (m>MR_MAX_M_T_S) return FALSE; MR_IN(215) one.a=mr_mip->w12; one.b=mr_mip->w13; t.a=mr_mip->w14; t.b=mr_mip->w15; zzn2_from_int(_MIPP_ 1,&one); for (i=0;imarker!=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_add(_MIPD_ ecn2 *Q,ecn2 *P) { BOOL Doubling; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zzn2 lam; lam.a = mr_mip->w14; lam.b = mr_mip->w15; 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 zzn2 lam; lam.a = mr_mip->w14; lam.b = mr_mip->w15; ecn2_negate(_MIPP_ Q,Q); Doubling=ecn2_add3(_MIPP_ Q,P,&lam,NULL,NULL); ecn2_negate(_MIPP_ Q,Q); return Doubling; } 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; if (P->marker==MR_EPOINT_GENERAL || Q->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(&(P->x),&t2); zzn2_sub(_MIPP_ &t2,&(Q->x),&t2); zzn2_inv(_MIPP_ &t2); /* only one inverse required */ zzn2_add(_MIPP_ &(P->x),&(Q->x),&(PP->x)); zzn2_copy(&(PP->x),&(PM->x)); zzn2_copy(&(P->y),&t1); zzn2_sub(_MIPP_ &t1,&(Q->y),&t1); zzn2_copy(&t1,&lam); zzn2_mul(_MIPP_ &lam,&t2,&lam); zzn2_copy(&lam,&t1); zzn2_sqr(_MIPP_ &t1,&t1); zzn2_sub(_MIPP_ &t1,&(PP->x),&(PP->x)); zzn2_copy(&(Q->x),&(PP->y)); zzn2_sub(_MIPP_ &(PP->y),&(PP->x),&(PP->y)); zzn2_mul(_MIPP_ &(PP->y),&lam,&(PP->y)); zzn2_sub(_MIPP_ &(PP->y),&(Q->y),&(PP->y)); zzn2_copy(&(P->y),&t1); zzn2_add(_MIPP_ &t1,&(Q->y),&t1); zzn2_copy(&t1,&lam); zzn2_mul(_MIPP_ &lam,&t2,&lam); zzn2_copy(&lam,&t1); zzn2_sqr(_MIPP_ &t1,&t1); zzn2_sub(_MIPP_ &t1,&(PM->x),&(PM->x)); zzn2_copy(&(Q->x),&(PM->y)); zzn2_sub(_MIPP_ &(PM->y),&(PM->x),&(PM->y)); zzn2_mul(_MIPP_ &(PM->y),&lam,&(PM->y)); zzn2_add(_MIPP_ &(PM->y),&(Q->y),&(PM->y)); PP->marker=MR_EPOINT_NORMALIZED; PM->marker=MR_EPOINT_NORMALIZED; return TRUE; } BOOL ecn2_add3(_MIPD_ ecn2 *Q,ecn2 *P,zzn2 *lam,zzn2 *ex1,zzn2 *ex2) { /* P+=Q */ BOOL Doubling=FALSE; int twist; int iA; zzn2 t1,t2,t3; zzn2 Yzzz; #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; Yzzz.a = mr_mip->w3; Yzzz.b = mr_mip->w4; 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(&(P->y),&t1); zzn2_sub(_MIPP_ &t1,&(Q->y),&t1); zzn2_copy(&(P->x),&t2); zzn2_sub(_MIPP_ &t2,&(Q->x),&t2); zzn2_copy(&t1,lam); zzn2_inv(_MIPP_ &t2); zzn2_mul(_MIPP_ lam,&t2,lam); zzn2_add(_MIPP_ &(P->x),&(Q->x),&(P->x)); zzn2_copy(lam,&t1); zzn2_sqr(_MIPP_ &t1,&t1); zzn2_sub(_MIPP_ &t1,&(P->x),&(P->x)); zzn2_copy(&(Q->x),&(P->y)); zzn2_sub(_MIPP_ &(P->y),&(P->x),&(P->y)); zzn2_mul(_MIPP_ &(P->y),lam,&(P->y)); zzn2_sub(_MIPP_ &(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(&(P->x),&t1); zzn2_copy(&(P->x),&t2); zzn2_copy(&(P->x),lam); zzn2_sqr(_MIPP_ lam,lam); zzn2_add(_MIPP_ lam,lam,&t3); zzn2_add(_MIPP_ lam,&t3,lam); if (mr_abs(mr_mip->Asize)Asize,&t3); else zzn2_from_zzn(mr_mip->A,&t3); if (twist) { if (twist==MR_QUARTIC_M) { zzn2_txx(_MIPP_ &t3); } if (twist==MR_QUARTIC_D) { zzn2_txd(_MIPP_ &t3); } if (twist==MR_QUADRATIC) { zzn2_txx(_MIPP_ &t3); zzn2_txx(_MIPP_ &t3); } /* if (mr_mip->Bsize==0) { // assume its the quartic twist zzn2_txx(_MIPP_ &t3); } else { zzn2_txx(_MIPP_ &t3); zzn2_txx(_MIPP_ &t3); } */ } zzn2_add(_MIPP_ lam,&t3,lam); zzn2_add(_MIPP_ &(P->y),&(P->y),&t3); zzn2_inv(_MIPP_ &t3); zzn2_mul(_MIPP_ lam,&t3,lam); zzn2_add(_MIPP_ &t2,&(P->x),&t2); zzn2_copy(lam,&(P->x)); zzn2_sqr(_MIPP_ &(P->x),&(P->x)); zzn2_sub(_MIPP_ &(P->x),&t2,&(P->x)); zzn2_sub(_MIPP_ &t1,&(P->x),&t1); zzn2_mul(_MIPP_ &t1,lam,&t1); zzn2_sub(_MIPP_ &t1,&(P->y),&(P->y)); } P->marker=MR_EPOINT_NORMALIZED; MR_OUT return Doubling; #ifndef MR_AFFINE_ONLY } if (Q==P) Doubling=TRUE; zzn2_copy(&(Q->x),&t3); zzn2_copy(&(Q->y),&Yzzz); if (!Doubling) { if (P->marker!=MR_EPOINT_NORMALIZED) { zzn2_sqr(_MIPP_ &(P->z),&t1); /* 1S */ zzn2_mul(_MIPP_ &t3,&t1,&t3); /* 1M */ zzn2_mul(_MIPP_ &t1,&(P->z),&t1); /* 1M */ zzn2_mul(_MIPP_ &Yzzz,&t1,&Yzzz); /* 1M */ } if (zzn2_compare(&t3,&(P->x))) { if (!zzn2_compare(&Yzzz,&(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(_MIPP_ &t3,&(P->x),&t3); zzn2_sub(_MIPP_ &Yzzz,&(P->y),lam); if (P->marker==MR_EPOINT_NORMALIZED) zzn2_copy(&t3,&(P->z)); else zzn2_mul(_MIPP_ &(P->z),&t3,&(P->z)); /* 1M */ zzn2_sqr(_MIPP_ &t3,&t1); /* 1S */ zzn2_mul(_MIPP_ &t1,&t3,&Yzzz); /* 1M */ zzn2_mul(_MIPP_ &t1,&(P->x),&t1); /* 1M */ zzn2_copy(&t1,&t3); zzn2_add(_MIPP_ &t3,&t3,&t3); zzn2_sqr(_MIPP_ lam,&(P->x)); /* 1S */ zzn2_sub(_MIPP_ &(P->x),&t3,&(P->x)); zzn2_sub(_MIPP_ &(P->x),&Yzzz,&(P->x)); zzn2_sub(_MIPP_ &t1,&(P->x),&t1); zzn2_mul(_MIPP_ &t1,lam,&t1); /* 1M */ zzn2_mul(_MIPP_ &Yzzz,&(P->y),&Yzzz); /* 1M */ zzn2_sub(_MIPP_ &t1,&Yzzz,&(P->y)); /* zzn2_sub(_MIPP_ &(P->x),&t3,&t1); zzn2_sub(_MIPP_ &(P->y),&Yzzz,lam); if (P->marker==MR_EPOINT_NORMALIZED) zzn2_copy(&t1,&(P->z)); else zzn2_mul(_MIPP_ &(P->z),&t1,&(P->z)); zzn2_sqr(_MIPP_ &t1,&t2); zzn2_add(_MIPP_ &(P->x),&t3,&t3); zzn2_mul(_MIPP_ &t3,&t2,&t3); zzn2_sqr(_MIPP_ lam,&(P->x)); zzn2_sub(_MIPP_ &(P->x),&t3,&(P->x)); zzn2_mul(_MIPP_ &t2,&t1,&t2); zzn2_add(_MIPP_ &(P->x),&(P->x),&t1); zzn2_sub(_MIPP_ &t3,&t1,&t3); zzn2_mul(_MIPP_ &t3,lam,&t3); zzn2_add(_MIPP_ &(P->y),&Yzzz,&t1); zzn2_mul(_MIPP_ &t2,&t1,&t2); zzn2_sub(_MIPP_ &t3,&t2,&(P->y)); zzn2_div2(_MIPP_ &(P->y)); */ } else { /* doubling */ zzn2_sqr(_MIPP_ &(P->y),&t3); /* 1S */ iA=mr_mip->Asize; if (iA!=0) { if (P->marker==MR_EPOINT_NORMALIZED) zzn2_from_int(_MIPP_ 1,&t1); else zzn2_sqr(_MIPP_ &(P->z),&t1); /* 1S */ if (ex2!=NULL) zzn2_copy(&t1,ex2); if (iA==-3 && twist<=MR_QUADRATIC) { if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &t1); /* quadratic twist */ zzn2_sub(_MIPP_ &(P->x),&t1,lam); zzn2_add(_MIPP_ &t1,&(P->x),&t1); zzn2_mul(_MIPP_ lam,&t1,lam); /* 1M */ zzn2_add(_MIPP_ lam,lam,&t2); zzn2_add(_MIPP_ lam,&t2,lam); } else { zzn2_sqr(_MIPP_ &(P->x),lam); /* 1S */ zzn2_add(_MIPP_ lam,lam,&t2); zzn2_add(_MIPP_ lam,&t2,lam); if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &t1); /* quadratic twist */ zzn2_sqr(_MIPP_ &t1,&t1); /* 1S */ if (twist==MR_QUARTIC_M) zzn2_txx(_MIPP_ &t1); /* quartic twist */ if (twist==MR_QUARTIC_D) zzn2_txd(_MIPP_ &t1); /* quartic twist */ if (iA!=1) { /* optimized for iA=1 case */ if (iAA,&t1); } zzn2_add(_MIPP_ lam,&t1,lam); } } else { zzn2_sqr(_MIPP_ &(P->x),lam); /* 1S */ zzn2_add(_MIPP_ lam,lam,&t2); zzn2_add(_MIPP_ lam,&t2,lam); } zzn2_mul(_MIPP_ &(P->x),&t3,&t1); /* 1M */ zzn2_add(_MIPP_ &t1,&t1,&t1); zzn2_add(_MIPP_ &t1,&t1,&t1); zzn2_sqr(_MIPP_ lam,&(P->x)); /* 1S */ zzn2_add(_MIPP_ &t1,&t1,&t2); zzn2_sub(_MIPP_ &(P->x),&t2,&(P->x)); if (P->marker==MR_EPOINT_NORMALIZED) zzn2_copy(&(P->y),&(P->z)); else zzn2_mul(_MIPP_ &(P->z),&(P->y),&(P->z)); /* 1M */ zzn2_add(_MIPP_ &(P->z),&(P->z),&(P->z)); zzn2_add(_MIPP_ &t3,&t3,&t3); if (ex1!=NULL) zzn2_copy(&t3,ex1); zzn2_sqr(_MIPP_ &t3,&t3); /* 1S */ zzn2_add(_MIPP_ &t3,&t3,&t3); zzn2_sub(_MIPP_ &t1,&(P->x),&t1); zzn2_mul(_MIPP_ lam,&t1,&(P->y)); /* 1M */ zzn2_sub(_MIPP_ &(P->y),&t3,&(P->y)); } P->marker=MR_EPOINT_GENERAL; MR_OUT return Doubling; #endif } /* 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_PRE_2 (14+4*MR_ECC_STORE_N2) static void ecn2_pre(_MIPD_ int sz,BOOL norm,ecn2 *PT) { int twist; int i,j; zzn2 A,B,C,D,E,T,W; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifndef MR_STATIC zzn2 *d=(zzn2 *)mr_alloc(_MIPP_ sz,sizeof(zzn2)); zzn2 *e=(zzn2 *)mr_alloc(_MIPP_ sz,sizeof(zzn2)); char *mem = (char *)memalloc(_MIPP_ 14+4*sz); #else zzn2 d[MR_ECC_STORE_N2],e[MR_ECC_STORE_N2]; char mem[MR_BIG_RESERVE(MR_PRE_2)]; memset(mem, 0, MR_BIG_RESERVE(MR_PRE_2)); #endif twist=mr_mip->TWIST; j=0; 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) { if (twist==MR_QUARTIC_M) { zzn2_txx(_MIPP_ &A); } if (twist==MR_QUARTIC_D) { zzn2_txd(_MIPP_ &A); } if (twist==MR_QUADRATIC) { zzn2_txx(_MIPP_ &A); zzn2_txx(_MIPP_ &A); } /* if (mr_mip->Bsize==0) { // assume its the quartic twist zzn2_txx(_MIPP_ &A); } else { zzn2_txx(_MIPP_ &A); zzn2_txx(_MIPP_ &A); } */ } zzn2_add(_MIPP_ &A,&T,&A); /* 3. A=3x^2+a */ zzn2_copy(&A,&W); zzn2_add(_MIPP_ &C,&C,&B); zzn2_add(_MIPP_ &B,&C,&B); zzn2_mul(_MIPP_ &B,&(PT[0].x),&B); /* 4. B=3C.x */ zzn2_sqr(_MIPP_ &A,&d[1]); zzn2_sub(_MIPP_ &d[1],&B,&d[1]); /* 5. d_1=A^2-B */ zzn2_sqr(_MIPP_ &d[1],&E); /* 6. E=d_1^2 */ zzn2_mul(_MIPP_ &B,&E,&B); /* 7. B=E.B */ zzn2_sqr(_MIPP_ &C,&C); /* 8. C=C^2 */ zzn2_mul(_MIPP_ &E,&d[1],&D); /* 9. D=E.d_1 */ zzn2_mul(_MIPP_ &A,&d[1],&A); zzn2_add(_MIPP_ &A,&C,&A); zzn2_negate(_MIPP_ &A,&A); /* 10. A=-d_1*A-C */ zzn2_add(_MIPP_ &D,&D,&T); zzn2_sqr(_MIPP_ &A,&d[2]); zzn2_sub(_MIPP_ &d[2],&T,&d[2]); zzn2_sub(_MIPP_ &d[2],&B,&d[2]); /* 11. d_2=A^2-2D-B */ if (sz>3) { zzn2_sqr(_MIPP_ &d[2],&E); /* 12. E=d_2^2 */ zzn2_add(_MIPP_ &T,&D,&T); zzn2_add(_MIPP_ &T,&B,&T); zzn2_mul(_MIPP_ &T,&E,&B); /* 13. B=E(B+3D) */ zzn2_add(_MIPP_ &A,&A,&T); zzn2_add(_MIPP_ &C,&T,&C); zzn2_mul(_MIPP_ &C,&D,&C); /* 14. C=D(2A+C) */ zzn2_mul(_MIPP_ &d[2],&E,&D); /* 15. D=E.d_2 */ zzn2_mul(_MIPP_ &A,&d[2],&A); zzn2_add(_MIPP_ &A,&C,&A); zzn2_negate(_MIPP_ &A,&A); /* 16. A=-d_2*A-C */ zzn2_sqr(_MIPP_ &A,&d[3]); zzn2_sub(_MIPP_ &d[3],&D,&d[3]); zzn2_sub(_MIPP_ &d[3],&B,&d[3]); /* 17. d_3=A^2-D-B */ for (i=4;i0;i--) { zzn2_copy(&d[i],&B); zzn2_mul(_MIPP_ &e[i-1],&A,&d[i]); zzn2_mul(_MIPP_ &A,&B,&A); } zzn2_copy(&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_ECC_STORE_N2); 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 precomputed store size, sza (=8?) and szb (=20?) 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 sza,int wb,int szb,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 nadds; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif 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 sz,BOOL norm,ecn2 *P,zzn2 *psi,ecn2 *T) { int i,j; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif j=0; MR_IN(219) ecn2_norm(_MIPP_ P); ecn2_copy(P,&T[0]); ecn2_pre(_MIPP_ sz,norm,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=(ecn2 *)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=MR_QUADRATIC; 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_small *)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=MR_QUADRATIC; #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=MR_QUADRATIC; #ifdef MR_STATIC memset(mem,0,MR_BIG_RESERVE(10)); #else mem=(char *)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 } #else /* Now for curves in Inverted Twisted Edwards Form */ BOOL ecn2_iszero(ecn2 *a) { if (a->marker==MR_EPOINT_INFINITY) return TRUE; return FALSE; } void ecn2_copy(ecn2 *a,ecn2 *b) { zzn2_copy(&(a->x),&(b->x)); zzn2_copy(&(a->y),&(b->y)); if (a->marker==MR_EPOINT_GENERAL) zzn2_copy(&(a->z),&(b->z)); b->marker=a->marker; } void ecn2_zero(ecn2 *a) { zzn2_zero(&(a->x)); zzn2_zero(&(a->y)); if (a->marker==MR_EPOINT_GENERAL) zzn2_zero(&(a->z)); 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) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; if (a->marker!=MR_EPOINT_GENERAL) return; MR_IN(194) zzn2_inv(_MIPP_ &(a->z)); zzn2_mul(_MIPP_ &(a->x),&(a->z),&(a->x)); zzn2_mul(_MIPP_ &(a->y),&(a->z),&(a->y)); zzn2_from_zzn(mr_mip->one,&(a->z)); a->marker=MR_EPOINT_NORMALIZED; MR_OUT } void ecn2_get(_MIPD_ ecn2 *e,zzn2 *x,zzn2 *y,zzn2 *z) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zzn2_copy(&(e->x),x); zzn2_copy(&(e->y),y); if (e->marker==MR_EPOINT_GENERAL) zzn2_copy(&(e->z),z); else zzn2_from_zzn(mr_mip->one,z); } void ecn2_getxy(ecn2 *e,zzn2 *x,zzn2 *y) { zzn2_copy(&(e->x),x); zzn2_copy(&(e->y),y); } void ecn2_getx(ecn2 *e,zzn2 *x) { zzn2_copy(&(e->x),x); } void ecn2_getz(_MIPD_ ecn2 *e,zzn2 *z) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (e->marker==MR_EPOINT_GENERAL) zzn2_copy(&(e->z),z); else zzn2_from_zzn(mr_mip->one,z); } void ecn2_psi(_MIPD_ zzn2 *psi,ecn2 *P) { /* apply GLS morphism to P */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif MR_IN(212) zzn2_conj(_MIPP_ &(P->x),&(P->x)); zzn2_conj(_MIPP_ &(P->y),&(P->y)); if (P->marker==MR_EPOINT_GENERAL) zzn2_conj(_MIPP_ &(P->z),&(P->z)); zzn2_mul(_MIPP_ &(P->x),&psi[0],&(P->x)); MR_OUT } /* static void out_zzn2(zzn2 *x) { redc(x->a,x->a); redc(x->b,x->b); cotnum(x->a,stdout); cotnum(x->b,stdout); nres(x->a,x->a); nres(x->b,x->b); } */ /* find RHS=(x^2-B)/(x^2-A) */ void ecn2_rhs(_MIPD_ zzn2 *x,zzn2 *rhs) { /* calculate RHS of elliptic curve equation */ int 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->w8; A.b=mr_mip->w9; B.a=mr_mip->w10; B.b=mr_mip->w11; zzn2_from_zzn(mr_mip->A,&A); zzn2_from_zzn(mr_mip->B,&B); if (twist==MR_QUADRATIC) { /* quadratic twist */ zzn2_txx(_MIPP_ &A); zzn2_txx(_MIPP_ &B); } zzn2_sqr(_MIPP_ x,rhs); zzn2_sub(_MIPP_ rhs,&B,&B); zzn2_sub(_MIPP_ rhs,&A,&A); zzn2_inv(_MIPP_ &A); zzn2_mul(_MIPP_ &A,&B,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->w12; lhs.b=mr_mip->w13; rhs.a=mr_mip->w14; rhs.b=mr_mip->w15; ecn2_rhs(_MIPP_ x,&rhs); zzn2_sqr(_MIPP_ y,&lhs); if (!zzn2_compare(&lhs,&rhs)) { MR_OUT return FALSE; } zzn2_copy(x,&(e->x)); zzn2_copy(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_qr(_MIPP_ &rhs)) { MR_OUT return FALSE; } zzn2_sqrt(_MIPP_ &rhs,&rhs); } zzn2_copy(x,&(e->x)); zzn2_copy(&rhs,&(e->y)); e->marker=MR_EPOINT_NORMALIZED; MR_OUT return TRUE; } #endif void ecn2_setxyz(zzn2 *x,zzn2 *y,zzn2 *z,ecn2 *e) { zzn2_copy(x,&(e->x)); zzn2_copy(y,&(e->y)); zzn2_copy(z,&(e->z)); e->marker=MR_EPOINT_GENERAL; } /* Normalise an array of points of length mERNUM) return FALSE; if (m>MR_MAX_M_T_S) return FALSE; MR_IN(215) one.a=mr_mip->w12; one.b=mr_mip->w13; zzn2_from_zzn(mr_mip->one,&one); for (i=0;ione,&(p[i].z)); } MR_OUT return TRUE; } BOOL ecn2_add(_MIPD_ ecn2 *Q,ecn2 *P) { /* P+=Q */ BOOL Doubling=FALSE; int twist; zzn2 t2,t3,t4; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif t2.a = mr_mip->w8; t2.b = mr_mip->w9; t3.a = mr_mip->w10; t3.b = mr_mip->w11; t4.a = mr_mip->w12; t4.b = mr_mip->w13; 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; if (Q==P) { Doubling=TRUE; if (P->marker==MR_EPOINT_INFINITY) { /* 2 times infinity == infinity ! */ return Doubling; } } MR_IN(205) if (!Doubling) { /* Addition */ zzn2_add(_MIPP_ &(Q->x),&(Q->y),&t2); zzn2_add(_MIPP_ &(P->x),&(P->y),&t4); zzn2_mul(_MIPP_ &t4,&t2,&t4); /* I = t4 = (x1+y1)(x2+y2) */ if (Q->marker!=MR_EPOINT_NORMALIZED) { if (P->marker==MR_EPOINT_NORMALIZED) zzn2_copy(&(Q->z),&(P->z)); else zzn2_mul(_MIPP_ &(Q->z),&(P->z),&(P->z)); /* Z = z1*z2 */ } else { if (P->marker==MR_EPOINT_NORMALIZED) zzn2_from_zzn(mr_mip->one,&(P->z)); } zzn2_sqr(_MIPP_ &(P->z),&t2); /* P->z = z1.z2 */ if (mr_abs(mr_mip->Bsize)==MR_TOOBIG) zzn2_smul(_MIPP_ &t2,mr_mip->B,&t2); else zzn2_imul(_MIPP_ &t2,mr_mip->Bsize,&t2); if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &t2); /* B = t2 = d*A^2 */ zzn2_mul(_MIPP_ &(P->x),&(Q->x),&(P->x)); /* X = x1*x2 */ zzn2_mul(_MIPP_ &(P->y),&(Q->y),&(P->y)); /* Y = y1*y2 */ zzn2_sub(_MIPP_ &t4,&(P->x),&t4); zzn2_sub(_MIPP_ &t4,&(P->y),&t4); /* I = (x1+y1)(x2+y2)-X-Y */ zzn2_mul(_MIPP_ &(P->x),&(P->y),&t3); /* E = t3 = X*Y */ if (mr_abs(mr_mip->Asize)==MR_TOOBIG) zzn2_smul(_MIPP_ &(P->y),mr_mip->A,&(P->y)); else zzn2_imul(_MIPP_ &(P->y),mr_mip->Asize,&(P->y)); if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &(P->y)); /* Y=aY */ zzn2_sub(_MIPP_ &(P->x),&(P->y),&(P->x)); /* X=X-aY */ zzn2_mul(_MIPP_ &(P->z),&(P->x),&(P->z)); zzn2_mul(_MIPP_ &(P->z),&t4,&(P->z)); zzn2_sub(_MIPP_ &t3,&t2,&(P->y)); zzn2_mul(_MIPP_ &(P->y),&t4,&(P->y)); zzn2_add(_MIPP_ &t3,&t2,&t4); zzn2_mul(_MIPP_ &(P->x),&t4,&(P->x)); } else { /* doubling */ zzn2_add(_MIPP_ &(P->x),&(P->y),&t2); zzn2_sqr(_MIPP_ &t2,&t2); zzn2_sqr(_MIPP_ &(P->x),&(P->x)); zzn2_sqr(_MIPP_ &(P->y),&(P->y)); zzn2_sub(_MIPP_ &t2,&(P->x),&t2); zzn2_sub(_MIPP_ &t2,&(P->y),&t2); /* E=(X+Y)^2-X^2-Y^2 */ if (P->marker!=MR_EPOINT_NORMALIZED) zzn2_sqr(_MIPP_ &(P->z),&(P->z)); else zzn2_from_zzn(mr_mip->one,&(P->z)); zzn2_add(_MIPP_ &(P->z),&(P->z),&(P->z)); if (mr_abs(mr_mip->Bsize)==MR_TOOBIG) zzn2_smul(_MIPP_ &(P->z),mr_mip->B,&(P->z)); else zzn2_imul(_MIPP_ &(P->z),mr_mip->Bsize,&(P->z)); if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &(P->z)); if (mr_abs(mr_mip->Asize)==MR_TOOBIG) zzn2_smul(_MIPP_ &(P->y),mr_mip->A,&(P->y)); else zzn2_imul(_MIPP_ &(P->y),mr_mip->Asize,&(P->y)); if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &(P->y)); zzn2_add(_MIPP_ &(P->x),&(P->y),&t3); zzn2_sub(_MIPP_ &(P->x),&(P->y),&t4); zzn2_mul(_MIPP_ &t3,&t4,&(P->x)); zzn2_sub(_MIPP_ &t3,&(P->z),&t3); zzn2_mul(_MIPP_ &t2,&t3,&(P->y)); zzn2_mul(_MIPP_ &t2,&t4,&(P->z)); } if (zzn2_iszero(&(P->z))) { zzn2_from_zzn(mr_mip->one,&(P->x)); zzn2_zero(&(P->y)); P->marker=MR_EPOINT_INFINITY; } else P->marker=MR_EPOINT_GENERAL; MR_OUT return Doubling; } void ecn2_negate(_MIPD_ ecn2 *u,ecn2 *w) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif ecn2_copy(u,w); if (w->marker!=MR_EPOINT_INFINITY) zzn2_negate(_MIPP_ &(w->x),&(w->x)); } BOOL ecn2_sub(_MIPD_ ecn2 *Q,ecn2 *P) { BOOL Doubling; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zzn2 lam; lam.a = mr_mip->w14; lam.b = mr_mip->w15; ecn2_negate(_MIPP_ Q,Q); Doubling=ecn2_add(_MIPP_ Q,P); ecn2_negate(_MIPP_ Q,Q); return Doubling; } /* 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; PP->marker=MR_EPOINT_NORMALIZED; PM->marker=MR_EPOINT_NORMALIZED; return TRUE; } */ /* Precomputation of 3P, 5P, 7P etc. into PT. Assume PT[0] contains P */ #define MR_PRE_2 (6+2*MR_ECC_STORE_N2) static void ecn2_pre(_MIPD_ int sz,BOOL norm,ecn2 *PT) { int i,j; ecn2 P2; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifndef MR_STATIC zzn2 *work=(zzn2 *)mr_alloc(_MIPP_ sz,sizeof(zzn2)); char *mem = memalloc(_MIPP_ 6+2*sz); #else zzn2 work[MR_ECC_STORE_N2]; char mem[MR_BIG_RESERVE(MR_PRE_2)]; memset(mem, 0, MR_BIG_RESERVE(MR_PRE_2)); #endif j=0; P2.x.a=mirvar_mem(_MIPP_ mem, j++); P2.x.b=mirvar_mem(_MIPP_ mem, j++); P2.y.a=mirvar_mem(_MIPP_ mem, j++); P2.y.b=mirvar_mem(_MIPP_ mem, j++); P2.z.a=mirvar_mem(_MIPP_ mem, j++); P2.z.b=mirvar_mem(_MIPP_ mem, j++); for (i=0;i=1;) { if (mr_mip->user!=NULL) (*mr_mip->user)(); n=mr_naf_window(_MIPP_ k,h,i,&nbs,&nzs,MR_ECC_STORE_N2); 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_copy(&P1,&PS); ecn2_copy(&P1,&PD); ecn2_add(_MIPP_ &P2,&PS); ecn2_sub(_MIPP_ &P2,&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 precomputed store size, sza (=8?) and szb (=20?) 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 sza,int wb,int szb,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 nadds; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif 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) */ /* norm=TRUE if the table is to be normalised - which it should be */ /* if it is to be calculated off-line */ void ecn2_precomp_gls(_MIPD_ int sz,BOOL norm,ecn2 *P,zzn2 *psi,ecn2 *T) { int i,j; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif j=0; MR_IN(219) ecn2_norm(_MIPP_ P); ecn2_copy(P,&T[0]); ecn2_pre(_MIPP_ sz,norm,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_BEST); mr_mip->TWIST=MR_QUADRATIC; 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.z.a=mirvar(_MIPP_ 0); w.z.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].z.a=mirvar(_MIPP_ 0); table[0].z.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].z.a=mirvar(_MIPP_ 0); table[1].z.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[i].z.a); mr_free(table[i].z.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=MR_QUADRATIC; #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=MR_QUADRATIC; #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); w.z.a=mirvar_mem(_MIPP_ mem, 8); w.z.b=mirvar_mem(_MIPP_ mem, 9); 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 } #endif #ifndef MR_NO_ECC_MULTIADD void ecn2_mult4(_MIPD_ big *e,ecn2 *P,ecn2 *R) { /* R=e[0]*P[0]+e[1]*P[1]+ .... e[n-1]*P[n-1] */ int i,j,k,l,nb,ea,c; ecn2 G[16]; zzn2 work[16]; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifndef MR_STATIC char *mem=(char *)memalloc(_MIPP_ 120); #else char mem[MR_BIG_RESERVE(120)]; memset(mem, 0, MR_BIG_RESERVE(120)); #endif if (mr_mip->ERNUM) return; MR_IN(243) l=0; for (k=1;k<16;k++) { G[k].x.a=mirvar_mem(_MIPP_ mem, l++); G[k].x.b=mirvar_mem(_MIPP_ mem, l++); G[k].y.a=mirvar_mem(_MIPP_ mem, l++); G[k].y.b=mirvar_mem(_MIPP_ mem, l++); G[k].z.a=mirvar_mem(_MIPP_ mem, l++); G[k].z.b=mirvar_mem(_MIPP_ mem, l++); G[k].marker=MR_EPOINT_INFINITY; i=k; j=1; c=0; while (i>=(2*j)) {j*=2; c++;} if (i>j) ecn2_copy(&G[i-j],&G[k]); ecn2_add(_MIPP_ &P[c],&G[k]); } for (i=0;i<15;i++) { work[i].a=mirvar_mem(_MIPP_ mem, l++); work[i].b=mirvar_mem(_MIPP_ mem, l++); } ecn2_multi_norm(_MIPP_ 15,work,&G[1]); nb=0; for (j=0;j<4;j++) if ((k=logb2(_MIPP_ e[j])) > nb) nb=k; ecn2_zero(R); #ifndef MR_ALWAYS_BINARY if (mr_mip->base==mr_mip->base2) { #endif for (i=nb-1;i>=0;i--) { if (mr_mip->user!=NULL) (*mr_mip->user)(); ea=0; k=1; for (j=0;j<4;j++) { if (mr_testbit(_MIPP_ e[j],i)) ea+=k; k<<=1; } ecn2_add(_MIPP_ R,R); if (ea!=0) ecn2_add(_MIPP_ &G[ea],R); } #ifndef MR_ALWAYS_BINARY } else mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED); #endif #ifndef MR_STATIC memkill(_MIPP_ mem,120); #else memset(mem, 0, MR_BIG_RESERVE(120)); #endif MR_OUT } #ifndef MR_STATIC void ecn2_multn(_MIPD_ int n,big *e,ecn2 *P,ecn2 *R) { /* R=e[0]*P[0]+e[1]*P[1]+ .... e[n-1]*P[n-1] */ int i,j,k,l,nb,ea,c; int m=1<ERNUM) return; MR_IN(223) G= (ecn2 *)mr_alloc(_MIPP_ m,sizeof(ecn2)); work=(zzn2 *)mr_alloc(_MIPP_ m,sizeof(zzn2)); l=0; for (k=1;k=(2*j)) {j*=2; c++;} if (i>j) ecn2_copy(&G[i-j],&G[k]); ecn2_add(_MIPP_ &P[c],&G[k]); } for (i=0;i nb) nb=k; ecn2_zero(R); #ifndef MR_ALWAYS_BINARY if (mr_mip->base==mr_mip->base2) { #endif for (i=nb-1;i>=0;i--) { if (mr_mip->user!=NULL) (*mr_mip->user)(); ea=0; k=1; for (j=0;j