/*************************************************************************** * 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 C++ Implementation file ecn3.cpp * * AUTHOR : M. Scott * * PURPOSE : Implementation of class ECn3 (Elliptic curves over n^3) * * WARNING: This class has been cobbled together for a specific use with * the MIRACL library. It is not complete, and may not work in other * applications * */ #include "ecn3.h" using namespace std; void ECn3::get(ZZn3& a,ZZn3& b) const { #ifdef MR_ECN3_PROJECTIVE norm(); #endif a=x; b=y; } BOOL ECn3::iszero(void) const {if (marker==MR_EPOINT_INFINITY) return TRUE; return FALSE;} void ECn3::get(ZZn3& a) const { #ifdef MR_ECN3_PROJECTIVE norm(); #endif a=x; } #ifdef MR_ECN3_PROJECTIVE #ifndef MR_AFFINE_ONLY void ECn3::getZ(ZZn3& a) const {a=z;} void ECn3::get(ZZn3& a,ZZn3& b,ZZn3& c) const { a=x;b=y; if (marker==MR_EPOINT_GENERAL) c=z; else c=(ZZn)1; } void ECn3::set(const ZZn3& xx,const ZZn3& yy,const ZZn3& zz) { x=xx; y=yy; z=zz; if (z==(ZZn)1) marker=MR_EPOINT_NORMALIZED; else marker=MR_EPOINT_GENERAL; } #endif #endif BOOL ECn3::set(const ZZn3& xx,const ZZn3& yy) { int qnr; ZZn3 w; w=rhs(xx); if (yy*yy!=w) return FALSE; x=xx; y=yy; marker=MR_EPOINT_NORMALIZED; return TRUE; } BOOL ECn3::set(const ZZn3& xx) { ZZn3 w; w=rhs(xx); if (!w.iszero()) { w=sqrt(w); if (w.iszero()) return FALSE; } x=xx; y=w; marker=MR_EPOINT_NORMALIZED; return TRUE; } void ECn3::norm(void) const { // normalize a point #ifdef MR_ECN3_PROJECTIVE #ifndef MR_AFFINE_ONLY if (marker!=MR_EPOINT_GENERAL) return; ZZn3 t; z=inverse(z); t=z; z*=z; x*=z; z*=t; y*=z; z=1; marker=MR_EPOINT_NORMALIZED; #endif #endif } ECn3 operator-(const ECn3& a) {ECn3 w; if (a.marker!=MR_EPOINT_INFINITY) { w.x=a.x; w.y=-a.y; w.marker=a.marker; #ifdef MR_ECN3_PROJECTIVE #ifndef MR_AFFINE_ONLY if (w.marker==MR_EPOINT_GENERAL) w.z=a.z; #endif #endif } return w; } ECn3& ECn3::operator*=(const Big& k) { int i,j,n,nb,nbs,nzs; ECn3 p2,pt,t[11]; Big h,kk; if (k==0) { clear(); return *this; } if (k==1) { return (*this); } #ifdef MR_ECN3_PROJECTIVE norm(); #endif pt=*this; kk=k; if (kk<0) { pt=-pt; kk=-kk; } h=3*kk; // This is not optimal! p2=pt+pt; #ifdef MR_ECN3_PROJECTIVE p2.norm(); #endif t[0]=pt; for (i=1;i<=10;i++) { t[i]=t[i-1]+p2; #ifdef MR_ECN3_PROJECTIVE t[i].norm(); #endif } // Left to Right method nb=bits(h); for (i=nb-2;i>=1;) { n=naf_window(kk,h,i,&nbs,&nzs,11); for (j=0;j0) pt+=t[n/2]; if (n<0) pt-=t[(-n)/2]; i-=nbs; if (nzs) { for (j=0;jTWIST; int qnr=mip->cnr; if (marker==MR_EPOINT_INFINITY) { *this=W; return MR_ADD; } if (W.marker==MR_EPOINT_INFINITY) { return MR_ADD; } #ifdef MR_ECN3_PROJECTIVE #ifndef MR_AFFINE_ONLY if (mr_mip->coord==MR_AFFINE) { #endif #endif if (x!=W.x) { ZZn3 t=y; t-=W.y; ZZn3 t2=x; t2-=W.x; lam=t; lam/=t2; x+=W.x; t=lam; t*=t; t-=x; x=t; y=W.x; y-=x; y*=lam; y-=W.y; marker=MR_EPOINT_NORMALIZED; return MR_ADD; } else { if (y!=W.y || y.iszero()) { clear(); lam=one(); // any non-zero value return 0; } ZZn3 t=x; ZZn3 t1,t2=x; // lam=(3*(x*x)+getA())/(y+y); lam=x; lam*=lam; lam*=3; t1=getA(); if (twist==MR_QUADRATIC) t1=qnr*qnr*t1; if (twist==MR_QUARTIC_M) t1=tx(t1); if (twist==MR_QUARTIC_D) t1=txd(t1); lam+=t1; lam/=(y+y); t2+=x; x=lam; x*=x; x-=t2; t-=x; t*=lam; t-=y; y=t; marker=MR_EPOINT_NORMALIZED; return MR_DOUBLE; } #ifdef MR_ECN3_PROJECTIVE #ifndef MR_AFFINE_ONLY } int iA; BOOL Doubling; ZZn3 t1,t2,t3; ZZn3 Yzzz; t3=W.x; Yzzz=W.y; Doubling=FALSE; if (this==&W) Doubling=TRUE; if (!Doubling) { if (W.marker!=MR_EPOINT_NORMALIZED) { mr_berror(_MIPP_ MR_ERR_BAD_PARAMETERS); MR_OUT return 0; } if (marker!=MR_EPOINT_NORMALIZED) { t1=z; t1*=t1; t3*=t1; t1*=z; Yzzz*=t1; } if (t3==x) { if (Yzzz!=y || y==0) { clear(); lam=1; } else Doubling=TRUE; } } if (!Doubling) { // Addition t3-=x; lam=Yzzz-y; if (marker==MR_EPOINT_NORMALIZED) z=t3; else z*=t3; t1=t3; t1*=t1; Yzzz=t1*t3; t1*=x; t3=t1; t3+=t3; x=lam; x*=x; x-=t3; x-=Yzzz; t1-=x; t1*=lam; Yzzz*=y; y=t1-Yzzz; } else { // doubling t3=y; t3*=t3; iA=get_mip()->Asize; if (iA!=0) { if (marker==MR_EPOINT_NORMALIZED) t1=1; else {t1=z; t1*=t1;} if (ex2!=NULL) *ex2=t1; if (iA==-3 && twist<=MR_QUADRATIC) { if (twist==MR_QUADRATIC) t1*=qnr; lam=x-t1; t1+=x; lam*=t1; t2=lam; t2+=t2; lam+=t2; } else { lam=x; lam*=lam; t2=lam; t2+=t2; lam+=t2; if (twist==MR_QUADRATIC) t1*=qnr; t1*=t1; if (twist==MR_QUARTIC_M) t1=tx(t1); if (twist==MR_QUARTIC_D) t1=txd(t1); if (iA!=1) { if (iAB3) nb=bits(A3)-1; else nb=bits(B3)-1; while (nb>=0) { R+=R; e1=h1=e2=h2=0; t=0; if (bit(A,nb)) {e2=1; t+=8;} if (bit(A3,nb)) {h2=1; t+=4;} if (bit(B,nb)) {e1=1; t+=2;} if (bit(B3,nb)) {h1=1; t+=1;} if (t==1 || t==13) R+=Y; if (t==2 || t==14) R-=Y; if (t==4 || t==7) R+=X; if (t==8 || t==11) R-=X; if (t==5) R+=S; if (t==10) R-=S; if (t==9) R+=D; if (t==6) R-=D; nb-=1; } #ifdef MR_ECN3_PROJECTIVE R.norm(); #endif return R; } #ifndef MR_STATIC ECn3 mul(int n,ECn3* P,const Big* b) { int k,j,i,m,nb,ea; ECn3 *G; ECn3 R; m=1<nb) nb=k; for (i=nb-1;i>=0;i--) { ea=0; k=1; for (j=0;j