/***************************************************************************
*
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