/*************************************************************************** * 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 routines for implementation of Elliptic Curve Cryptography over GF(2^m) * mrec2m.c * * Curve equation is Y^2 + XY = X^3 + A.X^2 + B * where A is 0 or 1 * * For algorithms used, see IEEE P1363 Standard, Appendix A * unless otherwise stated. * * New from version 5.1.1 - changed from IEEE to Lopez-Dahab coordinates * See "A note on Lopez-Dahab coordinates" - Tanja Lange (eprint archive) * (x,y,z) = (x/z,y/(z*z),1) * * For supersingular curves Ordinary Projective coordinates are used. * (x,y,z) = (x/z,y/z,1) * * READ COMMENTS CAREFULLY FOR VARIOUS OPTIMIZATION SUGGESTIONS * * No assembly language used. * * Space can be saved by removing unneeded functions and * deleting unrequired functionality */ #include #include "miracl.h" #ifdef MR_STATIC #include #endif #ifndef MR_NOFULLWIDTH /* This does not make sense using floating-point! */ /* Initialise with Trinomial or Pentanomial * * t^m + t^a + 1 OR t^m + t^a +t^b + t^c + 1 * * Set b=0 for pentanomial. a2 is usually 0 or 1 * * m negative indicates a super-singular curve */ BOOL ecurve2_init(_MIPD_ int m,int a,int b,int c,big a2,big a6,BOOL check,int type) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif /* catch some nonsense conditions */ if (mr_mip->ERNUM) return FALSE; #ifndef MR_NOKOBLITZ mr_mip->KOBLITZ=FALSE; #endif #ifndef MR_NO_SS mr_mip->SS=FALSE; if (m<0) { /* its a supersingular curve! */ mr_mip->SS=TRUE; /* type=MR_AFFINE; always AFFINE */ m=-m; if (size(a2)!=1) return FALSE; if (size(a6) >1) return FALSE; } #else if (m<0) return FALSE; #endif if (size(a2)<0) return FALSE; if (size(a6)<0) return FALSE; MR_IN(123) if (!prepare_basis(_MIPP_ m,a,b,c,check)) { /* unable to set the basis */ MR_OUT return FALSE; } mr_mip->Asize=size(a2); mr_mip->Bsize=size(a6); #ifndef MR_NOKOBLITZ #ifndef MR_NO_SS if (!mr_mip->SS && mr_mip->Bsize==1) #else if (mr_mip->Bsize==1) #endif { if (mr_mip->Asize==0 || mr_mip->Asize==1) { mr_mip->KOBLITZ=TRUE; } } #endif if (mr_mip->Asize==MR_TOOBIG) copy(a2,mr_mip->A); if (mr_mip->Bsize==MR_TOOBIG) copy(a6,mr_mip->B); #ifndef MR_AFFINE_ONLY if (type==MR_BEST) mr_mip->coord=MR_PROJECTIVE; else mr_mip->coord=type; #else if (type==MR_PROJECTIVE) mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED); #endif MR_OUT return TRUE; } BOOL epoint2_set(_MIPD_ big x,big y,int cb,epoint *p) { /* initialise a point on active ecurve * * if x or y == NULL, set to point at infinity * * if x==y, a y co-ordinate is calculated - if * * possible - and cb suggests LSB 0/1 of y/x * * (which "decompresses" y). Otherwise, check * * validity of given (x,y) point, ignoring cb. * * Returns TRUE for valid point, otherwise FALSE. */ BOOL valid; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return FALSE; MR_IN(125) if (x==NULL || y==NULL) { convert(_MIPP_ 1,p->X); convert(_MIPP_ 1,p->Y); p->marker=MR_EPOINT_INFINITY; MR_OUT return TRUE; } valid=FALSE; #ifndef MR_NO_SS if (mr_mip->SS) { /* Super-singular - calculate x^3+x+B */ copy (x,p->X); modsquare2(_MIPP_ p->X,mr_mip->w5); /* w5=x^2 */ modmult2(_MIPP_ mr_mip->w5,p->X,mr_mip->w5); /* w5=x^3 */ add2(mr_mip->w5,p->X,mr_mip->w5); incr2(mr_mip->w5,mr_mip->Bsize,mr_mip->w5); /* w5=x^3+x+B */ if (x!=y) { /* compare with y^2+y */ copy(y,p->Y); modsquare2(_MIPP_ p->Y,mr_mip->w1); add2(mr_mip->w1,p->Y,mr_mip->w1); if (mr_compare(mr_mip->w1,mr_mip->w5)==0) valid=TRUE; } else { /* no y supplied - calculate one. Solve quadratic */ valid=quad2(_MIPP_ mr_mip->w5,mr_mip->w5); incr2(mr_mip->w5,cb^parity2(mr_mip->w5),p->Y); } } else { /* calculate x^3+Ax^2+B */ #endif copy(x,p->X); modsquare2(_MIPP_ p->X,mr_mip->w6); /* w6=x^2 */ modmult2(_MIPP_ mr_mip->w6,p->X,mr_mip->w5); /* w5=x^3 */ if (mr_mip->Asize==MR_TOOBIG) copy(mr_mip->A,mr_mip->w1); else convert(_MIPP_ mr_mip->Asize,mr_mip->w1); modmult2(_MIPP_ mr_mip->w6,mr_mip->w1,mr_mip->w0); add2(mr_mip->w5,mr_mip->w0,mr_mip->w5); if (mr_mip->Bsize==MR_TOOBIG) add2(mr_mip->w5,mr_mip->B,mr_mip->w5); /* w5=x^3+Ax^2+B */ else incr2(mr_mip->w5,mr_mip->Bsize,mr_mip->w5); if (x!=y) { /* compare with y^2+xy */ copy(y,p->Y); modsquare2(_MIPP_ p->Y,mr_mip->w2); modmult2(_MIPP_ p->Y,p->X,mr_mip->w1); add2(mr_mip->w1,mr_mip->w2,mr_mip->w1); if (mr_compare(mr_mip->w1,mr_mip->w5)==0) valid=TRUE; } else { /* no y supplied - calculate one. Solve quadratic */ if (size(p->X)==0) { if (mr_mip->Bsize==MR_TOOBIG) copy(mr_mip->B,mr_mip->w1); else convert(_MIPP_ mr_mip->Bsize,mr_mip->w1); sqroot2(_MIPP_ mr_mip->w1,p->Y); valid=TRUE; } else { inverse2(_MIPP_ mr_mip->w6,mr_mip->w6); /* 1/x^2 */ modmult2(_MIPP_ mr_mip->w5,mr_mip->w6,mr_mip->w5); valid=quad2(_MIPP_ mr_mip->w5,mr_mip->w5); incr2(mr_mip->w5,cb^parity2(mr_mip->w5),mr_mip->w5); modmult2(_MIPP_ mr_mip->w5,p->X,p->Y); } } #ifndef MR_NO_SS } #endif if (valid) { p->marker=MR_EPOINT_NORMALIZED; MR_OUT return TRUE; } MR_OUT return FALSE; } BOOL epoint2_norm(_MIPD_ epoint *p) { /* normalise a point */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) return TRUE; if (p->marker!=MR_EPOINT_GENERAL) return TRUE; if (mr_mip->ERNUM) return FALSE; MR_IN(126) if (!inverse2(_MIPP_ p->Z,mr_mip->w8)) { MR_OUT return FALSE; } #ifndef MR_NO_SS if (mr_mip->SS) { modmult2(_MIPP_ p->X,mr_mip->w8,p->X); modmult2(_MIPP_ p->Y,mr_mip->w8,p->Y); } else { #endif modmult2(_MIPP_ p->X,mr_mip->w8,p->X); /* X/Z */ modsquare2(_MIPP_ mr_mip->w8,mr_mip->w8); /* 1/ZZ */ modmult2(_MIPP_ p->Y,mr_mip->w8,p->Y); /* Y/ZZ */ #ifndef MR_NO_SS } #endif convert(_MIPP_ 1,p->Z); p->marker=MR_EPOINT_NORMALIZED; MR_OUT #endif return TRUE; } #ifndef MR_STATIC void epoint2_getxyz(_MIPD_ epoint* p,big x,big y,big z) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif convert(_MIPP_ 1,mr_mip->w1); if (p->marker==MR_EPOINT_INFINITY) { #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { /* (0,0) = O */ #endif if (x!=NULL) zero(x); if (y!=NULL) zero(y); #ifndef MR_AFFINE_ONLY } if (mr_mip->coord==MR_PROJECTIVE) { /* (1,1,0) = O */ if (x!=NULL) copy(mr_mip->w1,x); if (y!=NULL) copy(mr_mip->w1,y); } #endif if (z!=NULL) zero(z); return; } if (x!=NULL) copy(p->X,x); if (y!=NULL) copy(p->Y,y); #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { #endif if (z!=NULL) zero(z); #ifndef MR_AFFINE_ONLY } if (mr_mip->coord==MR_PROJECTIVE) { if (z!=NULL) { if (p->marker!=MR_EPOINT_GENERAL) copy(mr_mip->w1,z); else copy(p->Z,z); } } #endif return; } #endif int epoint2_get(_MIPD_ epoint* p,big x,big y) { /* Get point co-ordinates in affine, normal form * * (converted from projective form). If x==y, supplies * * x only. Return value is LSB of y/x (useful for * * point compression) */ int lsb; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (p->marker==MR_EPOINT_INFINITY) { zero(x); zero(y); return 0; } if (mr_mip->ERNUM) return 0; MR_IN(127) epoint2_norm(_MIPP_ p); copy(p->X,x); copy(p->Y,mr_mip->w5); if (x!=y) copy(mr_mip->w5,y); if (size(x)==0) { MR_OUT return 0; } #ifndef MR_NO_SS if (mr_mip->SS) { lsb=parity2(p->Y); } else { #endif inverse2(_MIPP_ x,mr_mip->w5); modmult2(_MIPP_ mr_mip->w5,p->Y,mr_mip->w5); lsb=parity2(mr_mip->w5); #ifndef MR_NO_SS } #endif MR_OUT return lsb; } void ecurve2_double(_MIPD_ epoint *p) { /* double epoint on active curve */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (p->marker==MR_EPOINT_INFINITY) { /* 2 times infinity == infinity! */ return; } #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { #endif #ifndef MR_NO_SS if (mr_mip->SS) { /* super-singular */ modsquare2(_MIPP_ p->X,p->X); incr2(p->X,1,mr_mip->w8); modsquare2(_MIPP_ p->X,p->X); modsquare2(_MIPP_ p->Y,p->Y); modsquare2(_MIPP_ p->Y,p->Y); add2(p->Y,p->X,p->Y); /* y=x^4+y^4 */ incr2(p->X,1,p->X); /* x=x^4+1 */ return; } #endif if (size(p->X)==0) { /* set to point at infinity */ epoint2_set(_MIPP_ NULL,NULL,0,p); return; } inverse2(_MIPP_ p->X,mr_mip->w8); modmult2(_MIPP_ mr_mip->w8,p->Y,mr_mip->w8); add2(mr_mip->w8,p->X,mr_mip->w8); /* w8 is slope m */ modsquare2(_MIPP_ mr_mip->w8,mr_mip->w6); /* w6 =m^2 */ add2(mr_mip->w6,mr_mip->w8,mr_mip->w1); if (mr_mip->Asize==MR_TOOBIG) add2(mr_mip->w1,mr_mip->A,mr_mip->w1); else incr2(mr_mip->w1,mr_mip->Asize,mr_mip->w1); /* w1 = x3 */ add2(p->X,mr_mip->w1,mr_mip->w6); modmult2(_MIPP_ mr_mip->w6,mr_mip->w8,mr_mip->w6); copy(mr_mip->w1,p->X); add2(mr_mip->w6,mr_mip->w1,mr_mip->w6); add2(p->Y,mr_mip->w6,p->Y); return; #ifndef MR_AFFINE_ONLY } #ifndef MR_NO_SS if (mr_mip->SS) { /* super-singular */ modsquare2(_MIPP_ p->X,p->X); modsquare2(_MIPP_ p->X,p->X); modsquare2(_MIPP_ p->Y,p->Y); modsquare2(_MIPP_ p->Y,p->Y); if (p->marker!=MR_EPOINT_NORMALIZED) { modsquare2(_MIPP_ p->Z,p->Z); modsquare2(_MIPP_ p->Z,p->Z); /* z^4 */ add2(p->Y,p->X,p->Y); /* y^4+x^4 */ add2(p->X,p->Z,p->X); /* z^4+z^4 */ } else { add2(p->Y,p->X,p->Y); incr2(p->X,1,p->X); } return; } #endif if (size(p->X)==0) { /* set to infinity */ epoint2_set(_MIPP_ NULL,NULL,0,p); return; } modsquare2(_MIPP_ p->X,mr_mip->w1); /* S=X^2 */ add2(p->Y,mr_mip->w1,p->Y); /* U=S+Y */ if (p->marker!=MR_EPOINT_NORMALIZED) { modmult2(_MIPP_ p->X,p->Z,mr_mip->w4); /* T=X*Z */ modsquare2(_MIPP_ mr_mip->w4,p->Z); /* Z=T*T */ } else { copy(p->X,mr_mip->w4); copy(mr_mip->w1,p->Z); } modmult2(_MIPP_ mr_mip->w4,p->Y,mr_mip->w4); /* T=U*T */ modsquare2(_MIPP_ p->Y,p->Y); /* U*U */ add2(p->Y,mr_mip->w4,p->X); /* U*U+T */ if (mr_mip->Asize>0) /* X=U*U+T+AZ */ { if (mr_mip->Asize>1) { if (mr_mip->Asize==MR_TOOBIG) copy(mr_mip->A,p->Y); else convert(_MIPP_ mr_mip->Asize,p->Y); modmult2(_MIPP_ p->Y,p->Z,p->Y); add2(p->X,p->Y,p->X); } else add2(p->X,p->Z,p->X); } add2(mr_mip->w4,p->Z,mr_mip->w4); /* Z+T */ modmult2(_MIPP_ p->X,mr_mip->w4,p->Y); modsquare2(_MIPP_ mr_mip->w1,mr_mip->w1); /* S*S */ modmult2(_MIPP_ mr_mip->w1,p->Z,mr_mip->w1); add2(p->Y,mr_mip->w1,p->Y); p->marker=MR_EPOINT_GENERAL; #endif } static BOOL ecurve2_padd(_MIPD_ epoint *p,epoint *pa) { /* primitive add two epoints on the active ecurve pa+=p * * note that if p is normalized, its Z coordinate isn't used */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { #endif add2(p->Y,pa->Y,mr_mip->w8); add2(p->X,pa->X,mr_mip->w6); if (size(mr_mip->w6)==0) { /* divide by zero */ if (size(mr_mip->w8)==0) { /* should have doubled! */ return FALSE; } else { /* point at infinity */ epoint2_set(_MIPP_ NULL,NULL,0,pa); return TRUE; } } inverse2(_MIPP_ mr_mip->w6,mr_mip->w5); modmult2(_MIPP_ mr_mip->w8,mr_mip->w5,mr_mip->w8); /* w8=m */ modsquare2(_MIPP_ mr_mip->w8,mr_mip->w5); /* m^2 */ #ifndef MR_NO_SS if (mr_mip->SS) { add2(pa->X,p->X,pa->X); add2(pa->X,mr_mip->w5,pa->X); add2(pa->X,p->X,pa->Y); modmult2(_MIPP_ pa->Y,mr_mip->w8,pa->Y); add2(pa->Y,p->Y,pa->Y); incr2(pa->Y,1,pa->Y); } else { #endif add2(mr_mip->w5,mr_mip->w8,mr_mip->w5); add2(mr_mip->w5,mr_mip->w6,mr_mip->w5); if (mr_mip->Asize==MR_TOOBIG) add2(mr_mip->w5,mr_mip->A,mr_mip->w5); else incr2(mr_mip->w5,mr_mip->Asize,mr_mip->w5); /* w5=x3 */ add2(pa->X,mr_mip->w5,mr_mip->w6); modmult2(_MIPP_ mr_mip->w6,mr_mip->w8,mr_mip->w6); copy(mr_mip->w5,pa->X); add2(mr_mip->w6,mr_mip->w5,mr_mip->w6); add2(pa->Y,mr_mip->w6,pa->Y); #ifndef MR_NO_SS } #endif pa->marker=MR_EPOINT_NORMALIZED; return TRUE; #ifndef MR_AFFINE_ONLY } #ifndef MR_NO_SS if (mr_mip->SS) { /* pa+=p */ if (p->marker!=MR_EPOINT_NORMALIZED) { modmult2(_MIPP_ pa->Y,p->Z,mr_mip->w4); /* w4=y1.z2 */ modmult2(_MIPP_ pa->X,p->Z,mr_mip->w1); /* w1=x1.z2 */ if (pa->marker==MR_EPOINT_NORMALIZED) copy(p->Z,mr_mip->w2); else modmult2(_MIPP_ pa->Z,p->Z,mr_mip->w2); /* w2=z1.z2 */ } else { if (pa->marker==MR_EPOINT_NORMALIZED) convert(_MIPP_ 1,mr_mip->w2); else copy(pa->Z,mr_mip->w2); copy(pa->Y,mr_mip->w4); copy(pa->X,mr_mip->w1); } if (pa->marker!=MR_EPOINT_NORMALIZED) { modmult2(_MIPP_ p->Y,pa->Z,mr_mip->w8); /* w8=y2.z1 */ modmult2(_MIPP_ p->X,pa->Z,mr_mip->w5); /* w5=x2.z1 */ } else { copy(p->Y,mr_mip->w8); copy(p->X,mr_mip->w5); } add2(mr_mip->w4,mr_mip->w8,mr_mip->w8); /* A=y2.z1+y1.z2 */ add2(mr_mip->w1,mr_mip->w5,mr_mip->w1); /* B=x2.z1+x1.z2 */ if (size(mr_mip->w1)==0) { if (mr_compare(mr_mip->w2,mr_mip->w8)==0) { /* point at infinity */ epoint2_set(_MIPP_ NULL,NULL,0,pa); return TRUE; } else return FALSE; /* should have doubled */ } /* if (size(mr_mip->w8)==0) { if (size(mr_mip->w1)==0) { return FALSE; } else { epoint2_set(_MIPP_ NULL,NULL,0,pa); return TRUE; } } */ modsquare2(_MIPP_ mr_mip->w1,pa->X); /* X=B^2 */ modmult2(_MIPP_ pa->X,mr_mip->w1,pa->Z); /* Z=B^3 */ modmult2(_MIPP_ pa->X,mr_mip->w5,pa->Y); /* Y=x2.z1.B^2 */ modsquare2(_MIPP_ mr_mip->w8,mr_mip->w3); /* w3=A^2 */ modmult2(_MIPP_ mr_mip->w3,mr_mip->w2,mr_mip->w5); /* w5=A^2.z1.z2 */ add2(pa->Y,mr_mip->w5,pa->Y); /* Y=x2.z1.B^2 + A^2.z1.z2 */ modmult2(_MIPP_ pa->Y,mr_mip->w8,pa->Y); /* Y=A.Y */ modsquare2(_MIPP_ pa->X,pa->X); /* X=B^4 */ modmult2(_MIPP_ mr_mip->w1,mr_mip->w5,mr_mip->w8); /* w8=B*w5 */ add2(pa->X,mr_mip->w8,pa->X); /* X finished */ modmult2(_MIPP_ mr_mip->w4,pa->Z,mr_mip->w1); /* B^3.y1.z2 */ add2(pa->Y,mr_mip->w1,pa->Y); modmult2(_MIPP_ pa->Z,mr_mip->w2,pa->Z); add2(pa->Y,pa->Z,pa->Y); pa->marker=MR_EPOINT_GENERAL; return TRUE; } #endif if (p->marker!=MR_EPOINT_NORMALIZED) { if (pa->marker!=MR_EPOINT_NORMALIZED) modmult2(_MIPP_ p->X,pa->Z,mr_mip->w1); /* A1=x1.z2 =w1 */ else copy(p->X,mr_mip->w1); modmult2(_MIPP_ pa->X,p->Z,pa->X); /* A2=x2.z1 =X3 */ add2(mr_mip->w1,pa->X,mr_mip->w2); /* C= A1+A2 =w2 */ modsquare2(_MIPP_ mr_mip->w1,mr_mip->w3); /* B1=A1*A1 =w3 */ modsquare2(_MIPP_ pa->X,mr_mip->w4); /* B2=A2*A2 =w4 */ add2(mr_mip->w3,mr_mip->w4,mr_mip->w5); /* D=B1+B2 =w5 */ if (pa->marker!=MR_EPOINT_NORMALIZED) { modsquare2(_MIPP_ pa->Z,mr_mip->w6); modmult2(_MIPP_ mr_mip->w6,p->Y,mr_mip->w6); /* E1=y1.z2^2 = w6 */ } else copy(p->Y,mr_mip->w6); modsquare2(_MIPP_ p->Z,mr_mip->w8); modmult2(_MIPP_ mr_mip->w8,pa->Y,mr_mip->w8); /* E2=y2.z1^2 = w8 */ add2(mr_mip->w3,mr_mip->w6,mr_mip->w3); /* E1+B1 = w3 */ add2(mr_mip->w4,mr_mip->w8,mr_mip->w4); /* E2+B2 = w4 */ add2(mr_mip->w8,mr_mip->w6,mr_mip->w8); /* F=E1+E2 */ if (size(mr_mip->w2)==0) { if (size(mr_mip->w8)==0) { /* should have doubled */ return FALSE; } else { epoint2_set(_MIPP_ NULL,NULL,0,pa); return TRUE; } } modmult2(_MIPP_ mr_mip->w8,mr_mip->w2,mr_mip->w8); /* G=CF */ if (pa->marker!=MR_EPOINT_NORMALIZED) modmult2(_MIPP_ pa->Z,p->Z,pa->Z); else copy(p->Z,pa->Z); modmult2(_MIPP_ pa->Z,mr_mip->w5,pa->Z); /* Z3=z1.z2.D */ modmult2(_MIPP_ mr_mip->w1,mr_mip->w4,mr_mip->w2); modmult2(_MIPP_ pa->X,mr_mip->w3,pa->X); add2(pa->X,mr_mip->w2,pa->X); /* x3 = A1(E2+B2)+A2(E1+B1) */ modmult2(_MIPP_ mr_mip->w1,mr_mip->w8,mr_mip->w1); /* A1*G */ modmult2(_MIPP_ mr_mip->w6,mr_mip->w5,mr_mip->w6); /* E1*D */ add2(mr_mip->w1,mr_mip->w6,pa->Y); modmult2(_MIPP_ pa->Y,mr_mip->w5,pa->Y); add2(mr_mip->w8,pa->Z,mr_mip->w8); modmult2(_MIPP_ mr_mip->w8,pa->X,mr_mip->w8); add2(pa->Y,mr_mip->w8,pa->Y); } else { if (pa->marker!=MR_EPOINT_NORMALIZED) { modsquare2(_MIPP_ pa->Z,mr_mip->w1); modmult2(_MIPP_ mr_mip->w1,p->Y,mr_mip->w1); add2(mr_mip->w1,pa->Y,mr_mip->w1); /* U=z2^2.y1 + y2 */ modmult2(_MIPP_ pa->Z,p->X,mr_mip->w2); add2(mr_mip->w2,pa->X,mr_mip->w2); /* S=z2x1+x2 */ } else { add2(p->Y,pa->Y,mr_mip->w1); add2(p->X,pa->X,mr_mip->w2); } if (size(mr_mip->w2)==0) { if (size(mr_mip->w1)==0) { /* should have doubled! */ return FALSE; } else { epoint2_set(_MIPP_ NULL,NULL,0,pa); return TRUE; } } if (pa->marker!=MR_EPOINT_NORMALIZED) modmult2(_MIPP_ pa->Z,mr_mip->w2,mr_mip->w3); /* T=z2.S */ else copy(mr_mip->w2,mr_mip->w3); modsquare2(_MIPP_ mr_mip->w3,pa->Z); /* z3=T^2 */ modmult2(_MIPP_ pa->Z,p->X,mr_mip->w4); /* V=z3.x1 */ add2(p->X,p->Y,mr_mip->w5); /* C=x1+y1 */ modsquare2(_MIPP_ mr_mip->w1,pa->X); modsquare2(_MIPP_ mr_mip->w2,mr_mip->w2); /* S^2 */ add2(mr_mip->w2,mr_mip->w1,mr_mip->w2); if (mr_mip->Asize>0) /* T(U+S^2+BT) */ { if (mr_mip->Asize>1) { if (mr_mip->Asize==MR_TOOBIG) copy(mr_mip->A,mr_mip->w6); else convert(_MIPP_ mr_mip->Asize,mr_mip->w6); modmult2(_MIPP_ mr_mip->w6,mr_mip->w3,mr_mip->w6); add2(mr_mip->w2,mr_mip->w6,mr_mip->w2); } else add2(mr_mip->w2,mr_mip->w3,mr_mip->w2); } modmult2(_MIPP_ mr_mip->w2,mr_mip->w3,mr_mip->w2); add2(pa->X,mr_mip->w2,pa->X); add2(mr_mip->w4,pa->X,mr_mip->w4); /* V+X */ modmult2(_MIPP_ mr_mip->w3,mr_mip->w1,mr_mip->w3); /* T*U */ add2(pa->Z,mr_mip->w3,pa->Y); /* Z3+T*U */ modmult2(_MIPP_ pa->Y,mr_mip->w4,pa->Y); modsquare2(_MIPP_ pa->Z,mr_mip->w1); modmult2(_MIPP_ mr_mip->w1,mr_mip->w5,mr_mip->w1); /*z3^2.C */ add2(pa->Y,mr_mip->w1,pa->Y); } pa->marker=MR_EPOINT_GENERAL; return TRUE; #endif } void epoint2_copy(epoint *a,epoint *b) { if (a==b) return; copy(a->X,b->X); copy(a->Y,b->Y); #ifndef MR_AFFINE_ONLY if (a->marker==MR_EPOINT_GENERAL) copy(a->Z,b->Z); #endif b->marker=a->marker; return; } BOOL epoint2_comp(_MIPD_ epoint *a,epoint *b) { int ia,ib; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return FALSE; if (a==b) return TRUE; if (a->marker==MR_EPOINT_INFINITY) { if (b->marker==MR_EPOINT_INFINITY) return TRUE; else return FALSE; } if (b->marker==MR_EPOINT_INFINITY) return FALSE; MR_IN(128) ia=epoint2_get(_MIPP_ a,mr_mip->w9,mr_mip->w9); ib=epoint2_get(_MIPP_ b,mr_mip->w10,mr_mip->w10); MR_OUT if (ia==ib && mr_compare(mr_mip->w9,mr_mip->w10)==0) return TRUE; return FALSE; } big ecurve2_add(_MIPD_ epoint *p,epoint *pa) { /* pa=pa+p; */ /* An ephemeral pointer to the line slope is returned * * only if curve is super-singular */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return NULL; MR_IN(129) if (p==pa) { ecurve2_double(_MIPP_ pa); MR_OUT return mr_mip->w8; } if (pa->marker==MR_EPOINT_INFINITY) { epoint2_copy(p,pa); MR_OUT return NULL; } if (p->marker==MR_EPOINT_INFINITY) { MR_OUT return NULL; } if (!ecurve2_padd(_MIPP_ p,pa)) ecurve2_double(_MIPP_ pa); MR_OUT return mr_mip->w8; } void epoint2_negate(_MIPD_ epoint *p) { /* negate a point */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; if (p->marker==MR_EPOINT_INFINITY) return; MR_IN(130) #ifndef MR_AFFINE_ONLY if (p->marker==MR_EPOINT_GENERAL) { #ifndef MR_NO_SS if (mr_mip->SS) { add2(p->Y,p->Z,p->Y); } else { #endif modmult2(_MIPP_ p->X,p->Z,mr_mip->w1); add2(p->Y,mr_mip->w1,p->Y); #ifndef MR_NO_SS } #endif } else { #endif #ifndef MR_NO_SS if (mr_mip->SS) incr2(p->Y,1,p->Y); else #endif add2(p->Y,p->X,p->Y); #ifndef MR_AFFINE_ONLY } #endif MR_OUT } big ecurve2_sub(_MIPD_ epoint *p,epoint *pa) { big r; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return NULL; MR_IN(131) if (p==pa) { epoint2_set(_MIPP_ NULL,NULL,0,pa); MR_OUT return NULL; } if (p->marker==MR_EPOINT_INFINITY) { MR_OUT return NULL; } epoint2_negate(_MIPP_ p); r=ecurve2_add(_MIPP_ p,pa); epoint2_negate(_MIPP_ p); MR_OUT return r; } #ifndef MR_NO_ECC_MULTIADD #ifndef MR_STATIC void ecurve2_multi_add(_MIPD_ int m,epoint **x,epoint **w) { /* adds m points together simultaneously, w[i]+=x[i] */ int i,*flag; big *A,*B,*C; char *mem; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(132) #ifndef MR_NO_SS if (mr_mip->SS) { for (i=0;icoord==MR_AFFINE) { #endif A=(big *)mr_alloc(_MIPP_ m,sizeof(big)); B=(big *)mr_alloc(_MIPP_ m,sizeof(big)); C=(big *)mr_alloc(_MIPP_ m,sizeof(big)); flag=(int *)mr_alloc(_MIPP_ m,sizeof(int)); convert(_MIPP_ 1,mr_mip->w3); /* unity */ mem=(char *)memalloc(_MIPP_ 3*m); for (i=0;iX,w[i]->X)==0 && mr_compare(x[i]->Y,w[i]->Y)==0) { /* doubling */ if (x[i]->marker==MR_EPOINT_INFINITY || size(x[i]->Y)==0) { flag[i]=1; /* result is infinity */ copy(mr_mip->w3,B[i]); continue; } modsquare2(_MIPP_ x[i]->X,A[i]); add2(A[i],x[i]->Y,A[i]); copy(x[i]->X,B[i]); } else { if (x[i]->marker==MR_EPOINT_INFINITY) { flag[i]=2; /* w[i] unchanged */ copy(mr_mip->w3,B[i]); continue; } if (w[i]->marker==MR_EPOINT_INFINITY) { flag[i]=3; /* w[i]=x[i] */ copy(mr_mip->w3,B[i]); continue; } add2(x[i]->X,w[i]->X,B[i]); if (size(B[i])==0) { /* point at infinity */ flag[i]=1; /* result is infinity */ copy(mr_mip->w3,B[i]); continue; } add2(x[i]->Y,w[i]->Y,A[i]); } } multi_inverse2(_MIPP_ m,B,C); /* one inversion only */ for (i=0;iw8); modsquare2(_MIPP_ mr_mip->w8,mr_mip->w6); /* m^2 */ add2(mr_mip->w6,mr_mip->w8,mr_mip->w6); add2(mr_mip->w6,x[i]->X,mr_mip->w6); add2(mr_mip->w6,w[i]->X,mr_mip->w6); if (mr_mip->Asize==MR_TOOBIG) add2(mr_mip->w6,mr_mip->A,mr_mip->w6); else incr2(mr_mip->w6,mr_mip->Asize,mr_mip->w6); add2(w[i]->X,mr_mip->w6,mr_mip->w2); modmult2(_MIPP_ mr_mip->w2,mr_mip->w8,mr_mip->w2); add2(mr_mip->w2,mr_mip->w6,mr_mip->w2); add2(mr_mip->w2,w[i]->Y,w[i]->Y); copy(mr_mip->w6,w[i]->X); w[i]->marker=MR_EPOINT_NORMALIZED; } memkill(_MIPP_ mem,3*m); mr_free(flag); mr_free(C); mr_free(B); mr_free(A); #ifndef MR_AFFINE_ONLY } else { /* no speed-up for projective coordinates */ for (i=0;imarker==MR_EPOINT_INFINITY) return; modsquare2(_MIPP_ P->X,P->X); modsquare2(_MIPP_ P->Y,P->Y); #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_PROJECTIVE && P->marker==MR_EPOINT_GENERAL) modsquare2(_MIPP_ P->Z,P->Z); #endif } /* creates a tnaf from a+tau.b into tm[.] */ static int itnaf(int mu,int a,int b,signed char *tm) { int u,t,len=0; int r0=a; int r1=b; while (r0!=0 || r1!=0) { if ((r0%2)!=0) { t=(r0-2*r1)%4; if (t<0) t+=4; u=2-t; r0-=u; } else u=0; tm[len++]=u; t=r0; if (mu==1) r0=r1+r0/2; else r0=r1-r0/2; r1=-t/2; } return len; } /* Here we use the post-processing algorithm of Lutz and Hasan */ /* rather than the more well known Solinas method - see */ /* http://vlsi.uwaterloo.ca/~ahasan/web_papers/technical_reports/web_Hi_Per_ECC.pdf */ static int tnaf(_MIPD_ big e,big hp,big hn) { int n,u,t,i,j,len,mu,count; signed char tm[8]; BOOL wrapped=FALSE; int m,a; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifdef MR_STATIC signed char tn[MIRACL*MR_STATIC+8]; #else signed char *tn=(signed char *)mr_alloc(_MIPP_ mr_mip->M+8,1); #endif m=mr_mip->M; a=mr_mip->Asize; if (a==0) mu=-1; else mu=1; copy(e,mr_mip->w1); zero(mr_mip->w2); for (i=0;iw1)!=0 || size(mr_mip->w2)!=0) { if (remain(_MIPP_ mr_mip->w1,2)!=0) { premult(_MIPP_ mr_mip->w2,2,mr_mip->w3); subtract(_MIPP_ mr_mip->w1,mr_mip->w3,mr_mip->w3); t=remain(_MIPP_ mr_mip->w3,4); if (t<0) t+=4; u=2-t; decr(_MIPP_ mr_mip->w1,u,mr_mip->w1); tn[i]+=u; } subdiv(_MIPP_ mr_mip->w1,2,mr_mip->w3); if (mu>0) add(_MIPP_ mr_mip->w2,mr_mip->w3,mr_mip->w1); else subtract(_MIPP_ mr_mip->w2,mr_mip->w3,mr_mip->w1); negify(mr_mip->w3,mr_mip->w2); i++; if (i==m) { i=0; wrapped=TRUE; } } len=i; count=0; if (wrapped) forever { len=m; for (i=0;i=len) len=i+n; i++; } count++; if (count<3 && len>m) { for (i=m;iw3); add(_MIPP_ hp,mr_mip->w3,hp); } if (tn[i]==-1) { expb2(_MIPP_ i,mr_mip->w3); add(_MIPP_ hn,mr_mip->w3,hn); } tn[i]=0; } for (i=0;i<8;i++) tm[i]=0; #ifndef MR_STATIC mr_free(tn); #endif return len; } #endif BOOL epoint2_multi_norm(_MIPD_ int m,big *work,epoint **p) { /* Normalise an array of points of length m<20 - requires a workspace array of length m */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifndef MR_AFFINE_ONLY int i; big w[MR_MAX_M_T_S]; if (mr_mip->coord==MR_AFFINE) return TRUE; if (mr_mip->ERNUM) return FALSE; if (m>MR_MAX_M_T_S) return FALSE; MR_IN(192) for (i=0;imarker==MR_EPOINT_NORMALIZED) w[i]=mr_mip->one; else w[i]=p[i]->Z; } if (!multi_inverse2(_MIPP_ m,w,work)) { MR_OUT return FALSE; } for (i=0;ione,p[i]->Z); p[i]->marker=MR_EPOINT_NORMALIZED; #ifndef MR_NO_SS if (mr_mip->SS) { modmult2(_MIPP_ p[i]->X,work[i],p[i]->X); modmult2(_MIPP_ p[i]->Y,work[i],p[i]->Y); } else { #endif modmult2(_MIPP_ p[i]->X,work[i],p[i]->X); /* X/Z */ modmult2(_MIPP_ work[i],work[i],mr_mip->w1); modmult2(_MIPP_ p[i]->Y,mr_mip->w1,p[i]->Y); /* Y/ZZ */ #ifndef MR_NO_SS } #endif } MR_OUT #endif return TRUE; } static void table_init(_MIPD_ epoint *g,epoint **table) { /* A precomputation option for the multiplication of a */ /* fixed point, would be to precalculate and normalize */ /* this table */ int i,n,n3,nf,nb,t; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif #ifndef MR_NOKOBLITZ if (mr_mip->KOBLITZ) { epoint2_copy(g,table[0]); epoint2_copy(g,table[MR_ECC_STORE_2M-1]); frobenius(_MIPP_ table[MR_ECC_STORE_2M-1]); frobenius(_MIPP_ table[MR_ECC_STORE_2M-1]); nf=2; for (i=1;i1) { /* number of bits in n3 */ t>>=1; nb++; } while (nb>nf) { /* move to next power of tau */ frobenius(_MIPP_ table[MR_ECC_STORE_2M-1]); nf++; } n3-=(1<0) ecurve2_add(_MIPP_ table[n/2],table[i]); else ecurve2_sub(_MIPP_ table[(-n)/2],table[i]); } else { /* mostly mixed additions... */ if (n>0) epoint2_copy(table[n/2],table[i]); if (n<0) { epoint2_copy(table[(-n)/2],table[i]); epoint2_negate(_MIPP_ table[i]); } ecurve2_add(_MIPP_ table[MR_ECC_STORE_2M-1],table[i]); } } } else { #endif epoint2_copy(g,table[0]); epoint2_copy(g,table[MR_ECC_STORE_2M-1]); ecurve2_double(_MIPP_ table[MR_ECC_STORE_2M-1]); /* epoint2_norm(_MIPP_ table[MR_ECC_STORE_2M-1]); makes additions below faster */ for (i=1;iKOBLITZ) { tnaf(_MIPP_ e,hp,hn); } else { #endif copy(e,hn); premult(_MIPP_ hn,3,hp); subdiv(_MIPP_ hn,2,hn); subdiv(_MIPP_ hp,2,hp); #ifndef MR_NOKOBLITZ } #endif } void ecurve2_mult(_MIPD_ big e,epoint *pa,epoint *pt) { /* pt=e*pa; */ int i,j,n,nb,nbs,nzs; #ifndef MR_AFFINE_ONLY /* int coord; */ big work[MR_ECC_STORE_2M]; #endif epoint *table[MR_ECC_STORE_2M]; #ifdef MR_STATIC char mem[MR_ECP_RESERVE(MR_ECC_STORE_2M)]; /* char mem[MR_ECP_RESERVE_A(MR_ECC_STORE_2M)]; Reserve space for AFFINE (x,y) only */ #ifndef MR_AFFINE_ONLY char mem1[MR_BIG_RESERVE(MR_ECC_STORE_2M)]; #endif #else char *mem; #ifndef MR_AFFINE_ONLY char *mem1; #endif #endif #ifndef MR_ALWAYS_BINARY epoint *p; int ch,ce; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(133) if (size(e)==0) { /* multiplied by 0 */ epoint2_set(_MIPP_ NULL,NULL,0,pt); MR_OUT return; } epoint2_norm(_MIPP_ pa); epoint2_copy(pa,pt); copy(e,mr_mip->w9); if (size(mr_mip->w9)<0) { /* pt = -pt */ negify(mr_mip->w9,mr_mip->w9); epoint2_negate(_MIPP_ pt); } if (size(mr_mip->w9)==1) { MR_OUT return; } prepare_naf(_MIPP_ mr_mip->w9,mr_mip->w10,mr_mip->w9); if (size(mr_mip->w9)==0 && size(mr_mip->w10)==0) { /* multiplied by 0 */ epoint2_set(_MIPP_ NULL,NULL,0,pt); MR_OUT return; } #ifndef MR_STATIC #ifndef MR_ALWAYS_BINARY if (mr_mip->base==mr_mip->base2) { #endif #endif #ifdef MR_STATIC memset(mem,0,MR_ECP_RESERVE(MR_ECC_STORE_2M)); /* memset(mem,0,MR_ECP_RESERVE_A(MR_ECC_STORE_2M)); */ #ifndef MR_AFFINE_ONLY memset(mem1,0,MR_BIG_RESERVE(MR_ECC_STORE_2M)); #endif #else mem=(char *)ecp_memalloc(_MIPP_ MR_ECC_STORE_2M); #ifndef MR_AFFINE_ONLY mem1=(char *)memalloc(_MIPP_ MR_ECC_STORE_2M); #endif #endif for (i=0;i<=MR_ECC_STORE_2M-1;i++) { table[i]=epoint_init_mem(_MIPP_ mem,i); #ifndef MR_AFFINE_ONLY work[i]=mirvar_mem(_MIPP_ mem1,i); #endif } table_init(_MIPP_ pt,table); #ifndef MR_AFFINE_ONLY epoint2_multi_norm(_MIPP_ MR_ECC_STORE_2M,work,table); #endif nb=logb2(_MIPP_ mr_mip->w10); if ((n=logb2(_MIPP_ mr_mip->w9))>nb) { nb=n; epoint2_negate(_MIPP_ pt); } epoint2_set(_MIPP_ NULL,NULL,0,pt); for (i=nb-1;i>=0;) { /* add/subtract */ if (mr_mip->user!=NULL) (*mr_mip->user)(); n=mr_naf_window(_MIPP_ mr_mip->w9,mr_mip->w10,i,&nbs,&nzs,MR_ECC_STORE_2M); /* printf("n= %d nbs= %d nzs= %d \n",n,nbs,nzs); */ for (j=0;jKOBLITZ) frobenius(_MIPP_ pt); else #endif ecurve2_double(_MIPP_ pt); } if (n>0) ecurve2_add(_MIPP_ table[n/2],pt); if (n<0) ecurve2_sub(_MIPP_ table[(-n)/2],pt); i-=nbs; if (nzs) { for (j=0;jKOBLITZ) frobenius(_MIPP_ pt); else #endif ecurve2_double(_MIPP_ pt); } i-=nzs; } } /* #ifndef MR_AFFINE_ONLY coord=mr_mip->coord; switch to AFFINE coordinates mr_mip->coord=MR_AFFINE; #endif */ #ifdef MR_STATIC /* memset(mem,0,MR_ECP_RESERVE_A(MR_ECC_STORE_2M)); */ memset(mem,0,MR_ECP_RESERVE(MR_ECC_STORE_2M)); #else ecp_memkill(_MIPP_ mem,MR_ECC_STORE_2M); #endif #ifndef MR_AFFINE_ONLY memkill(_MIPP_ mem1,MR_ECC_STORE_2M); /* mr_mip->coord=coord; */ #endif #ifndef MR_STATIC #ifndef MR_ALWAYS_BINARY } else { mem=(char *)ecp_memalloc(_MIPP_ 1); p=epoint_init_mem(_MIPP_ mem,0); epoint2_copy(pt,p); expb2(_MIPP_ logb2(_MIPP_ mr_mip->w10)-1,mr_mip->w11); mr_psub(_MIPP_ mr_mip->w10,mr_mip->w11,mr_mip->w10); subdiv(_MIPP_ mr_mip->w11,2,mr_mip->w11); while (size(mr_mip->w11) > 0) { /* add/subtract method */ if (mr_mip->user!=NULL) (*mr_mip->user)(); ecurve2_double(_MIPP_ pt); ce=mr_compare(mr_mip->w9,mr_mip->w11); /* e(i)=1? */ ch=mr_compare(mr_mip->w10,mr_mip->w11); /* h(i)=1? */ if (ch>=0) { /* h(i)=1 */ if (ce<0) ecurve2_add(_MIPP_ p,pt); mr_psub(_MIPP_ mr_mip->w10,mr_mip->w11,mr_mip->w10); } if (ce>=0) { /* e(i)=1 */ if (ch<0) ecurve2_sub(_MIPP_ p,pt); mr_psub(_MIPP_ mr_mip->w9,mr_mip->w11,mr_mip->w9); } subdiv(_MIPP_ mr_mip->w11,2,mr_mip->w11); } ecp_memkill(_MIPP_ mem,1); } #endif #endif epoint2_norm(_MIPP_ pt); MR_OUT } #ifndef MR_NO_ECC_MULTIADD #ifndef MR_STATIC void ecurve2_multn(_MIPD_ int n,big *y,epoint **x,epoint *w) { /* pt=e[o]*p[0]+e[1]*p[1]+ .... e[n-1]*p[n-1] */ int i,j,k,m,nb,ea; epoint **G; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(134) m=1< nb) nb=k; epoint2_set(_MIPP_ NULL,NULL,0,w); /* w=0 */ #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;jw14; work[1]=mr_mip->w15; #endif if (mr_mip->ERNUM) return; MR_IN(135) if (size(e)==0) { ecurve2_mult(_MIPP_ ea,pa,pt); MR_OUT return; } #ifdef MR_STATIC memset(mem,0,MR_ECP_RESERVE(4)); #else mem=(char *)ecp_memalloc(_MIPP_ 4); #endif p2=epoint_init_mem(_MIPP_ mem,0); p1=epoint_init_mem(_MIPP_ mem,1); ps[0]=epoint_init_mem(_MIPP_ mem,2); ps[1]=epoint_init_mem(_MIPP_ mem,3); epoint2_norm(_MIPP_ pa); epoint2_copy(pa,p2); copy(ea,mr_mip->w9); if (size(mr_mip->w9)<0) { /* p2 = -p2 */ negify(mr_mip->w9,mr_mip->w9); epoint2_negate(_MIPP_ p2); } epoint2_norm(_MIPP_ p); epoint2_copy(p,p1); copy(e,mr_mip->w12); if (size(mr_mip->w12)<0) { /* p1= -p1 */ negify(mr_mip->w12,mr_mip->w12); epoint2_negate(_MIPP_ p1); } #ifdef MR_NOKOBLITZ mr_jsf(_MIPP_ mr_mip->w9,mr_mip->w12,mr_mip->w10,mr_mip->w9,mr_mip->w13,mr_mip->w12); #else if (mr_mip->KOBLITZ) { prepare_naf(_MIPP_ mr_mip->w9,mr_mip->w10,mr_mip->w9); prepare_naf(_MIPP_ mr_mip->w12,mr_mip->w13,mr_mip->w12); } else mr_jsf(_MIPP_ mr_mip->w9,mr_mip->w12,mr_mip->w10,mr_mip->w9,mr_mip->w13,mr_mip->w12); #endif nb=logb2(_MIPP_ mr_mip->w10); if ((n=logb2(_MIPP_ mr_mip->w13))>nb) nb=n; if ((n=logb2(_MIPP_ mr_mip->w9))>nb) nb=n; if ((n=logb2(_MIPP_ mr_mip->w12))>nb) nb=n; epoint2_set(_MIPP_ NULL,NULL,0,pt); /* pt=0 */ expb2(_MIPP_ nb-1,mr_mip->w11); epoint2_copy(p1,ps[0]); ecurve2_add(_MIPP_ p2,ps[0]); /* ps=p1+p2 */ epoint2_copy(p1,ps[1]); ecurve2_sub(_MIPP_ p2,ps[1]); /* pd=p1-p2 */ #ifndef MR_AFFINE_ONLY epoint2_multi_norm(_MIPP_ 2,work,ps); #endif while (size(mr_mip->w11) > 0) { /* add/subtract method */ if (mr_mip->user!=NULL) (*mr_mip->user)(); #ifndef MR_NOKOBLITZ if (mr_mip->KOBLITZ) frobenius(_MIPP_ pt); else #endif ecurve2_double(_MIPP_ pt); e1=h1=e2=h2=0; if (mr_compare(mr_mip->w9,mr_mip->w11)>=0) { /* e1(i)=1? */ e2=1; mr_psub(_MIPP_ mr_mip->w9,mr_mip->w11,mr_mip->w9); } if (mr_compare(mr_mip->w10,mr_mip->w11)>=0) { /* h1(i)=1? */ h2=1; mr_psub(_MIPP_ mr_mip->w10,mr_mip->w11,mr_mip->w10); } if (mr_compare(mr_mip->w12,mr_mip->w11)>=0) { /* e2(i)=1? */ e1=1; mr_psub(_MIPP_ mr_mip->w12,mr_mip->w11,mr_mip->w12); } if (mr_compare(mr_mip->w13,mr_mip->w11)>=0) { /* h2(i)=1? */ h1=1; mr_psub(_MIPP_ mr_mip->w13,mr_mip->w11,mr_mip->w13); } if (e1!=h1) { if (e2==h2) { if (h1==1) ecurve2_add(_MIPP_ p1,pt); else ecurve2_sub(_MIPP_ p1,pt); } else { if (h1==1) { if (h2==1) ecurve2_add(_MIPP_ ps[0],pt); else ecurve2_add(_MIPP_ ps[1],pt); } else { if (h2==1) ecurve2_sub(_MIPP_ ps[1],pt); else ecurve2_sub(_MIPP_ ps[0],pt); } } } else if (e2!=h2) { if (h2==1) ecurve2_add(_MIPP_ p2,pt); else ecurve2_sub(_MIPP_ p2,pt); } subdiv(_MIPP_ mr_mip->w11,2,mr_mip->w11); } ecp_memkill(_MIPP_ mem,4); MR_OUT } #endif /* Routines to implement comb method for fast * computation of x*G mod n, for fixed G and n, using precomputation. * * Elliptic curve over GF(2^m) version of mrebrick.c * * This idea can be used to substantially speed up certain phases * of the Elliptic Curve Digital Signature Standard (ECS) for example. * * See "Handbook of Applied Cryptography" */ #ifndef MR_STATIC BOOL ebrick2_init(_MIPD_ ebrick2 *B,big x,big y,big a2,big a6,int m,int a,int b,int c,int window,int nb) { /* (x,y) is the fixed base * * a2 and a6 the parameters of the curve * * m, a, b, c are the m in the 2^m modulus, and a,b,c * * are the parameters of the irreducible bases, * * trinomial if b!=0, otherwise pentanomial * * window is the window size in bits and * * nb is the maximum number of bits in the multiplier */ int i,j,k,t,bp,len,bptr,is; epoint **table; epoint *w; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (nb<2 || window<1 || window>nb || mr_mip->ERNUM) return FALSE; t=MR_ROUNDUP(nb,window); if (t<2) return FALSE; MR_IN(136) #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=(epoint **)mr_alloc(_MIPP_ (1<a6=mirvar(_MIPP_ 0); copy(a6,B->a6); B->a2=mirvar(_MIPP_ 0); copy(a2,B->a2); B->m=m; B->a=a; B->b=b; B->c=c; if (!ecurve2_init(_MIPP_ m,a,b,c,a2,a6,TRUE,MR_AFFINE)) { MR_OUT return FALSE; } if (m<0) m=-m; /* if it is supersingular */ w=epoint_init(_MIPPO_ ); epoint2_set(_MIPP_ x,y,0,w); table[0]=epoint_init(_MIPPO_ ); table[1]=epoint_init(_MIPPO_ ); epoint2_copy(w,table[1]); for (j=0;jtable=(mr_small *)mr_alloc(_MIPP_ 2*len*(1<table[bptr++]=table[i]->X->w[j]; for (j=0;jtable[bptr++]=table[i]->Y->w[j]; epoint_free(table[i]); } mr_free(table); MR_OUT return TRUE; } void ebrick2_end(ebrick2 *B) { mirkill(B->a2); mirkill(B->a6); mr_free(B->table); } #else /* use precomputated table in ROM - use romaker2.c to create the table, and ecdh2m*.c for an example of use */ void ebrick2_init(ebrick2 *B,const mr_small* rom,big a2,big a6,int m,int a,int b,int c,int window,int nb) { B->table=rom; B->a2=a2; /* just pass a pointer */ B->a6=a6; B->m=m; B->a=a; B->b=b; B->c=c; B->window=window; /* 2^4=16 stored values */ B->max=nb; } #endif int mul2_brick(_MIPD_ ebrick2 *B,big e,big x,big y) { int i,j,t,d,m,len,maxsize,promptr; epoint *w,*z; #ifdef MR_STATIC char mem[MR_ECP_RESERVE(2)]; #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 0; } #endif if (logb2(_MIPP_ e) > B->max) { mr_berror(_MIPP_ MR_ERR_EXP_TOO_BIG); MR_OUT return 0; } if (!ecurve2_init(_MIPP_ B->m,B->a,B->b,B->c,B->a2,B->a6,FALSE,MR_BEST)) { MR_OUT return 0; } #ifdef MR_STATIC memset(mem,0,MR_ECP_RESERVE(2)); #else mem=(char *)ecp_memalloc(_MIPP_ 2); #endif w=epoint_init_mem(_MIPP_ mem,0); z=epoint_init_mem(_MIPP_ mem,1); m=B->m; if (m<0) m=-m; len=MR_ROUNDUP(m,MIRACL); maxsize=2*(1<window)*len; j=recode(_MIPP_ e,t,B->window,t-1); if (j>0) { promptr=2*j*len; init_point_from_rom(w,len,B->table,maxsize,&promptr); } for (i=t-2;i>=0;i--) { j=recode(_MIPP_ e,t,B->window,i); ecurve2_double(_MIPP_ w); if (j>0) { promptr=2*j*len; init_point_from_rom(z,len,B->table,maxsize,&promptr); ecurve2_add(_MIPP_ z,w); } } d=epoint2_get(_MIPP_ w,x,y); #ifndef MR_STATIC ecp_memkill(_MIPP_ mem,2); #else memset(mem,0,MR_ECP_RESERVE(2)); #endif MR_OUT return d; } #endif