/*************************************************************************** * 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 small number theoretic routines * mrsmall.c */ #include "miracl.h" #ifdef MR_FP #include #endif #ifdef MR_WIN64 #include #endif mr_small smul(mr_small x,mr_small y,mr_small n) { /* returns x*y mod n */ mr_small r; #ifdef MR_ITANIUM mr_small tm; #endif #ifdef MR_WIN64 mr_small tm; #endif #ifdef MR_FP mr_small dres; #endif #ifndef MR_NOFULLWIDTH if (n==0) { /* Assume n=2^MIRACL */ muldvd(x,y,(mr_small)0,&r); return r; } #endif x=MR_REMAIN(x,n); y=MR_REMAIN(y,n); muldiv(x,y,(mr_small)0,n,&r); return r; } mr_small invers(mr_small x,mr_small y) { /* returns inverse of x mod y */ mr_small r,s,q,t,p; #ifdef MR_FP mr_small dres; #endif BOOL pos; if (y!=0) x=MR_REMAIN(x,y); r=1; s=0; p=y; pos=TRUE; #ifndef MR_NOFULLWIDTH if (p==0) { /* if modulus is 0, assume its actually 2^MIRACL */ if (x==1) return (mr_small)1; t=r; r=s; s=t; p=x; q=muldvm((mr_small)1,(mr_small)0,p,&t); t=r+s*q; r=s; s=t; t=0-p*q; x=p; p=t; } #endif while (p!=0) { /* main euclidean loop */ q=MR_DIV(x,p); t=r+s*q; r=s; s=t; t=x-p*q; x=p; p=t; pos=!pos; } if (!pos) r=y-r; return r; } int jac(mr_small x,mr_small n) { /* finds (x/n) as (-1)^m */ int m,k,n8,u4; mr_small t; #ifdef MR_FP mr_small dres; #endif if (x==0) { if (n==1) return 1; else return 0; } if (MR_REMAIN(n,2)==0) return 0; x=MR_REMAIN(x,n); m=0; while(n>1) { /* main loop */ if (x==0) return 0; /* extract powers of 2 */ for (k=0;MR_REMAIN(x,2)==0;k++) x=MR_DIV(x,2); n8=(int)MR_REMAIN(n,8); if (k%2==1) m+=(n8*n8-1)/8; /* quadratic reciprocity */ u4=(int)MR_REMAIN(x,4); m+=(n8-1)*(u4-1)/4; t=n; t=MR_REMAIN(t,x); n=x; x=t; m%=2; } if (m==0) return 1; else return (-1); } #ifndef MR_STATIC mr_small spmd(mr_small x,mr_small n,mr_small m) { /* returns x^n mod m */ mr_small r,sx; #ifdef MR_FP mr_small dres; #endif x=MR_REMAIN(x,m); r=0; if (x==0) return r; r=1; if (n==0) return r; sx=x; forever { if (MR_REMAIN(n,2)!=0) muldiv(r,sx,(mr_small)0,m,&r); n=MR_DIV(n,2); if (n==0) return r; muldiv(sx,sx,(mr_small)0,m,&sx); } } mr_small sqrmp(mr_small x,mr_small m) { /* square root mod a small prime by Shanks method * * returns 0 if root does not exist or m not prime */ mr_small z,y,v,w,t,q; #ifdef MR_FP mr_small dres; #endif int i,e,n,r; BOOL pp; x=MR_REMAIN(x,m); if (x==0) return 0; if (x==1) return 1; if (spmd(x,(mr_small)((m-1)/2),m)!=1) return 0; /* Legendre symbol not 1 */ if (MR_REMAIN(m,4)==3) return spmd(x,(mr_small)((m+1)/4),m); /* easy case for m=4.k+3 */ if (MR_REMAIN(m,8)==5) { /* also relatively easy */ t=spmd(x,(mr_small)((m-1)/4),m); if (t==1) return spmd(x,(mr_small)((m+3)/8),m); if (t==(mr_small)(m-1)) { muldiv((mr_small)4,x,(mr_small)0,m,&t); t=spmd(t,(mr_small)((m+3)/8),m); muldiv(t,(mr_small)((m+1)/2),(mr_small)0,m,&t); return t; } return 0; } q=m-1; e=0; while (MR_REMAIN(q,2)==0) { q=MR_DIV(q,2); e++; } if (e==0) return 0; /* even m */ for (r=2;;r++) { /* find suitable z */ z=spmd((mr_small)r,q,m); if (z==1) continue; t=z; pp=FALSE; for (i=1;i=r) return 0; y=spmd(y,mr_shiftbits(1,r-n-1),m); muldiv(v,y,(mr_small)0,m,&v); muldiv(y,y,(mr_small)0,m,&y); muldiv(w,y,(mr_small)0,m,&w); r=n; } return v; } #endif