/*************************************************************************** * 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 elliptic curve routines * mrcurve.c * * Assumes Weierstrass equation y^2 = x^3 + Ax + B * See IEEE P1363 Draft Standard * * (See below for Edwards coordinates implementation) * * Uses Montgomery's representation internally * * Works particularly well with fixed length Comba multiplier * e.g. #define MR_COMBA 5 for 5x32 = 160 bit modulus * on 32-bit computer * */ #include #include "miracl.h" #ifdef MR_STATIC #include #endif #ifndef MR_EDWARDS static void epoint_getrhs(_MIPD_ big x,big y) { /* x and y must be different */ /* find x^3+Ax+B */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif nres_modmult(_MIPP_ x,x,y); nres_modmult(_MIPP_ y,x,y); if (mr_abs(mr_mip->Asize)==MR_TOOBIG) nres_modmult(_MIPP_ x,mr_mip->A,mr_mip->w1); else nres_premult(_MIPP_ x,mr_mip->Asize,mr_mip->w1); nres_modadd(_MIPP_ y,mr_mip->w1,y); if (mr_abs(mr_mip->Bsize)==MR_TOOBIG) nres_modadd(_MIPP_ y,mr_mip->B,y); else { convert(_MIPP_ mr_mip->Bsize,mr_mip->w1); nres(_MIPP_ mr_mip->w1,mr_mip->w1); nres_modadd(_MIPP_ y,mr_mip->w1,y); } } #ifndef MR_NOSUPPORT_COMPRESSION BOOL epoint_x(_MIPD_ big x) { /* test if x is associated with a point on the * * currently active curve */ int j; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return FALSE; MR_IN(147) if (x==NULL) return FALSE; nres(_MIPP_ x,mr_mip->w2); epoint_getrhs(_MIPP_ mr_mip->w2,mr_mip->w3); if (size(mr_mip->w3)==0) { MR_OUT return TRUE; } redc(_MIPP_ mr_mip->w3,mr_mip->w4); j=jack(_MIPP_ mr_mip->w4,mr_mip->modulus); MR_OUT if (j==1) return TRUE; return FALSE; } #endif BOOL epoint_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 * * (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(97) if (x==NULL || y==NULL) { copy(mr_mip->one,p->X); copy(mr_mip->one,p->Y); p->marker=MR_EPOINT_INFINITY; MR_OUT return TRUE; } /* find x^3+Ax+B */ nres(_MIPP_ x,p->X); epoint_getrhs(_MIPP_ p->X,mr_mip->w3); valid=FALSE; if (x!=y) { /* compare with y^2 */ nres(_MIPP_ y,p->Y); nres_modmult(_MIPP_ p->Y,p->Y,mr_mip->w1); if (mr_compare(mr_mip->w1,mr_mip->w3)==0) valid=TRUE; } else { /* no y supplied - calculate one. Find square root */ #ifndef MR_NOSUPPORT_COMPRESSION valid=nres_sqroot(_MIPP_ mr_mip->w3,p->Y); /* check LSB - have we got the right root? */ redc(_MIPP_ p->Y,mr_mip->w1); if (remain(_MIPP_ mr_mip->w1,2)!=cb) mr_psub(_MIPP_ mr_mip->modulus,p->Y,p->Y); #else mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED); MR_OUT return FALSE; #endif } if (valid) { p->marker=MR_EPOINT_NORMALIZED; MR_OUT return TRUE; } MR_OUT return FALSE; } #ifndef MR_STATIC void epoint_getxyz(_MIPD_ epoint *p,big x,big y,big z) { /* get (x,y,z) coordinates */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif MR_IN(143) convert(_MIPP_ 1,mr_mip->w1); if (p->marker==MR_EPOINT_INFINITY) { #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { /* (0,1) or (0,0) = O */ #endif if (x!=NULL) zero(x); if (mr_mip->Bsize==0) { if (y!=NULL) copy(mr_mip->w1,y); } else { 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); MR_OUT return; } if (x!=NULL) redc(_MIPP_ p->X,x); if (y!=NULL) redc(_MIPP_ 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 redc(_MIPP_ p->Z,z); } } #endif MR_OUT return; } #endif int epoint_get(_MIPD_ epoint* p,big x,big y) { /* Get point co-ordinates in affine, normal form * * (converted from projective, Montgomery form) * * if x==y, supplies x only. Return value is Least * * Significant Bit of y (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(98) if (!epoint_norm(_MIPP_ p)) { /* not possible ! */ MR_OUT return (-1); } redc(_MIPP_ p->X,x); redc(_MIPP_ p->Y,mr_mip->w1); if (x!=y) copy(mr_mip->w1,y); lsb=remain(_MIPP_ mr_mip->w1,2); MR_OUT return lsb; } BOOL epoint_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(117) copy(mr_mip->one,mr_mip->w8); if (nres_moddiv(_MIPP_ mr_mip->w8,p->Z,mr_mip->w8)>1) /* 1/Z */ { epoint_set(_MIPP_ NULL,NULL,0,p); mr_berror(_MIPP_ MR_ERR_COMPOSITE_MODULUS); MR_OUT return FALSE; } nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w8,mr_mip->w1);/* 1/ZZ */ nres_modmult(_MIPP_ p->X,mr_mip->w1,p->X); /* X/ZZ */ nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w8,mr_mip->w1);/* 1/ZZZ */ nres_modmult(_MIPP_ p->Y,mr_mip->w1,p->Y); /* Y/ZZZ */ copy(mr_mip->one,p->Z); p->marker=MR_EPOINT_NORMALIZED; MR_OUT #endif return TRUE; } BOOL epoint_multi_norm(_MIPD_ int m,big *work,epoint **p) { /* 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(190) for (i=0;imarker==MR_EPOINT_NORMALIZED) w[i]=mr_mip->one; else w[i]=p[i]->Z; if (p[i]->marker==MR_EPOINT_INFINITY) {inf=TRUE; break;} /* whoops, one of them is point at infinity */ } if (inf) { for (i=0;ione,p[i]->Z); p[i]->marker=MR_EPOINT_NORMALIZED; nres_modmult(_MIPP_ work[i],work[i],mr_mip->w1); nres_modmult(_MIPP_ p[i]->X,mr_mip->w1,p[i]->X); /* X/ZZ */ nres_modmult(_MIPP_ mr_mip->w1,work[i],mr_mip->w1); nres_modmult(_MIPP_ p[i]->Y,mr_mip->w1,p[i]->Y); /* Y/ZZZ */ } MR_OUT #endif return TRUE; } /* adds b+=a, d+=c, and slopes in s1 and s2 */ #ifndef MR_NO_ECC_MULTIADD #ifndef MR_STATIC void ecurve_double_add(_MIPD_ epoint *a,epoint*b,epoint *c,epoint *d,big *s1,big *s2) { #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(144); #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { #endif if (a->marker==MR_EPOINT_INFINITY || size(a->Y)==0) { *s1=NULL; ecurve_add(_MIPP_ c,d); *s2=mr_mip->w8; MR_OUT return; } if (b->marker==MR_EPOINT_INFINITY || size(b->Y)==0) { *s1=NULL; epoint_copy(a,b); ecurve_add(_MIPP_ c,d); *s2=mr_mip->w8; MR_OUT return; } if (c->marker==MR_EPOINT_INFINITY || size(c->Y)==0) { ecurve_add(_MIPP_ a,b); *s1=mr_mip->w8; *s2=NULL; MR_OUT return; } if (d->marker==MR_EPOINT_INFINITY || size(d->Y)==0) { epoint_copy(c,d); ecurve_add(_MIPP_ a,b); *s1=mr_mip->w8; *s2=NULL; MR_OUT return; } if (a==b || (mr_compare(a->X,b->X)==0 && mr_compare(a->Y,b->Y)==0)) { nres_modmult(_MIPP_ a->X,a->X,mr_mip->w8); nres_premult(_MIPP_ mr_mip->w8,3,mr_mip->w8); /* 3x^2 */ if (mr_abs(mr_mip->Asize)==MR_TOOBIG) nres_modadd(_MIPP_ mr_mip->w8,mr_mip->A,mr_mip->w8); else { convert(_MIPP_ mr_mip->Asize,mr_mip->w2); nres(_MIPP_ mr_mip->w2,mr_mip->w2); nres_modadd(_MIPP_ mr_mip->w8,mr_mip->w2,mr_mip->w8); } nres_premult(_MIPP_ a->Y,2,mr_mip->w10); } else { if (mr_compare(a->X,b->X)==0) { epoint_set(_MIPP_ NULL,NULL,0,b); *s1=NULL; ecurve_add(_MIPP_ c,d); *s2=mr_mip->w8; MR_OUT return; } nres_modsub(_MIPP_ a->Y,b->Y,mr_mip->w8); nres_modsub(_MIPP_ a->X,b->X,mr_mip->w10); } if (c==d || (mr_compare(c->X,d->X)==0 && mr_compare(c->Y,d->Y)==0)) { nres_modmult(_MIPP_ c->X,c->X,mr_mip->w9); nres_premult(_MIPP_ mr_mip->w9,3,mr_mip->w9); /* 3x^2 */ if (mr_abs(mr_mip->Asize)==MR_TOOBIG) nres_modadd(_MIPP_ mr_mip->w9,mr_mip->A,mr_mip->w9); else { convert(_MIPP_ mr_mip->Asize,mr_mip->w2); nres(_MIPP_ mr_mip->w2,mr_mip->w2); nres_modadd(_MIPP_ mr_mip->w9,mr_mip->w2,mr_mip->w9); } nres_premult(_MIPP_ c->Y,2,mr_mip->w11); } else { if (mr_compare(c->X,d->X)==0) { epoint_set(_MIPP_ NULL,NULL,0,d); *s2=NULL; ecurve_add(_MIPP_ a,b); *s1=mr_mip->w8; MR_OUT return; } nres_modsub(_MIPP_ c->Y,d->Y,mr_mip->w9); nres_modsub(_MIPP_ c->X,d->X,mr_mip->w11); } nres_double_inverse(_MIPP_ mr_mip->w10,mr_mip->w10,mr_mip->w11,mr_mip->w11); nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w10,mr_mip->w8); nres_modmult(_MIPP_ mr_mip->w9,mr_mip->w11,mr_mip->w9); nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w8,mr_mip->w2); /* m^2 */ nres_modsub(_MIPP_ mr_mip->w2,a->X,mr_mip->w1); nres_modsub(_MIPP_ mr_mip->w1,b->X,mr_mip->w1); nres_modsub(_MIPP_ b->X,mr_mip->w1,mr_mip->w2); nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w8,mr_mip->w2); nres_modsub(_MIPP_ mr_mip->w2,b->Y,b->Y); copy(mr_mip->w1,b->X); b->marker=MR_EPOINT_GENERAL; nres_modmult(_MIPP_ mr_mip->w9,mr_mip->w9,mr_mip->w2); /* m^2 */ nres_modsub(_MIPP_ mr_mip->w2,c->X,mr_mip->w1); nres_modsub(_MIPP_ mr_mip->w1,d->X,mr_mip->w1); nres_modsub(_MIPP_ d->X,mr_mip->w1,mr_mip->w2); nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w9,mr_mip->w2); nres_modsub(_MIPP_ mr_mip->w2,d->Y,d->Y); copy(mr_mip->w1,d->X); d->marker=MR_EPOINT_GENERAL; *s1=mr_mip->w8; *s2=mr_mip->w9; #ifndef MR_AFFINE_ONLY } else { /* no speed-up */ ecurve_add(_MIPP_ a,b); copy(mr_mip->w8,mr_mip->w9); *s1=mr_mip->w9; ecurve_add(_MIPP_ c,d); *s2=mr_mip->w8; } #endif MR_OUT } void ecurve_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; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(122) #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { /* this can be done faster */ #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)); copy(mr_mip->one,mr_mip->w3); 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; } nres_modmult(_MIPP_ x[i]->X,x[i]->X,A[i]); nres_premult(_MIPP_ A[i],3,A[i]); /* 3*x^2 */ if (mr_abs(mr_mip->Asize) == MR_TOOBIG) nres_modadd(_MIPP_ A[i],mr_mip->A,A[i]); else { convert(_MIPP_ mr_mip->Asize,mr_mip->w2); nres(_MIPP_ mr_mip->w2,mr_mip->w2); nres_modadd(_MIPP_ A[i],mr_mip->w2,A[i]); } /* 3*x^2+A */ nres_premult(_MIPP_ x[i]->Y,2,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; } nres_modsub(_MIPP_ 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; } nres_modsub(_MIPP_ x[i]->Y,w[i]->Y,A[i]); } } nres_multi_inverse(_MIPP_ m,B,C); /* only one inversion needed */ for (i=0;iw8); nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w8,mr_mip->w2); /* m^2 */ nres_modsub(_MIPP_ mr_mip->w2,x[i]->X,mr_mip->w1); nres_modsub(_MIPP_ mr_mip->w1,w[i]->X,mr_mip->w1); nres_modsub(_MIPP_ w[i]->X,mr_mip->w1,mr_mip->w2); nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w8,mr_mip->w2); nres_modsub(_MIPP_ mr_mip->w2,w[i]->Y,w[i]->Y); copy(mr_mip->w1,w[i]->X); w[i]->marker=MR_EPOINT_NORMALIZED; mr_free(C[i]); mr_free(B[i]); mr_free(A[i]); } mr_free(flag); mr_free(C); mr_free(B); mr_free(A); #ifndef MR_AFFINE_ONLY } else { /* no speed-up */ for (i=0;iERNUM) return; if (p->marker==MR_EPOINT_INFINITY) { /* 2 times infinity == infinity ! */ return; } #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { /* 2 sqrs, 1 mul, 1 div */ #endif if (size(p->Y)==0) { /* set to point at infinity */ epoint_set(_MIPP_ NULL,NULL,0,p); return; } nres_modmult(_MIPP_ p->X,p->X,mr_mip->w8); /* w8=x^2 */ nres_premult(_MIPP_ mr_mip->w8,3,mr_mip->w8); /* w8=3*x^2 */ if (mr_abs(mr_mip->Asize) == MR_TOOBIG) nres_modadd(_MIPP_ mr_mip->w8,mr_mip->A,mr_mip->w8); else { convert(_MIPP_ mr_mip->Asize,mr_mip->w2); nres(_MIPP_ mr_mip->w2,mr_mip->w2); nres_modadd(_MIPP_ mr_mip->w8,mr_mip->w2,mr_mip->w8); } /* w8=3*x^2+A */ nres_premult(_MIPP_ p->Y,2,mr_mip->w6); /* w6=2y */ if (nres_moddiv(_MIPP_ mr_mip->w8,mr_mip->w6,mr_mip->w8)>1) { epoint_set(_MIPP_ NULL,NULL,0,p); mr_berror(_MIPP_ MR_ERR_COMPOSITE_MODULUS); return; } /* w8 is slope m on exit */ nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w8,mr_mip->w2); /* w2=m^2 */ nres_premult(_MIPP_ p->X,2,mr_mip->w1); nres_modsub(_MIPP_ mr_mip->w2,mr_mip->w1,mr_mip->w1); /* w1=m^2-2x */ nres_modsub(_MIPP_ p->X,mr_mip->w1,mr_mip->w2); nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w8,mr_mip->w2); nres_modsub(_MIPP_ mr_mip->w2,p->Y,p->Y); copy(mr_mip->w1,p->X); return; #ifndef MR_AFFINE_ONLY } if (size(p->Y)==0) { /* set to point at infinity */ epoint_set(_MIPP_ NULL,NULL,0,p); return; } convert(_MIPP_ 1,mr_mip->w1); if (mr_abs(mr_mip->Asize) < MR_TOOBIG) { if (mr_mip->Asize!=0) { if (p->marker==MR_EPOINT_NORMALIZED) nres(_MIPP_ mr_mip->w1,mr_mip->w6); else nres_modmult(_MIPP_ p->Z,p->Z,mr_mip->w6); } if (mr_mip->Asize==(-3)) { /* a is -3. Goody. 4 sqrs, 4 muls */ nres_modsub(_MIPP_ p->X,mr_mip->w6,mr_mip->w3); nres_modadd(_MIPP_ p->X,mr_mip->w6,mr_mip->w8); nres_modmult(_MIPP_ mr_mip->w3,mr_mip->w8,mr_mip->w3); nres_modadd(_MIPP_ mr_mip->w3,mr_mip->w3,mr_mip->w8); nres_modadd(_MIPP_ mr_mip->w8,mr_mip->w3,mr_mip->w8); } else { /* a is small */ if (mr_mip->Asize!=0) { /* a is non zero! */ nres_modmult(_MIPP_ mr_mip->w6,mr_mip->w6,mr_mip->w3); nres_premult(_MIPP_ mr_mip->w3,mr_mip->Asize,mr_mip->w3); } nres_modmult(_MIPP_ p->X,p->X,mr_mip->w1); nres_modadd(_MIPP_ mr_mip->w1,mr_mip->w1,mr_mip->w8); nres_modadd(_MIPP_ mr_mip->w8,mr_mip->w1,mr_mip->w8); if (mr_mip->Asize!=0) nres_modadd(_MIPP_ mr_mip->w8,mr_mip->w3,mr_mip->w8); } } else { /* a is not special */ if (p->marker==MR_EPOINT_NORMALIZED) nres(_MIPP_ mr_mip->w1,mr_mip->w6); else nres_modmult(_MIPP_ p->Z,p->Z,mr_mip->w6); nres_modmult(_MIPP_ mr_mip->w6,mr_mip->w6,mr_mip->w3); nres_modmult(_MIPP_ mr_mip->w3,mr_mip->A,mr_mip->w3); nres_modmult(_MIPP_ p->X,p->X,mr_mip->w1); nres_modadd(_MIPP_ mr_mip->w1,mr_mip->w1,mr_mip->w8); nres_modadd(_MIPP_ mr_mip->w8,mr_mip->w1,mr_mip->w8); nres_modadd(_MIPP_ mr_mip->w8,mr_mip->w3,mr_mip->w8); } /* w8 contains numerator of slope 3x^2+A.z^4 * * denominator is now placed in Z */ nres_modmult(_MIPP_ p->Y,p->Y,mr_mip->w2); nres_modmult(_MIPP_ p->X,mr_mip->w2,mr_mip->w3); nres_modadd(_MIPP_ mr_mip->w3,mr_mip->w3,mr_mip->w3); nres_modadd(_MIPP_ mr_mip->w3,mr_mip->w3,mr_mip->w3); nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w8,p->X); nres_modsub(_MIPP_ p->X,mr_mip->w3,p->X); nres_modsub(_MIPP_ p->X,mr_mip->w3,p->X); if (p->marker==MR_EPOINT_NORMALIZED) copy(p->Y,p->Z); else nres_modmult(_MIPP_ p->Z,p->Y,p->Z); nres_modadd(_MIPP_ p->Z,p->Z,p->Z); nres_modadd(_MIPP_ mr_mip->w2,mr_mip->w2,mr_mip->w7); nres_modmult(_MIPP_ mr_mip->w7,mr_mip->w7,mr_mip->w2); nres_modadd(_MIPP_ mr_mip->w2,mr_mip->w2,mr_mip->w2); nres_modsub(_MIPP_ mr_mip->w3,p->X,mr_mip->w3); nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w3,p->Y); nres_modsub(_MIPP_ p->Y,mr_mip->w2,p->Y); /* alternative method nres_modadd(_MIPP_ p->Y,p->Y,mr_mip->w2); if (p->marker==MR_EPOINT_NORMALIZED) copy(mr_mip->w2,p->Z); else nres_modmult(_MIPP_ mr_mip->w2,p->Z,p->Z); nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w2,mr_mip->w2); nres_modmult(_MIPP_ p->X,mr_mip->w2,mr_mip->w3); nres_modadd(_MIPP_ mr_mip->w3,mr_mip->w3,p->X); nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w8,mr_mip->w1); nres_modsub(_MIPP_ mr_mip->w1,p->X,p->X); nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w2,mr_mip->w2); if (remain(_MIPP_ mr_mip->w2,2)!=0) mr_padd(_MIPP_ mr_mip->w2,mr_mip->modulus,mr_mip->w2); subdiv(_MIPP_ mr_mip->w2,2,mr_mip->w2); nres_modsub(_MIPP_ mr_mip->w3,p->X,mr_mip->w3); nres_modmult(_MIPP_ mr_mip->w3,mr_mip->w8,mr_mip->w3); nres_modsub(_MIPP_ mr_mip->w3,mr_mip->w2,p->Y); */ /* Observe that when finished w8 contains the line slope, w7 has 2y^2 and w6 has z^2 This is useful for calculating line functions in pairings */ p->marker=MR_EPOINT_GENERAL; return; #endif } static BOOL ecurve_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) { /* 1 sqr, 1 mul, 1 div */ #endif nres_modsub(_MIPP_ p->Y,pa->Y,mr_mip->w8); nres_modsub(_MIPP_ p->X,pa->X,mr_mip->w6); if (size(mr_mip->w6)==0) { /* divide by 0 */ if (size(mr_mip->w8)==0) { /* should have doubled ! */ return FALSE; } else { /* point at infinity */ epoint_set(_MIPP_ NULL,NULL,0,pa); return TRUE; } } if (nres_moddiv(_MIPP_ mr_mip->w8,mr_mip->w6,mr_mip->w8)>1) { epoint_set(_MIPP_ NULL,NULL,0,pa); mr_berror(_MIPP_ MR_ERR_COMPOSITE_MODULUS); return TRUE; } nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w8,mr_mip->w2); /* w2=m^2 */ nres_modsub(_MIPP_ mr_mip->w2,p->X,mr_mip->w1); /* w1=m^2-x1-x2 */ nres_modsub(_MIPP_ mr_mip->w1,pa->X,mr_mip->w1); nres_modsub(_MIPP_ pa->X,mr_mip->w1,mr_mip->w2); nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w8,mr_mip->w2); nres_modsub(_MIPP_ mr_mip->w2,pa->Y,pa->Y); copy(mr_mip->w1,pa->X); pa->marker=MR_EPOINT_NORMALIZED; return TRUE; #ifndef MR_AFFINE_ONLY } if (p->marker!=MR_EPOINT_NORMALIZED) { nres_modmult(_MIPP_ p->Z,p->Z,mr_mip->w6); nres_modmult(_MIPP_ pa->X,mr_mip->w6,mr_mip->w1); nres_modmult(_MIPP_ mr_mip->w6,p->Z,mr_mip->w6); nres_modmult(_MIPP_ pa->Y,mr_mip->w6,mr_mip->w8); } else { copy(pa->X,mr_mip->w1); copy(pa->Y,mr_mip->w8); } if (pa->marker==MR_EPOINT_NORMALIZED) copy(mr_mip->one,mr_mip->w6); else nres_modmult(_MIPP_ pa->Z,pa->Z,mr_mip->w6); nres_modmult(_MIPP_ p->X,mr_mip->w6,mr_mip->w4); if (pa->marker!=MR_EPOINT_NORMALIZED) nres_modmult(_MIPP_ mr_mip->w6,pa->Z,mr_mip->w6); nres_modmult(_MIPP_ p->Y,mr_mip->w6,mr_mip->w5); nres_modsub(_MIPP_ mr_mip->w1,mr_mip->w4,mr_mip->w1); nres_modsub(_MIPP_ mr_mip->w8,mr_mip->w5,mr_mip->w8); /* w8 contains the numerator of the slope */ if (size(mr_mip->w1)==0) { if (size(mr_mip->w8)==0) { /* should have doubled ! */ return FALSE; } else { /* point at infinity */ epoint_set(_MIPP_ NULL,NULL,0,pa); return TRUE; } } nres_modadd(_MIPP_ mr_mip->w4,mr_mip->w4,mr_mip->w6); nres_modadd(_MIPP_ mr_mip->w1,mr_mip->w6,mr_mip->w4); nres_modadd(_MIPP_ mr_mip->w5,mr_mip->w5,mr_mip->w6); nres_modadd(_MIPP_ mr_mip->w8,mr_mip->w6,mr_mip->w5); if (p->marker!=MR_EPOINT_NORMALIZED) { if (pa->marker!=MR_EPOINT_NORMALIZED) nres_modmult(_MIPP_ pa->Z,p->Z,mr_mip->w3); else copy(p->Z,mr_mip->w3); nres_modmult(_MIPP_ mr_mip->w3,mr_mip->w1,pa->Z); } else { if (pa->marker!=MR_EPOINT_NORMALIZED) nres_modmult(_MIPP_ pa->Z,mr_mip->w1,pa->Z); else copy(mr_mip->w1,pa->Z); } nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w1,mr_mip->w6); nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w6,mr_mip->w1); nres_modmult(_MIPP_ mr_mip->w6,mr_mip->w4,mr_mip->w6); nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w8,mr_mip->w4); nres_modsub(_MIPP_ mr_mip->w4,mr_mip->w6,pa->X); nres_modsub(_MIPP_ mr_mip->w6,pa->X,mr_mip->w6); nres_modsub(_MIPP_ mr_mip->w6,pa->X,mr_mip->w6); nres_modmult(_MIPP_ mr_mip->w8,mr_mip->w6,mr_mip->w2); nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w5,mr_mip->w1); nres_modsub(_MIPP_ mr_mip->w2,mr_mip->w1,mr_mip->w5); /* divide by 2 */ nres_div2(_MIPP_ mr_mip->w5,pa->Y); pa->marker=MR_EPOINT_GENERAL; return TRUE; #endif } void epoint_copy(epoint *a,epoint *b) { if (a==b || b==NULL) 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 epoint_comp(_MIPD_ epoint *a,epoint *b) { BOOL result; #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; #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { #endif if (mr_compare(a->X,b->X)==0 && mr_compare(a->Y,b->Y)==0) result=TRUE; else result=FALSE; return result; #ifndef MR_AFFINE_ONLY } if (mr_mip->coord==MR_PROJECTIVE) { MR_IN(105) if (a->marker!=MR_EPOINT_GENERAL) copy(mr_mip->one,mr_mip->w1); else copy(a->Z,mr_mip->w1); if (b->marker!=MR_EPOINT_GENERAL) copy(mr_mip->one,mr_mip->w2); else copy(b->Z,mr_mip->w2); nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w1,mr_mip->w3); /* Za*Za */ nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w2,mr_mip->w4); /* Zb*Zb */ nres_modmult(_MIPP_ a->X,mr_mip->w4,mr_mip->w5); /* Xa*Zb*Zb */ nres_modmult(_MIPP_ b->X,mr_mip->w3,mr_mip->w6); /* Xb*Za*Za */ if (mr_compare(mr_mip->w5,mr_mip->w6)!=0) result=FALSE; else { nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w3,mr_mip->w3); nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w4,mr_mip->w4); nres_modmult(_MIPP_ a->Y,mr_mip->w4,mr_mip->w5); nres_modmult(_MIPP_ b->Y,mr_mip->w3,mr_mip->w6); if (mr_compare(mr_mip->w5,mr_mip->w6)!=0) result=FALSE; else result=TRUE; } MR_OUT return result; } return FALSE; #endif } int ecurve_add(_MIPD_ epoint *p,epoint *pa) { /* pa=pa+p; */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return MR_OVER; MR_IN(94) if (p==pa) { ecurve_double(_MIPP_ pa); MR_OUT if (pa->marker==MR_EPOINT_INFINITY) return MR_OVER; return MR_DOUBLE; } if (pa->marker==MR_EPOINT_INFINITY) { epoint_copy(p,pa); MR_OUT return MR_ADD; } if (p->marker==MR_EPOINT_INFINITY) { MR_OUT return MR_ADD; } if (!ecurve_padd(_MIPP_ p,pa)) { ecurve_double(_MIPP_ pa); MR_OUT return MR_DOUBLE; } MR_OUT if (pa->marker==MR_EPOINT_INFINITY) return MR_OVER; return MR_ADD; } void epoint_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(121) if (size(p->Y)!=0) mr_psub(_MIPP_ mr_mip->modulus,p->Y,p->Y); MR_OUT } int ecurve_sub(_MIPD_ epoint *p,epoint *pa) { int r; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return MR_OVER; MR_IN(104) if (p==pa) { epoint_set(_MIPP_ NULL,NULL,0,pa); MR_OUT return MR_OVER; } if (p->marker==MR_EPOINT_INFINITY) { MR_OUT return MR_ADD; } epoint_negate(_MIPP_ p); r=ecurve_add(_MIPP_ p,pa); epoint_negate(_MIPP_ p); MR_OUT return r; } int ecurve_mult(_MIPD_ big e,epoint *pa,epoint *pt) { /* pt=e*pa; */ int i,j,n,nb,nbs,nzs,nadds; epoint *table[MR_ECC_STORE_N]; #ifndef MR_AFFINE_ONLY big work[MR_ECC_STORE_N]; #endif #ifdef MR_STATIC char mem[MR_ECP_RESERVE(MR_ECC_STORE_N)]; #ifndef MR_AFFINE_ONLY char mem1[MR_BIG_RESERVE(MR_ECC_STORE_N)]; #endif #else char *mem; #ifndef MR_AFFINE_ONLY char *mem1; #endif #endif #ifndef MR_ALWAYS_BINARY epoint *p; int ce,ch; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return 0; MR_IN(95) if (size(e)==0) { /* multiplied by 0 */ epoint_set(_MIPP_ NULL,NULL,0,pt); MR_OUT return 0; } copy(e,mr_mip->w9); /* epoint_norm(_MIPP_ pa); */ epoint_copy(pa,pt); if (size(mr_mip->w9)<0) { /* pt = -pt */ negify(mr_mip->w9,mr_mip->w9); epoint_negate(_MIPP_ pt); } if (size(mr_mip->w9)==1) { MR_OUT return 0; } premult(_MIPP_ mr_mip->w9,3,mr_mip->w10); /* h=3*e */ #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_N)); #ifndef MR_AFFINE_ONLY memset(mem1,0,MR_BIG_RESERVE(MR_ECC_STORE_N)); #endif #else mem=(char *)ecp_memalloc(_MIPP_ MR_ECC_STORE_N); #ifndef MR_AFFINE_ONLY mem1=(char *)memalloc(_MIPP_ MR_ECC_STORE_N); #endif #endif for (i=0;i<=MR_ECC_STORE_N-1;i++) { table[i]=epoint_init_mem(_MIPP_ mem,i); #ifndef MR_AFFINE_ONLY work[i]=mirvar_mem(_MIPP_ mem1,i); #endif } epoint_copy(pt,table[0]); epoint_copy(table[0],table[MR_ECC_STORE_N-1]); ecurve_double(_MIPP_ table[MR_ECC_STORE_N-1]); /* epoint_norm(_MIPP_ table[MR_ECC_STORE_N-1]); */ for (i=1;iw10); nadds=0; epoint_set(_MIPP_ NULL,NULL,0,pt); for (i=nb-1;i>=1;) { /* 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_N); for (j=0;j0) {ecurve_add(_MIPP_ table[n/2],pt); nadds++;} if (n<0) {ecurve_sub(_MIPP_ table[(-n)/2],pt); nadds++;} i-=nbs; if (nzs) { for (j=0;jw10)-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) > 1) { /* add/subtract method */ if (mr_mip->user!=NULL) (*mr_mip->user)(); ecurve_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) {ecurve_add(_MIPP_ p,pt); nadds++;} mr_psub(_MIPP_ mr_mip->w10,mr_mip->w11,mr_mip->w10); } if (ce>=0) { /* e(i)=1 */ if (ch<0) {ecurve_sub(_MIPP_ p,pt); nadds++;} 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 MR_OUT return nadds; } #ifndef MR_NO_ECC_MULTIADD #ifndef MR_STATIC void ecurve_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(114) m=1< nb) nb=k; epoint_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;jERNUM) return FALSE; if (P->marker==MR_EPOINT_GENERAL || Q->marker==MR_EPOINT_GENERAL) { mr_berror(_MIPP_ MR_ERR_BAD_PARAMETERS); MR_OUT return FALSE; } if (mr_compare(P->X,Q->X)==0) { /* P=Q or P=-Q - shouldn't happen */ epoint_copy(P,PP); ecurve_add(_MIPP_ Q,PP); epoint_copy(P,PM); ecurve_sub(_MIPP_ Q,PM); MR_OUT return TRUE; } t1= mr_mip->w10; t2= mr_mip->w11; lam = mr_mip->w13; copy(P->X,t2); nres_modsub(_MIPP_ t2,Q->X,t2); redc(_MIPP_ t2,t2); invmodp(_MIPP_ t2,mr_mip->modulus,t2); nres(_MIPP_ t2,t2); nres_modadd(_MIPP_ P->X,Q->X,PP->X); copy(PP->X,PM->X); copy(P->Y,t1); nres_modsub(_MIPP_ t1,Q->Y,t1); copy(t1,lam); nres_modmult(_MIPP_ lam,t2,lam); copy(lam,t1); nres_modmult(_MIPP_ t1,t1,t1); nres_modsub(_MIPP_ t1,PP->X,PP->X); copy(Q->X,PP->Y); nres_modsub(_MIPP_ PP->Y,PP->X,PP->Y); nres_modmult(_MIPP_ PP->Y,lam,PP->Y); nres_modsub(_MIPP_ PP->Y,Q->Y,PP->Y); copy(P->Y,t1); nres_modadd(_MIPP_ t1,Q->Y,t1); copy(t1,lam); nres_modmult(_MIPP_ lam,t2,lam); copy(lam,t1); nres_modmult(_MIPP_ t1,t1,t1); nres_modsub(_MIPP_ t1,PM->X,PM->X); copy(Q->X,PM->Y); nres_modsub(_MIPP_ PM->Y,PM->X,PM->Y); nres_modmult(_MIPP_ PM->Y,lam,PM->Y); nres_modadd(_MIPP_ PM->Y,Q->Y,PM->Y); PP->marker=MR_EPOINT_NORMALIZED; PM->marker=MR_EPOINT_NORMALIZED; return TRUE; } void ecurve_mult2(_MIPD_ big e,epoint *p,big ea,epoint *pa,epoint *pt) { /* pt=e*p+ea*pa; */ int e1,h1,e2,h2,bb; epoint *p1,*p2,*ps[2]; #ifdef MR_STATIC char mem[MR_ECP_RESERVE(4)]; #else char *mem; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(103) if (size(e)==0) { ecurve_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); epoint_norm(_MIPP_ pa); epoint_copy(pa,p2); copy(ea,mr_mip->w9); if (size(mr_mip->w9)<0) { /* p2 = -p2 */ negify(mr_mip->w9,mr_mip->w9); epoint_negate(_MIPP_ p2); } epoint_norm(_MIPP_ p); epoint_copy(p,p1); copy(e,mr_mip->w12); if (size(mr_mip->w12)<0) { /* p1= -p1 */ negify(mr_mip->w12,mr_mip->w12); epoint_negate(_MIPP_ p1); } epoint_set(_MIPP_ NULL,NULL,0,pt); /* pt=0 */ ecurve_add_sub(_MIPP_ p1,p2,ps[0],ps[1]); /* only one inversion! ps[0]=p1+p2, ps[1]=p1-p2 */ mr_jsf(_MIPP_ mr_mip->w9,mr_mip->w12,mr_mip->w10,mr_mip->w9,mr_mip->w13,mr_mip->w12); /* To use a simple NAF instead, substitute this for the JSF premult(_MIPP_ mr_mip->w9,3,mr_mip->w10); 3*ea premult(_MIPP_ mr_mip->w12,3,mr_mip->w13); 3*e */ #ifndef MR_ALWAYS_BINARY if (mr_mip->base==mr_mip->base2) { #endif if (mr_compare(mr_mip->w10,mr_mip->w13)>=0) bb=logb2(_MIPP_ mr_mip->w10)-1; else bb=logb2(_MIPP_ mr_mip->w13)-1; while (bb>=0) /* for the simple NAF, this should be 1 */ { if (mr_mip->user!=NULL) (*mr_mip->user)(); ecurve_double(_MIPP_ pt); e1=h1=e2=h2=0; if (mr_testbit(_MIPP_ mr_mip->w9,bb)) e2=1; if (mr_testbit(_MIPP_ mr_mip->w10,bb)) h2=1; if (mr_testbit(_MIPP_ mr_mip->w12,bb)) e1=1; if (mr_testbit(_MIPP_ mr_mip->w13,bb)) h1=1; if (e1!=h1) { if (e2==h2) { if (h1==1) ecurve_add(_MIPP_ p1,pt); else ecurve_sub(_MIPP_ p1,pt); } else { if (h1==1) { if (h2==1) ecurve_add(_MIPP_ ps[0],pt); else ecurve_add(_MIPP_ ps[1],pt); } else { if (h2==1) ecurve_sub(_MIPP_ ps[1],pt); else ecurve_sub(_MIPP_ ps[0],pt); } } } else if (e2!=h2) { if (h2==1) ecurve_add(_MIPP_ p2,pt); else ecurve_sub(_MIPP_ p2,pt); } bb-=1; } #ifndef MR_ALWAYS_BINARY } else { if (mr_compare(mr_mip->w10,mr_mip->w13)>=0) expb2(_MIPP_ logb2(_MIPP_ mr_mip->w10)-1,mr_mip->w11); else expb2(_MIPP_ logb2(_MIPP_ mr_mip->w13)-1,mr_mip->w11); while (size(mr_mip->w11) > 0) /* for the NAF, this should be 1 */ { /* add/subtract method */ if (mr_mip->user!=NULL) (*mr_mip->user)(); ecurve_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) ecurve_add(_MIPP_ p1,pt); else ecurve_sub(_MIPP_ p1,pt); } else { if (h1==1) { if (h2==1) ecurve_add(_MIPP_ ps[0],pt); else ecurve_add(_MIPP_ ps[1],pt); } else { if (h2==1) ecurve_sub(_MIPP_ ps[1],pt); else ecurve_sub(_MIPP_ ps[0],pt); } } } else if (e2!=h2) { if (h2==1) ecurve_add(_MIPP_ p2,pt); else ecurve_sub(_MIPP_ p2,pt); } subdiv(_MIPP_ mr_mip->w11,2,mr_mip->w11); } } #endif ecp_memkill(_MIPP_ mem,4); MR_OUT } #endif #else /* Twisted Inverted Edwards curves * Assumes Twisted Inverted Edward's equation x^2+Ay^2 = x^2.y^2 + B * Assumes points are not of order 2 or 4 */ static void epoint_getrhs(_MIPD_ big x,big y) { /* find RHS=(x^2-B)/(x^2-A) */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif nres_modmult(_MIPP_ x,x,mr_mip->w6); nres_modsub(_MIPP_ mr_mip->w6,mr_mip->B,y); nres_modsub(_MIPP_ mr_mip->w6,mr_mip->A,mr_mip->w6); nres_moddiv(_MIPP_ y,mr_mip->w6,y); } #ifndef MR_NOSUPPORT_COMPRESSION BOOL epoint_x(_MIPD_ big x) { /* test if x is associated with a point on the * * currently active curve */ int j; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return FALSE; MR_IN(147) if (x==NULL) return FALSE; nres(_MIPP_ x,mr_mip->w2); epoint_getrhs(_MIPP_ mr_mip->w2,mr_mip->w7); if (size(mr_mip->w7)==0) { MR_OUT return TRUE; } redc(_MIPP_ mr_mip->w7,mr_mip->w4); j=jack(_MIPP_ mr_mip->w4,mr_mip->modulus); MR_OUT if (j==1) return TRUE; return FALSE; } #endif BOOL epoint_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 * * (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(97) if (x==NULL || y==NULL) { copy(mr_mip->one,p->X); zero(p->Y); p->marker=MR_EPOINT_INFINITY; MR_OUT return TRUE; } valid=FALSE; nres(_MIPP_ x,p->X); if (x!=y) { /* Check directly that x^2+Ay^2 == x^2.y^2+B */ nres(_MIPP_ y,p->Y); nres_modmult(_MIPP_ p->X,p->X,mr_mip->w1); nres_modmult(_MIPP_ p->Y,p->Y,mr_mip->w2); nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w3); nres_modadd(_MIPP_ mr_mip->w3,mr_mip->B,mr_mip->w3); if (mr_abs(mr_mip->Asize)==MR_TOOBIG) nres_modmult(_MIPP_ mr_mip->w2,mr_mip->A,mr_mip->w2); else nres_premult(_MIPP_ mr_mip->w2,mr_mip->Asize,mr_mip->w2); nres_modadd(_MIPP_ mr_mip->w2,mr_mip->w1,mr_mip->w2); if (mr_compare(mr_mip->w2,mr_mip->w3)==0) valid=TRUE; } else { /* find RHS */ epoint_getrhs(_MIPP_ p->X,mr_mip->w7); /* no y supplied - calculate one. Find square root */ #ifndef MR_NOSUPPORT_COMPRESSION valid=nres_sqroot(_MIPP_ mr_mip->w7,p->Y); /* check LSB - have we got the right root? */ redc(_MIPP_ p->Y,mr_mip->w1); if (remain(_MIPP_ mr_mip->w1,2)!=cb) mr_psub(_MIPP_ mr_mip->modulus,p->Y,p->Y); #else mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED); MR_OUT return FALSE; #endif } if (valid) { p->marker=MR_EPOINT_NORMALIZED; MR_OUT return TRUE; } MR_OUT return FALSE; } #ifndef MR_STATIC void epoint_getxyz(_MIPD_ epoint *p,big x,big y,big z) { /* get (x,y,z) coordinates */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif MR_IN(143) convert(_MIPP_ 1,mr_mip->w1); if (p->marker==MR_EPOINT_INFINITY) { if (x!=NULL) copy(mr_mip->w1,x); if (y!=NULL) zero(y); if (z!=NULL) zero(z); MR_OUT return; } if (x!=NULL) redc(_MIPP_ p->X,x); if (y!=NULL) redc(_MIPP_ p->Y,y); if (z!=NULL) redc(_MIPP_ p->Z,z); MR_OUT return; } #endif int epoint_get(_MIPD_ epoint* p,big x,big y) { /* Get point co-ordinates in affine, normal form * * (converted from projective, Montgomery form) * * if x==y, supplies x only. Return value is Least * * Significant Bit of y (useful for point compression) */ int lsb; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (p->marker==MR_EPOINT_INFINITY) { zero(y); convert(_MIPP_ 1,x); return 0; } if (mr_mip->ERNUM) return 0; MR_IN(98) if (!epoint_norm(_MIPP_ p)) { /* not possible ! */ MR_OUT return (-1); } redc(_MIPP_ p->X,x); redc(_MIPP_ p->Y,mr_mip->w1); if (x!=y) copy(mr_mip->w1,y); lsb=remain(_MIPP_ mr_mip->w1,2); MR_OUT return lsb; } BOOL epoint_norm(_MIPD_ epoint *p) { /* normalise a point */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (p->marker!=MR_EPOINT_GENERAL) return TRUE; if (mr_mip->ERNUM) return FALSE; MR_IN(117) copy(mr_mip->one,mr_mip->w8); if (nres_moddiv(_MIPP_ mr_mip->w8,p->Z,mr_mip->w8)>1) /* 1/Z */ { epoint_set(_MIPP_ NULL,NULL,0,p); mr_berror(_MIPP_ MR_ERR_COMPOSITE_MODULUS); MR_OUT return FALSE; } nres_modmult(_MIPP_ p->X,mr_mip->w8,p->X); /* X/Z */ nres_modmult(_MIPP_ p->Y,mr_mip->w8,p->Y); /* Y/Z */ copy(mr_mip->one,p->Z); p->marker=MR_EPOINT_NORMALIZED; MR_OUT return TRUE; } void ecurve_double(_MIPD_ epoint *p) { /* double epoint on active ecurve */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; if (p->marker==MR_EPOINT_INFINITY) { /* 2 times infinity == infinity ! */ return; } nres_modadd(_MIPP_ p->X,p->Y,mr_mip->w1); nres_modmult(_MIPP_ p->X,p->X,p->X); /* A=X1^2 */ nres_modmult(_MIPP_ p->Y,p->Y,p->Y); /* B=Y1^2 */ nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w1,mr_mip->w1); /* (X+Y)^2 */ nres_modsub(_MIPP_ mr_mip->w1,p->X,mr_mip->w1); nres_modsub(_MIPP_ mr_mip->w1,p->Y,mr_mip->w1); /* E=(X+Y)^2-A-B */ if (mr_abs(mr_mip->Asize)==MR_TOOBIG) /* U = aB */ nres_modmult(_MIPP_ p->Y,mr_mip->A,p->Y); else nres_premult(_MIPP_ p->Y,mr_mip->Asize,p->Y); if (p->marker!=MR_EPOINT_NORMALIZED) nres_modmult(_MIPP_ p->Z,p->Z,p->Z); else copy(mr_mip->one,p->Z); nres_modadd(_MIPP_ p->Z,p->Z,p->Z); if (mr_abs(mr_mip->Bsize)==MR_TOOBIG) /* 2dZ^2 */ nres_modmult(_MIPP_ p->Z,mr_mip->B,p->Z); else nres_premult(_MIPP_ p->Z,mr_mip->Bsize,p->Z); nres_modadd(_MIPP_ p->X,p->Y,mr_mip->w2); /* C=A+U */ nres_modsub(_MIPP_ p->X,p->Y,mr_mip->w3); /* D=A-U */ nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w3,p->X); /* X=C.D */ nres_modsub(_MIPP_ mr_mip->w2,p->Z,mr_mip->w2); /* C-2dZ^2 */ nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w1,p->Y); /* Y=E.(C-2dZ^2) */ nres_modmult(_MIPP_ mr_mip->w3,mr_mip->w1,p->Z); /* Z=D.E */ p->marker=MR_EPOINT_GENERAL; return; } static BOOL ecurve_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 if (p->marker==MR_EPOINT_INFINITY) return TRUE; if (pa->marker==MR_EPOINT_INFINITY) { epoint_copy(p,pa); return TRUE; } nres_modadd(_MIPP_ p->X,p->Y,mr_mip->w1); nres_modadd(_MIPP_ pa->X,pa->Y,mr_mip->w2); nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w1); /* I=(X1+Y1)(X2+Y2) */ if (p->marker!=MR_EPOINT_NORMALIZED) { if (pa->marker==MR_EPOINT_NORMALIZED) copy(p->Z,pa->Z); else nres_modmult(_MIPP_ p->Z,pa->Z,pa->Z); /* z = A = Z1*Z2 */ } else { if (pa->marker==MR_EPOINT_NORMALIZED) copy(mr_mip->one,pa->Z); } nres_modmult(_MIPP_ pa->Z,pa->Z,mr_mip->w2); /* w2 = B = dA^2 */ if (mr_abs(mr_mip->Bsize)==MR_TOOBIG) nres_modmult(_MIPP_ mr_mip->w2,mr_mip->B,mr_mip->w2); else nres_premult(_MIPP_ mr_mip->w2,mr_mip->Bsize,mr_mip->w2); nres_modmult(_MIPP_ p->X,pa->X,pa->X); /* x = C = X1*X2 */ nres_modmult(_MIPP_ p->Y,pa->Y,pa->Y); /* y = D = Y1*Y2 */ nres_modmult(_MIPP_ pa->X,pa->Y,mr_mip->w3); /* w3 = E = C*D */ nres_modsub(_MIPP_ mr_mip->w1,pa->X,mr_mip->w1); nres_modsub(_MIPP_ mr_mip->w1,pa->Y,mr_mip->w1); /* I=(X1+Y1)(X2+Y2)-C-D =X1*Y2+Y1*X2 */ if (mr_abs(mr_mip->Asize)==MR_TOOBIG) /* */ nres_modmult(_MIPP_ pa->Y,mr_mip->A,pa->Y); else nres_premult(_MIPP_ pa->Y,mr_mip->Asize,pa->Y); nres_modsub(_MIPP_ pa->X,pa->Y,pa->X); /* X = H = C-aD */ nres_modmult(_MIPP_ pa->Z,pa->X,pa->Z); nres_modmult(_MIPP_ pa->Z,mr_mip->w1,pa->Z); nres_modsub(_MIPP_ mr_mip->w3,mr_mip->w2,pa->Y); nres_modmult(_MIPP_ pa->Y,mr_mip->w1,pa->Y); nres_modadd(_MIPP_ mr_mip->w3,mr_mip->w2,mr_mip->w3); nres_modmult(_MIPP_ pa->X,mr_mip->w3,pa->X); if (size(pa->Z)==0) { copy(mr_mip->one,pa->X); zero(pa->Y); pa->marker=MR_EPOINT_INFINITY; } else pa->marker=MR_EPOINT_GENERAL; return TRUE; } void epoint_copy(epoint *a,epoint *b) { if (a==b || b==NULL) return; copy(a->X,b->X); copy(a->Y,b->Y); copy(a->Z,b->Z); b->marker=a->marker; return; } BOOL epoint_comp(_MIPD_ epoint *a,epoint *b) { #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(105) copy(a->Z,mr_mip->w1); copy(b->Z,mr_mip->w2); nres_modmult(_MIPP_ a->X,b->Z,mr_mip->w1); nres_modmult(_MIPP_ b->X,a->Z,mr_mip->w2); if (mr_compare(mr_mip->w1,mr_mip->w2)!=0) { MR_OUT return FALSE; } nres_modmult(_MIPP_ a->Y,b->Z,mr_mip->w1); nres_modmult(_MIPP_ b->Y,a->Z,mr_mip->w2); if (mr_compare(mr_mip->w1,mr_mip->w2)!=0) { MR_OUT return FALSE; } MR_OUT return TRUE; } int ecurve_add(_MIPD_ epoint *p,epoint *pa) { /* pa=pa+p; */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return MR_OVER; MR_IN(94) if (p==pa) { ecurve_double(_MIPP_ pa); MR_OUT if (pa->marker==MR_EPOINT_INFINITY) return MR_OVER; return MR_DOUBLE; } if (pa->marker==MR_EPOINT_INFINITY) { epoint_copy(p,pa); MR_OUT return MR_ADD; } if (p->marker==MR_EPOINT_INFINITY) { MR_OUT return MR_ADD; } if (!ecurve_padd(_MIPP_ p,pa)) { ecurve_double(_MIPP_ pa); MR_OUT return MR_DOUBLE; } MR_OUT if (pa->marker==MR_EPOINT_INFINITY) return MR_OVER; return MR_ADD; } void epoint_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(121) if (size(p->X)!=0) mr_psub(_MIPP_ mr_mip->modulus,p->X,p->X); MR_OUT } int ecurve_sub(_MIPD_ epoint *p,epoint *pa) { int r; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return MR_OVER; MR_IN(104) if (p==pa) { epoint_set(_MIPP_ NULL,NULL,0,pa); MR_OUT return MR_OVER; } if (p->marker==MR_EPOINT_INFINITY) { MR_OUT return MR_ADD; } epoint_negate(_MIPP_ p); r=ecurve_add(_MIPP_ p,pa); epoint_negate(_MIPP_ p); MR_OUT return r; } int ecurve_mult(_MIPD_ big e,epoint *pa,epoint *pt) { /* pt=e*pa; */ int i,j,n,nb,nbs,nzs,nadds; epoint *table[MR_ECC_STORE_N]; #ifdef MR_STATIC char mem[MR_ECP_RESERVE(MR_ECC_STORE_N)]; #else char *mem; #endif #ifndef MR_ALWAYS_BINARY epoint *p; int ce,ch; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return 0; MR_IN(95) if (size(e)==0) { /* multiplied by 0 */ epoint_set(_MIPP_ NULL,NULL,0,pt); MR_OUT return 0; } copy(e,mr_mip->w9); epoint_copy(pa,pt); if (size(mr_mip->w9)<0) { /* pt = -pt */ negify(mr_mip->w9,mr_mip->w9); epoint_negate(_MIPP_ pt); } if (size(mr_mip->w9)==1) { MR_OUT return 0; } premult(_MIPP_ mr_mip->w9,3,mr_mip->w10); /* h=3*e */ #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_N)); #else mem=(char *)ecp_memalloc(_MIPP_ MR_ECC_STORE_N); #endif for (i=0;i<=MR_ECC_STORE_N-1;i++) table[i]=epoint_init_mem(_MIPP_ mem,i); epoint_copy(pt,table[0]); epoint_copy(table[0],table[MR_ECC_STORE_N-1]); ecurve_double(_MIPP_ table[MR_ECC_STORE_N-1]); for (i=1;iw10); nadds=0; epoint_set(_MIPP_ NULL,NULL,0,pt); for (i=nb-1;i>=1;) { /* 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_N); for (j=0;j0) {ecurve_add(_MIPP_ table[n/2],pt); nadds++;} if (n<0) {ecurve_sub(_MIPP_ table[(-n)/2],pt); nadds++;} i-=nbs; if (nzs) { for (j=0;jw10)-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) > 1) { /* add/subtract method */ if (mr_mip->user!=NULL) (*mr_mip->user)(); ecurve_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) {ecurve_add(_MIPP_ p,pt); nadds++;} mr_psub(_MIPP_ mr_mip->w10,mr_mip->w11,mr_mip->w10); } if (ce>=0) { /* e(i)=1 */ if (ch<0) {ecurve_sub(_MIPP_ p,pt); nadds++;} 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 MR_OUT return nadds; } #ifndef MR_NO_ECC_MULTIADD #ifndef MR_STATIC void ecurve_multn(_MIPD_ int n,big *y,epoint **x,epoint *w) { /* pt=e[0]*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(114) m=1< nb) nb=k; epoint_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;jmarker==MR_EPOINT_NORMALIZED) { if (Q->marker==MR_EPOINT_NORMALIZED) copy(mr_mip->one,mr_mip->w1); else copy(Q->Z,mr_mip->w1); } else { if (Q->marker==MR_EPOINT_NORMALIZED) copy(P->Z,mr_mip->w1); else nres_modmult(_MIPP_ P->Z,Q->Z,mr_mip->w1); /* w1 = A = Z1*Z2 */ } nres_modmult(_MIPP_ mr_mip->w1,mr_mip->w1,mr_mip->w2); /* w2 = B = dA^2 */ if (mr_abs(mr_mip->Bsize)==MR_TOOBIG) nres_modmult(_MIPP_ mr_mip->w2,mr_mip->B,mr_mip->w2); else nres_premult(_MIPP_ mr_mip->w2,mr_mip->Bsize,mr_mip->w2); nres_modmult(_MIPP_ P->X,Q->X,mr_mip->w3); /* w3 = C = X1*X2 */ nres_modmult(_MIPP_ P->Y,Q->Y,mr_mip->w4); /* w4 = D = Y1*Y2 */ nres_modmult(_MIPP_ mr_mip->w3,mr_mip->w4,mr_mip->w5); /* w5 = E = C*D */ nres_modmult(_MIPP_ P->X,Q->Y,mr_mip->w7); /* w7 = F = X1.Y2 */ nres_modmult(_MIPP_ Q->X,P->Y,mr_mip->w8); /* w8 = G = X2.Y1 */ if (mr_abs(mr_mip->Asize)==MR_TOOBIG) /* w4 = aD */ nres_modmult(_MIPP_ mr_mip->w4,mr_mip->A,mr_mip->w4); else nres_premult(_MIPP_ mr_mip->w4,mr_mip->Asize,mr_mip->w4); /* P+Q */ nres_modsub(_MIPP_ mr_mip->w3,mr_mip->w4,mr_mip->w6); /* w6 = H = C-aD */ nres_modadd(_MIPP_ mr_mip->w7,mr_mip->w8,PP->Z); /* X1*Y2+X2*Y1 */ nres_modadd(_MIPP_ mr_mip->w5,mr_mip->w2,PP->X); nres_modmult(_MIPP_ PP->X,mr_mip->w6,PP->X); nres_modsub(_MIPP_ mr_mip->w5,mr_mip->w2,PP->Y); nres_modmult(_MIPP_ PP->Y,PP->Z,PP->Y); nres_modmult(_MIPP_ PP->Z,mr_mip->w6,PP->Z); nres_modmult(_MIPP_ PP->Z,mr_mip->w1,PP->Z); if (size(PP->Z)==0) { copy(mr_mip->one,PP->X); zero(PP->Y); PP->marker=MR_EPOINT_INFINITY; } else PP->marker=MR_EPOINT_GENERAL; /* P-Q */ nres_modadd(_MIPP_ mr_mip->w3,mr_mip->w4,mr_mip->w6); /* w6 = C+aD */ nres_modsub(_MIPP_ mr_mip->w8,mr_mip->w7,PM->Z); /* X2*Y1-X1*Y2 */ nres_modsub(_MIPP_ mr_mip->w5,mr_mip->w2,PM->X); nres_modmult(_MIPP_ PM->X,mr_mip->w6,PM->X); nres_modadd(_MIPP_ mr_mip->w5,mr_mip->w2,PM->Y); nres_modmult(_MIPP_ PM->Y,PM->Z,PM->Y); nres_modmult(_MIPP_ PM->Z,mr_mip->w6,PM->Z); nres_modmult(_MIPP_ PM->Z,mr_mip->w1,PM->Z); if (size(PM->Z)==0) { copy(mr_mip->one,PM->X); zero(PM->Y); PM->marker=MR_EPOINT_INFINITY; } else PM->marker=MR_EPOINT_GENERAL; return TRUE; } void ecurve_mult2(_MIPD_ big e,epoint *p,big ea,epoint *pa,epoint *pt) { /* pt=e*p+ea*pa; */ int e1,h1,e2,h2,bb; epoint *p1,*p2,*ps[2]; #ifdef MR_STATIC char mem[MR_ECP_RESERVE(4)]; #else char *mem; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(103) if (size(e)==0) { ecurve_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); epoint_copy(pa,p2); copy(ea,mr_mip->w9); if (size(mr_mip->w9)<0) { /* p2 = -p2 */ negify(mr_mip->w9,mr_mip->w9); epoint_negate(_MIPP_ p2); } epoint_copy(p,p1); copy(e,mr_mip->w12); if (size(mr_mip->w12)<0) { /* p1= -p1 */ negify(mr_mip->w12,mr_mip->w12); epoint_negate(_MIPP_ p1); } epoint_set(_MIPP_ NULL,NULL,0,pt); /* pt=0 */ ecurve_add_sub(_MIPP_ p1,p2,ps[0],ps[1]); /* ps[0]=p1+p2, ps[1]=p1-p2 */ mr_jsf(_MIPP_ mr_mip->w9,mr_mip->w12,mr_mip->w10,mr_mip->w9,mr_mip->w13,mr_mip->w12); /* To use a simple NAF instead, substitute this for the JSF premult(_MIPP_ mr_mip->w9,3,mr_mip->w10); 3*ea premult(_MIPP_ mr_mip->w12,3,mr_mip->w13); 3*e */ #ifndef MR_ALWAYS_BINARY if (mr_mip->base==mr_mip->base2) { #endif if (mr_compare(mr_mip->w10,mr_mip->w13)>=0) bb=logb2(_MIPP_ mr_mip->w10)-1; else bb=logb2(_MIPP_ mr_mip->w13)-1; while (bb>=0) /* for the simple NAF, this should be 1 */ { if (mr_mip->user!=NULL) (*mr_mip->user)(); ecurve_double(_MIPP_ pt); e1=h1=e2=h2=0; if (mr_testbit(_MIPP_ mr_mip->w9,bb)) e2=1; if (mr_testbit(_MIPP_ mr_mip->w10,bb)) h2=1; if (mr_testbit(_MIPP_ mr_mip->w12,bb)) e1=1; if (mr_testbit(_MIPP_ mr_mip->w13,bb)) h1=1; if (e1!=h1) { if (e2==h2) { if (h1==1) ecurve_add(_MIPP_ p1,pt); else ecurve_sub(_MIPP_ p1,pt); } else { if (h1==1) { if (h2==1) ecurve_add(_MIPP_ ps[0],pt); else ecurve_add(_MIPP_ ps[1],pt); } else { if (h2==1) ecurve_sub(_MIPP_ ps[1],pt); else ecurve_sub(_MIPP_ ps[0],pt); } } } else if (e2!=h2) { if (h2==1) ecurve_add(_MIPP_ p2,pt); else ecurve_sub(_MIPP_ p2,pt); } bb-=1; } #ifndef MR_ALWAYS_BINARY } else { if (mr_compare(mr_mip->w10,mr_mip->w13)>=0) expb2(_MIPP_ logb2(_MIPP_ mr_mip->w10)-1,mr_mip->w11); else expb2(_MIPP_ logb2(_MIPP_ mr_mip->w13)-1,mr_mip->w11); while (size(mr_mip->w11) > 0) /* for the NAF, this should be 1 */ { /* add/subtract method */ if (mr_mip->user!=NULL) (*mr_mip->user)(); ecurve_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) ecurve_add(_MIPP_ p1,pt); else ecurve_sub(_MIPP_ p1,pt); } else { if (h1==1) { if (h2==1) ecurve_add(_MIPP_ ps[0],pt); else ecurve_add(_MIPP_ ps[1],pt); } else { if (h2==1) ecurve_sub(_MIPP_ ps[1],pt); else ecurve_sub(_MIPP_ ps[0],pt); } } } else if (e2!=h2) { if (h2==1) ecurve_add(_MIPP_ p2,pt); else ecurve_sub(_MIPP_ p2,pt); } subdiv(_MIPP_ mr_mip->w11,2,mr_mip->w11); } } #endif ecp_memkill(_MIPP_ mem,4); MR_OUT } #endif #endif