You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1474 lines
32 KiB
1474 lines
32 KiB
/*
|
|
Licensed to the Apache Software Foundation (ASF) under one
|
|
or more contributor license agreements. See the NOTICE file
|
|
distributed with this work for additional information
|
|
regarding copyright ownership. The ASF licenses this file
|
|
to you under the Apache License, Version 2.0 (the
|
|
"License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing,
|
|
software distributed under the License is distributed on an
|
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
KIND, either express or implied. See the License for the
|
|
specific language governing permissions and limitations
|
|
under the License.
|
|
*/
|
|
|
|
/* AMCL basic functions for BIG type */
|
|
/* SU=m, SU is Stack Usage */
|
|
|
|
#include "big_256_56.h"
|
|
|
|
/* test a=0? */
|
|
int BIG_256_56_iszilch(BIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
if (a[i]!=0) return 0;
|
|
return 1;
|
|
}
|
|
|
|
/* test a=1? */
|
|
int BIG_256_56_isunity(BIG_256_56 a)
|
|
{
|
|
int i;
|
|
for(i=1; i<NLEN_256_56; i++)
|
|
if (a[i]!=0) return 0;
|
|
if (a[0]!=1) return 0;
|
|
return 1;
|
|
}
|
|
|
|
/* test a=0? */
|
|
int BIG_256_56_diszilch(DBIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<DNLEN_256_56; i++)
|
|
if (a[i]!=0) return 0;
|
|
return 1;
|
|
}
|
|
|
|
/* SU= 56 */
|
|
/* output a */
|
|
void BIG_256_56_output(BIG_256_56 a)
|
|
{
|
|
BIG_256_56 b;
|
|
int i,len;
|
|
len=BIG_256_56_nbits(a);
|
|
if (len%4==0) len/=4;
|
|
else
|
|
{
|
|
len/=4;
|
|
len++;
|
|
}
|
|
if (len<MODBYTES_256_56*2) len=MODBYTES_256_56*2;
|
|
|
|
for (i=len-1; i>=0; i--)
|
|
{
|
|
BIG_256_56_copy(b,a);
|
|
BIG_256_56_shr(b,i*4);
|
|
printf("%01x",(unsigned int) b[0]&15);
|
|
}
|
|
}
|
|
|
|
/* SU= 16 */
|
|
void BIG_256_56_rawoutput(BIG_256_56 a)
|
|
{
|
|
int i;
|
|
printf("(");
|
|
for (i=0; i<NLEN_256_56-1; i++)
|
|
#if CHUNK==64
|
|
printf("%"PRIxMAX",",(uintmax_t) a[i]);
|
|
printf("%"PRIxMAX")",(uintmax_t) a[NLEN_256_56-1]);
|
|
#else
|
|
printf("%x,",(unsigned int) a[i]);
|
|
printf("%x)",(unsigned int) a[NLEN_256_56-1]);
|
|
#endif
|
|
}
|
|
|
|
/* Swap a and b if d=1 */
|
|
void BIG_256_56_cswap(BIG_256_56 a,BIG_256_56 b,int d)
|
|
{
|
|
int i;
|
|
chunk t,c=d;
|
|
c=~(c-1);
|
|
#ifdef DEBUG_NORM
|
|
for (i=0; i<NLEN_256_56+2; i++)
|
|
#else
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
#endif
|
|
{
|
|
t=c&(a[i]^b[i]);
|
|
a[i]^=t;
|
|
b[i]^=t;
|
|
}
|
|
}
|
|
|
|
/* Move b to a if d=1 */
|
|
void BIG_256_56_cmove(BIG_256_56 f,BIG_256_56 g,int d)
|
|
{
|
|
int i;
|
|
chunk b=(chunk)-d;
|
|
#ifdef DEBUG_NORM
|
|
for (i=0; i<NLEN_256_56+2; i++)
|
|
#else
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
#endif
|
|
{
|
|
f[i]^=(f[i]^g[i])&b;
|
|
}
|
|
}
|
|
|
|
/* Move g to f if d=1 */
|
|
void BIG_256_56_dcmove(DBIG_256_56 f,DBIG_256_56 g,int d)
|
|
{
|
|
int i;
|
|
chunk b=(chunk)-d;
|
|
#ifdef DEBUG_NORM
|
|
for (i=0; i<DNLEN_256_56+2; i++)
|
|
#else
|
|
for (i=0; i<DNLEN_256_56; i++)
|
|
#endif
|
|
{
|
|
f[i]^=(f[i]^g[i])&b;
|
|
}
|
|
}
|
|
|
|
/* convert BIG to/from bytes */
|
|
/* SU= 64 */
|
|
void BIG_256_56_toBytes(char *b,BIG_256_56 a)
|
|
{
|
|
int i;
|
|
BIG_256_56 c;
|
|
BIG_256_56_norm(a);
|
|
BIG_256_56_copy(c,a);
|
|
for (i=MODBYTES_256_56-1; i>=0; i--)
|
|
{
|
|
b[i]=c[0]&0xff;
|
|
BIG_256_56_fshr(c,8);
|
|
}
|
|
}
|
|
|
|
/* SU= 16 */
|
|
void BIG_256_56_fromBytes(BIG_256_56 a,char *b)
|
|
{
|
|
int i;
|
|
BIG_256_56_zero(a);
|
|
for (i=0; i<MODBYTES_256_56; i++)
|
|
{
|
|
BIG_256_56_fshl(a,8);
|
|
a[0]+=(int)(unsigned char)b[i];
|
|
//BIG_256_56_inc(a,(int)(unsigned char)b[i]); BIG_256_56_norm(a);
|
|
}
|
|
#ifdef DEBUG_NORM
|
|
a[MPV_256_56]=1;
|
|
a[MNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
void BIG_256_56_fromBytesLen(BIG_256_56 a,char *b,int s)
|
|
{
|
|
int i,len=s;
|
|
BIG_256_56_zero(a);
|
|
|
|
if (len>MODBYTES_256_56) len=MODBYTES_256_56;
|
|
for (i=0; i<len; i++)
|
|
{
|
|
BIG_256_56_fshl(a,8);
|
|
a[0]+=(int)(unsigned char)b[i];
|
|
}
|
|
#ifdef DEBUG_NORM
|
|
a[MPV_256_56]=1;
|
|
a[MNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/* SU= 88 */
|
|
void BIG_256_56_doutput(DBIG_256_56 a)
|
|
{
|
|
DBIG_256_56 b;
|
|
int i,len;
|
|
BIG_256_56_dnorm(a);
|
|
len=BIG_256_56_dnbits(a);
|
|
if (len%4==0) len/=4;
|
|
else
|
|
{
|
|
len/=4;
|
|
len++;
|
|
}
|
|
|
|
for (i=len-1; i>=0; i--)
|
|
{
|
|
BIG_256_56_dcopy(b,a);
|
|
BIG_256_56_dshr(b,i*4);
|
|
printf("%01x",(unsigned int) b[0]&15);
|
|
}
|
|
}
|
|
|
|
|
|
void BIG_256_56_drawoutput(DBIG_256_56 a)
|
|
{
|
|
int i;
|
|
printf("(");
|
|
for (i=0; i<DNLEN_256_56-1; i++)
|
|
#if CHUNK==64
|
|
printf("%"PRIxMAX",",(uintmax_t) a[i]);
|
|
printf("%"PRIxMAX")",(uintmax_t) a[DNLEN_256_56-1]);
|
|
#else
|
|
printf("%x,",(unsigned int) a[i]);
|
|
printf("%x)",(unsigned int) a[DNLEN_256_56-1]);
|
|
#endif
|
|
}
|
|
|
|
/* Copy b=a */
|
|
void BIG_256_56_copy(BIG_256_56 b,BIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
b[i]=a[i];
|
|
#ifdef DEBUG_NORM
|
|
b[MPV_256_56]=a[MPV_256_56];
|
|
b[MNV_256_56]=a[MNV_256_56];
|
|
#endif
|
|
}
|
|
|
|
/* Copy from ROM b=a */
|
|
void BIG_256_56_rcopy(BIG_256_56 b,const BIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
b[i]=a[i];
|
|
#ifdef DEBUG_NORM
|
|
b[MPV_256_56]=1;
|
|
b[MNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
/* double length DBIG copy b=a */
|
|
void BIG_256_56_dcopy(DBIG_256_56 b,DBIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<DNLEN_256_56; i++)
|
|
b[i]=a[i];
|
|
#ifdef DEBUG_NORM
|
|
b[DMPV_256_56]=a[DMPV_256_56];
|
|
b[DMNV_256_56]=a[DMNV_256_56];
|
|
#endif
|
|
}
|
|
|
|
/* Copy BIG to bottom half of DBIG */
|
|
void BIG_256_56_dscopy(DBIG_256_56 b,BIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56-1; i++)
|
|
b[i]=a[i];
|
|
|
|
b[NLEN_256_56-1]=a[NLEN_256_56-1]&BMASK_256_56; /* top word normalized */
|
|
b[NLEN_256_56]=a[NLEN_256_56-1]>>BASEBITS_256_56;
|
|
|
|
for (i=NLEN_256_56+1; i<DNLEN_256_56; i++) b[i]=0;
|
|
#ifdef DEBUG_NORM
|
|
b[DMPV_256_56]=a[MPV_256_56];
|
|
b[DMNV_256_56]=a[MNV_256_56];
|
|
#endif
|
|
}
|
|
|
|
/* Copy BIG to top half of DBIG */
|
|
void BIG_256_56_dsucopy(DBIG_256_56 b,BIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
b[i]=0;
|
|
for (i=NLEN_256_56; i<DNLEN_256_56; i++)
|
|
b[i]=a[i-NLEN_256_56];
|
|
#ifdef DEBUG_NORM
|
|
b[DMPV_256_56]=a[MPV_256_56];
|
|
b[DMNV_256_56]=a[MNV_256_56];
|
|
#endif
|
|
}
|
|
|
|
/* Copy bottom half of DBIG to BIG */
|
|
void BIG_256_56_sdcopy(BIG_256_56 b,DBIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
b[i]=a[i];
|
|
#ifdef DEBUG_NORM
|
|
b[MPV_256_56]=a[DMPV_256_56];
|
|
b[MNV_256_56]=a[DMNV_256_56];
|
|
#endif
|
|
}
|
|
|
|
/* Copy top half of DBIG to BIG */
|
|
void BIG_256_56_sducopy(BIG_256_56 b,DBIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
b[i]=a[i+NLEN_256_56];
|
|
#ifdef DEBUG_NORM
|
|
b[MPV_256_56]=a[DMPV_256_56];
|
|
b[MNV_256_56]=a[DMNV_256_56];
|
|
|
|
#endif
|
|
}
|
|
|
|
/* Set a=0 */
|
|
void BIG_256_56_zero(BIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
a[i]=0;
|
|
#ifdef DEBUG_NORM
|
|
a[MPV_256_56]=a[MNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
void BIG_256_56_dzero(DBIG_256_56 a)
|
|
{
|
|
int i;
|
|
for (i=0; i<DNLEN_256_56; i++)
|
|
a[i]=0;
|
|
#ifdef DEBUG_NORM
|
|
a[DMPV_256_56]=a[DMNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
/* set a=1 */
|
|
void BIG_256_56_one(BIG_256_56 a)
|
|
{
|
|
int i;
|
|
a[0]=1;
|
|
for (i=1; i<NLEN_256_56; i++)
|
|
a[i]=0;
|
|
#ifdef DEBUG_NORM
|
|
a[MPV_256_56]=1;
|
|
a[MNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/* Set c=a+b */
|
|
/* SU= 8 */
|
|
void BIG_256_56_add(BIG_256_56 c,BIG_256_56 a,BIG_256_56 b)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
c[i]=a[i]+b[i];
|
|
#ifdef DEBUG_NORM
|
|
c[MPV_256_56]=a[MPV_256_56]+b[MPV_256_56];
|
|
c[MNV_256_56]=a[MNV_256_56]+b[MNV_256_56];
|
|
if (c[MPV_256_56]>NEXCESS_256_56) printf("add problem - positive digit overflow %d\n",c[MPV_256_56]);
|
|
if (c[MNV_256_56]>NEXCESS_256_56) printf("add problem - negative digit overflow %d\n",c[MNV_256_56]);
|
|
|
|
#endif
|
|
}
|
|
|
|
/* Set c=c+d */
|
|
void BIG_256_56_inc(BIG_256_56 c,int d)
|
|
{
|
|
BIG_256_56_norm(c);
|
|
c[0]+=(chunk)d;
|
|
#ifdef DEBUG_NORM
|
|
c[MPV_256_56]+=1;
|
|
#endif
|
|
}
|
|
|
|
/* Set c=a-b */
|
|
/* SU= 8 */
|
|
void BIG_256_56_sub(BIG_256_56 c,BIG_256_56 a,BIG_256_56 b)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
c[i]=a[i]-b[i];
|
|
#ifdef DEBUG_NORM
|
|
c[MPV_256_56]=a[MPV_256_56]+b[MNV_256_56];
|
|
c[MNV_256_56]=a[MNV_256_56]+b[MPV_256_56];
|
|
if (c[MPV_256_56]>NEXCESS_256_56) printf("sub problem - positive digit overflow %d\n",c[MPV_256_56]);
|
|
if (c[MNV_256_56]>NEXCESS_256_56) printf("sub problem - negative digit overflow %d\n",c[MNV_256_56]);
|
|
|
|
#endif
|
|
}
|
|
|
|
/* SU= 8 */
|
|
|
|
void BIG_256_56_dsub(DBIG_256_56 c,DBIG_256_56 a,DBIG_256_56 b)
|
|
{
|
|
int i;
|
|
for (i=0; i<DNLEN_256_56; i++)
|
|
c[i]=a[i]-b[i];
|
|
#ifdef DEBUG_NORM
|
|
c[DMPV_256_56]=a[DMPV_256_56]+b[DMNV_256_56];
|
|
c[DMNV_256_56]=a[DMNV_256_56]+b[DMPV_256_56];
|
|
if (c[DMPV_256_56]>NEXCESS_256_56) printf("double sub problem - positive digit overflow %d\n",c[DMPV_256_56]);
|
|
if (c[DMNV_256_56]>NEXCESS_256_56) printf("double sub problem - negative digit overflow %d\n",c[DMNV_256_56]);
|
|
#endif
|
|
}
|
|
|
|
void BIG_256_56_dadd(DBIG_256_56 c,DBIG_256_56 a,DBIG_256_56 b)
|
|
{
|
|
int i;
|
|
for (i=0; i<DNLEN_256_56; i++)
|
|
c[i]=a[i]+b[i];
|
|
#ifdef DEBUG_NORM
|
|
c[DMPV_256_56]=a[DMPV_256_56]+b[DMNV_256_56];
|
|
c[DMNV_256_56]=a[DMNV_256_56]+b[DMPV_256_56];
|
|
if (c[DMPV_256_56]>NEXCESS_256_56) printf("double add problem - positive digit overflow %d\n",c[DMPV_256_56]);
|
|
if (c[DMNV_256_56]>NEXCESS_256_56) printf("double add problem - negative digit overflow %d\n",c[DMNV_256_56]);
|
|
#endif
|
|
}
|
|
|
|
/* Set c=c-1 */
|
|
void BIG_256_56_dec(BIG_256_56 c,int d)
|
|
{
|
|
BIG_256_56_norm(c);
|
|
c[0]-=(chunk)d;
|
|
#ifdef DEBUG_NORM
|
|
c[MNV_256_56]+=1;
|
|
#endif
|
|
}
|
|
|
|
/* multiplication r=a*c by c<=NEXCESS_256_56 */
|
|
void BIG_256_56_imul(BIG_256_56 r,BIG_256_56 a,int c)
|
|
{
|
|
int i;
|
|
for (i=0; i<NLEN_256_56; i++) r[i]=a[i]*c;
|
|
#ifdef DEBUG_NORM
|
|
r[MPV_256_56]=a[MPV_256_56]*c;
|
|
r[MNV_256_56]=a[MNV_256_56]*c;
|
|
if (r[MPV_256_56]>NEXCESS_256_56) printf("int mul problem - positive digit overflow %d\n",r[MPV_256_56]);
|
|
if (r[MNV_256_56]>NEXCESS_256_56) printf("int mul problem - negative digit overflow %d\n",r[MNV_256_56]);
|
|
|
|
#endif
|
|
}
|
|
|
|
/* multiplication r=a*c by larger integer - c<=FEXCESS */
|
|
/* SU= 24 */
|
|
chunk BIG_256_56_pmul(BIG_256_56 r,BIG_256_56 a,int c)
|
|
{
|
|
int i;
|
|
chunk ak,carry=0;
|
|
// BIG_256_56_norm(a);
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
{
|
|
ak=a[i];
|
|
r[i]=0;
|
|
carry=muladd_256_56(ak,(chunk)c,carry,&r[i]);
|
|
}
|
|
#ifdef DEBUG_NORM
|
|
r[MPV_256_56]=1;
|
|
r[MNV_256_56]=0;
|
|
#endif
|
|
return carry;
|
|
}
|
|
|
|
/* r/=3 */
|
|
/* SU= 16 */
|
|
int BIG_256_56_div3(BIG_256_56 r)
|
|
{
|
|
int i;
|
|
chunk ak,base,carry=0;
|
|
BIG_256_56_norm(r);
|
|
base=((chunk)1<<BASEBITS_256_56);
|
|
for (i=NLEN_256_56-1; i>=0; i--)
|
|
{
|
|
ak=(carry*base+r[i]);
|
|
r[i]=ak/3;
|
|
carry=ak%3;
|
|
}
|
|
return (int)carry;
|
|
}
|
|
|
|
/* multiplication c=a*b by even larger integer b>FEXCESS, resulting in DBIG */
|
|
/* SU= 24 */
|
|
void BIG_256_56_pxmul(DBIG_256_56 c,BIG_256_56 a,int b)
|
|
{
|
|
int j;
|
|
chunk carry;
|
|
BIG_256_56_dzero(c);
|
|
carry=0;
|
|
for (j=0; j<NLEN_256_56; j++)
|
|
carry=muladd_256_56(a[j],(chunk)b,carry,&c[j]);
|
|
c[NLEN_256_56]=carry;
|
|
#ifdef DEBUG_NORM
|
|
c[DMPV_256_56]=1;
|
|
c[DMNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
/* .. if you know the result will fit in a BIG, c must be distinct from a and b */
|
|
/* SU= 40 */
|
|
void BIG_256_56_smul(BIG_256_56 c,BIG_256_56 a,BIG_256_56 b)
|
|
{
|
|
int i,j;
|
|
chunk carry;
|
|
// BIG_256_56_norm(a);
|
|
// BIG_256_56_norm(b);
|
|
|
|
BIG_256_56_zero(c);
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
{
|
|
carry=0;
|
|
for (j=0; j<NLEN_256_56; j++)
|
|
{
|
|
if (i+j<NLEN_256_56)
|
|
carry=muladd_256_56(a[i],b[j],carry,&c[i+j]);
|
|
}
|
|
}
|
|
#ifdef DEBUG_NORM
|
|
c[MPV_256_56]=1;
|
|
c[MNV_256_56]=0;
|
|
#endif
|
|
|
|
}
|
|
|
|
/* Set c=a*b */
|
|
/* SU= 72 */
|
|
void BIG_256_56_mul(DBIG_256_56 c,BIG_256_56 a,BIG_256_56 b)
|
|
{
|
|
int i;
|
|
#ifdef dchunk
|
|
dchunk t,co;
|
|
dchunk s;
|
|
dchunk d[NLEN_256_56];
|
|
int k;
|
|
#endif
|
|
|
|
#ifdef DEBUG_NORM
|
|
if ((a[MPV_256_56]!=1 && a[MPV_256_56]!=0) || a[MNV_256_56]!=0) printf("First input to mul not normed\n");
|
|
if ((b[MPV_256_56]!=1 && b[MPV_256_56]!=0) || b[MNV_256_56]!=0) printf("Second input to mul not normed\n");
|
|
#endif
|
|
|
|
/* Faster to Combafy it.. Let the compiler unroll the loops! */
|
|
|
|
#ifdef COMBA
|
|
|
|
/* faster psuedo-Karatsuba method */
|
|
#ifdef UNWOUND
|
|
|
|
/* Insert output of faster.c here */
|
|
|
|
#else
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
d[i]=(dchunk)a[i]*b[i];
|
|
|
|
s=d[0];
|
|
t=s;
|
|
c[0]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
|
|
for (k=1; k<NLEN_256_56; k++)
|
|
{
|
|
s+=d[k];
|
|
t=co+s;
|
|
for (i=k; i>=1+k/2; i--) t+=(dchunk)(a[i]-a[k-i])*(b[k-i]-b[i]);
|
|
c[k]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
}
|
|
for (k=NLEN_256_56; k<2*NLEN_256_56-1; k++)
|
|
{
|
|
s-=d[k-NLEN_256_56];
|
|
t=co+s;
|
|
for (i=NLEN_256_56-1; i>=1+k/2; i--) t+=(dchunk)(a[i]-a[k-i])*(b[k-i]-b[i]);
|
|
c[k]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
}
|
|
c[2*NLEN_256_56-1]=(chunk)co;
|
|
|
|
#endif
|
|
|
|
#else
|
|
int j;
|
|
chunk carry;
|
|
BIG_256_56_dzero(c);
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
{
|
|
carry=0;
|
|
for (j=0; j<NLEN_256_56; j++)
|
|
carry=muladd_256_56(a[i],b[j],carry,&c[i+j]);
|
|
|
|
c[NLEN_256_56+i]=carry;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef DEBUG_NORM
|
|
c[DMPV_256_56]=1;
|
|
c[DMNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
/* Set c=a*a */
|
|
/* SU= 80 */
|
|
void BIG_256_56_sqr(DBIG_256_56 c,BIG_256_56 a)
|
|
{
|
|
int i,j;
|
|
#ifdef dchunk
|
|
dchunk t,co;
|
|
#endif
|
|
|
|
#ifdef DEBUG_NORM
|
|
if ((a[MPV_256_56]!=1 && a[MPV_256_56]!=0) || a[MNV_256_56]!=0) printf("Input to sqr not normed\n");
|
|
#endif
|
|
/* Note 2*a[i] in loop below and extra addition */
|
|
|
|
#ifdef COMBA
|
|
|
|
#ifdef UNWOUND
|
|
|
|
/* Insert output of faster.c here */
|
|
|
|
#else
|
|
|
|
|
|
t=(dchunk)a[0]*a[0];
|
|
c[0]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
|
|
for (j=1; j<NLEN_256_56-1; )
|
|
{
|
|
t=(dchunk)a[j]*a[0];
|
|
for (i=1; i<(j+1)/2; i++)
|
|
{
|
|
t+=(dchunk)a[j-i]*a[i];
|
|
}
|
|
t+=t;
|
|
t+=co;
|
|
c[j]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
j++;
|
|
t=(dchunk)a[j]*a[0];
|
|
for (i=1; i<(j+1)/2; i++)
|
|
{
|
|
t+=(dchunk)a[j-i]*a[i];
|
|
}
|
|
t+=t;
|
|
t+=co;
|
|
t+=(dchunk)a[j/2]*a[j/2];
|
|
c[j]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
j++;
|
|
}
|
|
|
|
for (j=NLEN_256_56-1+NLEN_256_56%2; j<DNLEN_256_56-3; )
|
|
{
|
|
t=(dchunk)a[NLEN_256_56-1]*a[j-NLEN_256_56+1];
|
|
for (i=j-NLEN_256_56+2; i<(j+1)/2; i++)
|
|
{
|
|
t+=(dchunk)a[j-i]*a[i];
|
|
}
|
|
t+=t;
|
|
t+=co;
|
|
c[j]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
j++;
|
|
t=(dchunk)a[NLEN_256_56-1]*a[j-NLEN_256_56+1];
|
|
for (i=j-NLEN_256_56+2; i<(j+1)/2; i++)
|
|
{
|
|
t+=(dchunk)a[j-i]*a[i];
|
|
}
|
|
t+=t;
|
|
t+=co;
|
|
t+=(dchunk)a[j/2]*a[j/2];
|
|
c[j]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
j++;
|
|
}
|
|
|
|
t=(dchunk)a[NLEN_256_56-2]*a[NLEN_256_56-1];
|
|
t+=t;
|
|
t+=co;
|
|
c[DNLEN_256_56-3]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
|
|
t=(dchunk)a[NLEN_256_56-1]*a[NLEN_256_56-1]+co;
|
|
c[DNLEN_256_56-2]=(chunk)t&BMASK_256_56;
|
|
co=t>>BASEBITS_256_56;
|
|
c[DNLEN_256_56-1]=(chunk)co;
|
|
|
|
|
|
#endif
|
|
|
|
#else
|
|
chunk carry;
|
|
BIG_256_56_dzero(c);
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
{
|
|
carry=0;
|
|
for (j=i+1; j<NLEN_256_56; j++)
|
|
carry=muladd_256_56(a[i],a[j],carry,&c[i+j]);
|
|
c[NLEN_256_56+i]=carry;
|
|
}
|
|
|
|
for (i=0; i<DNLEN_256_56; i++) c[i]*=2;
|
|
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
c[2*i+1]+=muladd_256_56(a[i],a[i],0,&c[2*i]);
|
|
|
|
BIG_256_56_dnorm(c);
|
|
#endif
|
|
|
|
|
|
#ifdef DEBUG_NORM
|
|
c[DMPV_256_56]=1;
|
|
c[DMNV_256_56]=0;
|
|
#endif
|
|
|
|
}
|
|
|
|
/* Montgomery reduction */
|
|
void BIG_256_56_monty(BIG_256_56 a,BIG_256_56 md,chunk MC,DBIG_256_56 d)
|
|
{
|
|
int i,k;
|
|
|
|
#ifdef dchunk
|
|
dchunk t,c,s;
|
|
dchunk dd[NLEN_256_56];
|
|
chunk v[NLEN_256_56];
|
|
#endif
|
|
|
|
#ifdef COMBA
|
|
|
|
#ifdef UNWOUND
|
|
|
|
/* Insert output of faster.c here */
|
|
|
|
#else
|
|
|
|
t=d[0];
|
|
v[0]=((chunk)t*MC)&BMASK_256_56;
|
|
t+=(dchunk)v[0]*md[0];
|
|
c=(t>>BASEBITS_256_56)+d[1];
|
|
s=0;
|
|
|
|
for (k=1; k<NLEN_256_56; k++)
|
|
{
|
|
t=c+s+(dchunk)v[0]*md[k];
|
|
for (i=k-1; i>k/2; i--) t+=(dchunk)(v[k-i]-v[i])*(md[i]-md[k-i]);
|
|
v[k]=((chunk)t*MC)&BMASK_256_56;
|
|
t+=(dchunk)v[k]*md[0];
|
|
c=(t>>BASEBITS_256_56)+d[k+1];
|
|
dd[k]=(dchunk)v[k]*md[k];
|
|
s+=dd[k];
|
|
}
|
|
for (k=NLEN_256_56; k<2*NLEN_256_56-1; k++)
|
|
{
|
|
t=c+s;
|
|
for (i=NLEN_256_56-1; i>=1+k/2; i--) t+=(dchunk)(v[k-i]-v[i])*(md[i]-md[k-i]);
|
|
a[k-NLEN_256_56]=(chunk)t&BMASK_256_56;
|
|
c=(t>>BASEBITS_256_56)+d[k+1];
|
|
s-=dd[k-NLEN_256_56+1];
|
|
}
|
|
a[NLEN_256_56-1]=(chunk)c&BMASK_256_56;
|
|
|
|
#endif
|
|
|
|
#ifdef DEBUG_NORM
|
|
a[MPV_256_56]=1;
|
|
a[MNV_256_56]=0;
|
|
#endif
|
|
|
|
#else
|
|
int j;
|
|
chunk m,carry;
|
|
for (i=0; i<NLEN_256_56; i++)
|
|
{
|
|
if (MC==-1) m=(-d[i])&BMASK_256_56;
|
|
else
|
|
{
|
|
if (MC==1) m=d[i];
|
|
else m=(MC*d[i])&BMASK_256_56;
|
|
}
|
|
carry=0;
|
|
for (j=0; j<NLEN_256_56; j++)
|
|
carry=muladd_256_56(m,md[j],carry,&d[i+j]);
|
|
d[NLEN_256_56+i]+=carry;
|
|
}
|
|
BIG_256_56_sducopy(a,d);
|
|
BIG_256_56_norm(a);
|
|
|
|
#endif
|
|
}
|
|
|
|
/* General shift left of a by n bits */
|
|
/* a MUST be normalised */
|
|
/* SU= 32 */
|
|
void BIG_256_56_shl(BIG_256_56 a,int k)
|
|
{
|
|
int i;
|
|
int n=k%BASEBITS_256_56;
|
|
int m=k/BASEBITS_256_56;
|
|
|
|
a[NLEN_256_56-1]=((a[NLEN_256_56-1-m]<<n));
|
|
if (NLEN_256_56>=m+2) a[NLEN_256_56-1]|=(a[NLEN_256_56-m-2]>>(BASEBITS_256_56-n));
|
|
|
|
for (i=NLEN_256_56-2; i>m; i--)
|
|
a[i]=((a[i-m]<<n)&BMASK_256_56)|(a[i-m-1]>>(BASEBITS_256_56-n));
|
|
a[m]=(a[0]<<n)&BMASK_256_56;
|
|
for (i=0; i<m; i++) a[i]=0;
|
|
|
|
}
|
|
|
|
/* Fast shift left of a by n bits, where n less than a word, Return excess (but store it as well) */
|
|
/* a MUST be normalised */
|
|
/* SU= 16 */
|
|
int BIG_256_56_fshl(BIG_256_56 a,int n)
|
|
{
|
|
int i;
|
|
|
|
a[NLEN_256_56-1]=((a[NLEN_256_56-1]<<n))|(a[NLEN_256_56-2]>>(BASEBITS_256_56-n)); /* top word not masked */
|
|
for (i=NLEN_256_56-2; i>0; i--)
|
|
a[i]=((a[i]<<n)&BMASK_256_56)|(a[i-1]>>(BASEBITS_256_56-n));
|
|
a[0]=(a[0]<<n)&BMASK_256_56;
|
|
|
|
return (int)(a[NLEN_256_56-1]>>((8*MODBYTES_256_56)%BASEBITS_256_56)); /* return excess - only used in ff.c */
|
|
}
|
|
|
|
/* double length left shift of a by k bits - k can be > BASEBITS , a MUST be normalised */
|
|
/* SU= 32 */
|
|
void BIG_256_56_dshl(DBIG_256_56 a,int k)
|
|
{
|
|
int i;
|
|
int n=k%BASEBITS_256_56;
|
|
int m=k/BASEBITS_256_56;
|
|
|
|
a[DNLEN_256_56-1]=((a[DNLEN_256_56-1-m]<<n))|(a[DNLEN_256_56-m-2]>>(BASEBITS_256_56-n));
|
|
|
|
for (i=DNLEN_256_56-2; i>m; i--)
|
|
a[i]=((a[i-m]<<n)&BMASK_256_56)|(a[i-m-1]>>(BASEBITS_256_56-n));
|
|
a[m]=(a[0]<<n)&BMASK_256_56;
|
|
for (i=0; i<m; i++) a[i]=0;
|
|
|
|
}
|
|
|
|
/* General shift rightof a by k bits */
|
|
/* a MUST be normalised */
|
|
/* SU= 32 */
|
|
void BIG_256_56_shr(BIG_256_56 a,int k)
|
|
{
|
|
int i;
|
|
int n=k%BASEBITS_256_56;
|
|
int m=k/BASEBITS_256_56;
|
|
for (i=0; i<NLEN_256_56-m-1; i++)
|
|
a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS_256_56-n))&BMASK_256_56);
|
|
if (NLEN_256_56>m) a[NLEN_256_56-m-1]=a[NLEN_256_56-1]>>n;
|
|
for (i=NLEN_256_56-m; i<NLEN_256_56; i++) a[i]=0;
|
|
|
|
}
|
|
|
|
/* Faster shift right of a by k bits. Return shifted out part */
|
|
/* a MUST be normalised */
|
|
/* SU= 16 */
|
|
int BIG_256_56_fshr(BIG_256_56 a,int k)
|
|
{
|
|
int i;
|
|
chunk r=a[0]&(((chunk)1<<k)-1); /* shifted out part */
|
|
for (i=0; i<NLEN_256_56-1; i++)
|
|
a[i]=(a[i]>>k)|((a[i+1]<<(BASEBITS_256_56-k))&BMASK_256_56);
|
|
a[NLEN_256_56-1]=a[NLEN_256_56-1]>>k;
|
|
return (int)r;
|
|
}
|
|
|
|
/* double length right shift of a by k bits - can be > BASEBITS */
|
|
/* SU= 32 */
|
|
void BIG_256_56_dshr(DBIG_256_56 a,int k)
|
|
{
|
|
int i;
|
|
int n=k%BASEBITS_256_56;
|
|
int m=k/BASEBITS_256_56;
|
|
for (i=0; i<DNLEN_256_56-m-1; i++)
|
|
a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS_256_56-n))&BMASK_256_56);
|
|
a[DNLEN_256_56-m-1]=a[DNLEN_256_56-1]>>n;
|
|
for (i=DNLEN_256_56-m; i<DNLEN_256_56; i++ ) a[i]=0;
|
|
}
|
|
|
|
/* Split DBIG d into two BIGs t|b. Split happens at n bits, where n falls into NLEN word */
|
|
/* d MUST be normalised */
|
|
/* SU= 24 */
|
|
chunk BIG_256_56_split(BIG_256_56 t,BIG_256_56 b,DBIG_256_56 d,int n)
|
|
{
|
|
int i;
|
|
chunk nw,carry=0;
|
|
int m=n%BASEBITS_256_56;
|
|
// BIG_dnorm(d);
|
|
|
|
if (m==0)
|
|
{
|
|
for (i=0; i<NLEN_256_56; i++) b[i]=d[i];
|
|
if (t!=b)
|
|
{
|
|
for (i=NLEN_256_56; i<2*NLEN_256_56; i++) t[i-NLEN_256_56]=d[i];
|
|
carry=t[NLEN_256_56-1]>>BASEBITS_256_56;
|
|
t[NLEN_256_56-1]=t[NLEN_256_56-1]&BMASK_256_56; /* top word normalized */
|
|
}
|
|
return carry;
|
|
}
|
|
|
|
for (i=0; i<NLEN_256_56-1; i++) b[i]=d[i];
|
|
|
|
b[NLEN_256_56-1]=d[NLEN_256_56-1]&(((chunk)1<<m)-1);
|
|
|
|
if (t!=b)
|
|
{
|
|
carry=(d[DNLEN_256_56-1]<<(BASEBITS_256_56-m));
|
|
for (i=DNLEN_256_56-2; i>=NLEN_256_56-1; i--)
|
|
{
|
|
nw=(d[i]>>m)|carry;
|
|
carry=(d[i]<<(BASEBITS_256_56-m))&BMASK_256_56;
|
|
t[i-NLEN_256_56+1]=nw;
|
|
}
|
|
}
|
|
#ifdef DEBUG_NORM
|
|
t[MPV_256_56]=1;
|
|
t[MNV_256_56]=0;
|
|
b[MPV_256_56]=1;
|
|
b[MNV_256_56]=0;
|
|
#endif
|
|
return carry;
|
|
}
|
|
|
|
/* you gotta keep the sign of carry! Look - no branching! */
|
|
/* Note that sign bit is needed to disambiguate between +ve and -ve values */
|
|
/* normalise BIG - force all digits < 2^BASEBITS */
|
|
chunk BIG_256_56_norm(BIG_256_56 a)
|
|
{
|
|
int i;
|
|
chunk d,carry=0;
|
|
for (i=0; i<NLEN_256_56-1; i++)
|
|
{
|
|
d=a[i]+carry;
|
|
a[i]=d&BMASK_256_56;
|
|
carry=d>>BASEBITS_256_56;
|
|
}
|
|
a[NLEN_256_56-1]=(a[NLEN_256_56-1]+carry);
|
|
|
|
#ifdef DEBUG_NORM
|
|
a[MPV_256_56]=1;
|
|
a[MNV_256_56]=0;
|
|
#endif
|
|
return (a[NLEN_256_56-1]>>((8*MODBYTES_256_56)%BASEBITS_256_56)); /* only used in ff.c */
|
|
}
|
|
|
|
void BIG_256_56_dnorm(DBIG_256_56 a)
|
|
{
|
|
int i;
|
|
chunk d,carry=0;
|
|
for (i=0; i<DNLEN_256_56-1; i++)
|
|
{
|
|
d=a[i]+carry;
|
|
a[i]=d&BMASK_256_56;
|
|
carry=d>>BASEBITS_256_56;
|
|
}
|
|
a[DNLEN_256_56-1]=(a[DNLEN_256_56-1]+carry);
|
|
#ifdef DEBUG_NORM
|
|
a[DMPV_256_56]=1;
|
|
a[DMNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
/* Compare a and b. Return 1 for a>b, -1 for a<b, 0 for a==b */
|
|
/* a and b MUST be normalised before call */
|
|
int BIG_256_56_comp(BIG_256_56 a,BIG_256_56 b)
|
|
{
|
|
int i;
|
|
for (i=NLEN_256_56-1; i>=0; i--)
|
|
{
|
|
if (a[i]==b[i]) continue;
|
|
if (a[i]>b[i]) return 1;
|
|
else return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int BIG_256_56_dcomp(DBIG_256_56 a,DBIG_256_56 b)
|
|
{
|
|
int i;
|
|
for (i=DNLEN_256_56-1; i>=0; i--)
|
|
{
|
|
if (a[i]==b[i]) continue;
|
|
if (a[i]>b[i]) return 1;
|
|
else return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* return number of bits in a */
|
|
/* SU= 8 */
|
|
int BIG_256_56_nbits(BIG_256_56 a)
|
|
{
|
|
int bts,k=NLEN_256_56-1;
|
|
chunk c;
|
|
BIG_256_56_norm(a);
|
|
while (k>=0 && a[k]==0) k--;
|
|
if (k<0) return 0;
|
|
bts=BASEBITS_256_56*k;
|
|
c=a[k];
|
|
while (c!=0)
|
|
{
|
|
c/=2;
|
|
bts++;
|
|
}
|
|
return bts;
|
|
}
|
|
|
|
/* SU= 8, Calculate number of bits in a DBIG - output normalised */
|
|
int BIG_256_56_dnbits(DBIG_256_56 a)
|
|
{
|
|
int bts,k=DNLEN_256_56-1;
|
|
chunk c;
|
|
BIG_256_56_dnorm(a);
|
|
while (k>=0 && a[k]==0) k--;
|
|
if (k<0) return 0;
|
|
bts=BASEBITS_256_56*k;
|
|
c=a[k];
|
|
while (c!=0)
|
|
{
|
|
c/=2;
|
|
bts++;
|
|
}
|
|
return bts;
|
|
}
|
|
|
|
|
|
/* Set b=b mod c */
|
|
/* SU= 16 */
|
|
void BIG_256_56_mod(BIG_256_56 b,BIG_256_56 c)
|
|
{
|
|
int k=0;
|
|
BIG_256_56 r; /**/
|
|
|
|
BIG_256_56_norm(b);
|
|
if (BIG_256_56_comp(b,c)<0)
|
|
return;
|
|
do
|
|
{
|
|
BIG_256_56_fshl(c,1);
|
|
k++;
|
|
}
|
|
while (BIG_256_56_comp(b,c)>=0);
|
|
|
|
while (k>0)
|
|
{
|
|
BIG_256_56_fshr(c,1);
|
|
|
|
// constant time...
|
|
BIG_256_56_sub(r,b,c);
|
|
BIG_256_56_norm(r);
|
|
BIG_256_56_cmove(b,r,1-((r[NLEN_256_56-1]>>(CHUNK-1))&1));
|
|
k--;
|
|
}
|
|
}
|
|
|
|
/* Set a=b mod c, b is destroyed. Slow but rarely used. */
|
|
/* SU= 96 */
|
|
void BIG_256_56_dmod(BIG_256_56 a,DBIG_256_56 b,BIG_256_56 c)
|
|
{
|
|
int k=0;
|
|
DBIG_256_56 m,r;
|
|
BIG_256_56_dnorm(b);
|
|
BIG_256_56_dscopy(m,c);
|
|
|
|
if (BIG_256_56_dcomp(b,m)<0)
|
|
{
|
|
BIG_256_56_sdcopy(a,b);
|
|
return;
|
|
}
|
|
|
|
do
|
|
{
|
|
BIG_256_56_dshl(m,1);
|
|
k++;
|
|
}
|
|
while (BIG_256_56_dcomp(b,m)>=0);
|
|
|
|
while (k>0)
|
|
{
|
|
BIG_256_56_dshr(m,1);
|
|
// constant time...
|
|
BIG_256_56_dsub(r,b,m);
|
|
BIG_256_56_dnorm(r);
|
|
BIG_256_56_dcmove(b,r,1-((r[DNLEN_256_56-1]>>(CHUNK-1))&1));
|
|
|
|
k--;
|
|
}
|
|
BIG_256_56_sdcopy(a,b);
|
|
}
|
|
|
|
/* Set a=b/c, b is destroyed. Slow but rarely used. */
|
|
/* SU= 136 */
|
|
|
|
void BIG_256_56_ddiv(BIG_256_56 a,DBIG_256_56 b,BIG_256_56 c)
|
|
{
|
|
int d,k=0;
|
|
DBIG_256_56 m,dr;
|
|
BIG_256_56 e,r;
|
|
BIG_256_56_dnorm(b);
|
|
BIG_256_56_dscopy(m,c);
|
|
|
|
BIG_256_56_zero(a);
|
|
BIG_256_56_zero(e);
|
|
BIG_256_56_inc(e,1);
|
|
|
|
while (BIG_256_56_dcomp(b,m)>=0)
|
|
{
|
|
BIG_256_56_fshl(e,1);
|
|
BIG_256_56_dshl(m,1);
|
|
k++;
|
|
}
|
|
|
|
while (k>0)
|
|
{
|
|
BIG_256_56_dshr(m,1);
|
|
BIG_256_56_fshr(e,1);
|
|
|
|
BIG_256_56_dsub(dr,b,m);
|
|
BIG_256_56_dnorm(dr);
|
|
d=1-((dr[DNLEN_256_56-1]>>(CHUNK-1))&1);
|
|
BIG_256_56_dcmove(b,dr,d);
|
|
|
|
BIG_256_56_add(r,a,e);
|
|
BIG_256_56_norm(r);
|
|
BIG_256_56_cmove(a,r,d);
|
|
|
|
k--;
|
|
}
|
|
}
|
|
|
|
/* SU= 136 */
|
|
|
|
void BIG_256_56_sdiv(BIG_256_56 a,BIG_256_56 c)
|
|
{
|
|
int d,k=0;
|
|
BIG_256_56 m,e,b,r;
|
|
BIG_256_56_norm(a);
|
|
BIG_256_56_copy(b,a);
|
|
BIG_256_56_copy(m,c);
|
|
|
|
BIG_256_56_zero(a);
|
|
BIG_256_56_zero(e);
|
|
BIG_256_56_inc(e,1);
|
|
|
|
while (BIG_256_56_comp(b,m)>=0)
|
|
{
|
|
BIG_256_56_fshl(e,1);
|
|
BIG_256_56_fshl(m,1);
|
|
k++;
|
|
}
|
|
|
|
while (k>0)
|
|
{
|
|
BIG_256_56_fshr(m,1);
|
|
BIG_256_56_fshr(e,1);
|
|
|
|
BIG_256_56_sub(r,b,m);
|
|
BIG_256_56_norm(r);
|
|
d=1-((r[NLEN_256_56-1]>>(CHUNK-1))&1);
|
|
BIG_256_56_cmove(b,r,d);
|
|
|
|
BIG_256_56_add(r,a,e);
|
|
BIG_256_56_norm(r);
|
|
BIG_256_56_cmove(a,r,d);
|
|
k--;
|
|
}
|
|
}
|
|
|
|
/* return LSB of a */
|
|
int BIG_256_56_parity(BIG_256_56 a)
|
|
{
|
|
return a[0]%2;
|
|
}
|
|
|
|
/* return n-th bit of a */
|
|
/* SU= 16 */
|
|
int BIG_256_56_bit(BIG_256_56 a,int n)
|
|
{
|
|
if (a[n/BASEBITS_256_56]&((chunk)1<<(n%BASEBITS_256_56))) return 1;
|
|
else return 0;
|
|
}
|
|
|
|
/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
|
|
nbs is number of bits processed, and nzs is number of trailing 0s detected */
|
|
/* SU= 32 */
|
|
/*
|
|
int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs)
|
|
{
|
|
int j,r,nb;
|
|
|
|
nb=BIG_bit(x3,i)-BIG_bit(x,i);
|
|
*nbs=1;
|
|
*nzs=0;
|
|
if (nb==0) return 0;
|
|
if (i==0) return nb;
|
|
|
|
if (nb>0) r=1;
|
|
else r=(-1);
|
|
|
|
for (j=i-1;j>0;j--)
|
|
{
|
|
(*nbs)++;
|
|
r*=2;
|
|
nb=BIG_bit(x3,j)-BIG_bit(x,j);
|
|
if (nb>0) r+=1;
|
|
if (nb<0) r-=1;
|
|
if (abs(r)>5) break;
|
|
}
|
|
|
|
if (r%2!=0 && j!=0)
|
|
{ // backtrack
|
|
if (nb>0) r=(r-1)/2;
|
|
if (nb<0) r=(r+1)/2;
|
|
(*nbs)--;
|
|
}
|
|
|
|
while (r%2==0)
|
|
{ // remove trailing zeros
|
|
r/=2;
|
|
(*nzs)++;
|
|
(*nbs)--;
|
|
}
|
|
return r;
|
|
}
|
|
*/
|
|
|
|
/* return last n bits of a, where n is small < BASEBITS */
|
|
/* SU= 16 */
|
|
int BIG_256_56_lastbits(BIG_256_56 a,int n)
|
|
{
|
|
int msk=(1<<n)-1;
|
|
BIG_256_56_norm(a);
|
|
return ((int)a[0])&msk;
|
|
}
|
|
|
|
/* get 8*MODBYTES size random number */
|
|
void BIG_256_56_random(BIG_256_56 m,csprng *rng)
|
|
{
|
|
int i,b,j=0,r=0;
|
|
int len=8*MODBYTES_256_56;
|
|
|
|
BIG_256_56_zero(m);
|
|
/* generate random BIG */
|
|
for (i=0; i<len; i++)
|
|
{
|
|
if (j==0) r=RAND_byte(rng);
|
|
else r>>=1;
|
|
b=r&1;
|
|
BIG_256_56_shl(m,1);
|
|
m[0]+=b;
|
|
j++;
|
|
j&=7;
|
|
}
|
|
|
|
#ifdef DEBUG_NORM
|
|
m[MPV_256_56]=1;
|
|
m[MNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
/* get random BIG from rng, modulo q. Done one bit at a time, so its portable */
|
|
|
|
void BIG_256_56_randomnum(BIG_256_56 m,BIG_256_56 q,csprng *rng)
|
|
{
|
|
int i,b,j=0,r=0;
|
|
DBIG_256_56 d;
|
|
BIG_256_56_dzero(d);
|
|
/* generate random DBIG */
|
|
for (i=0; i<2*BIG_256_56_nbits(q); i++)
|
|
{
|
|
if (j==0) r=RAND_byte(rng);
|
|
else r>>=1;
|
|
b=r&1;
|
|
BIG_256_56_dshl(d,1);
|
|
d[0]+=b;
|
|
j++;
|
|
j&=7;
|
|
}
|
|
/* reduce modulo a BIG. Removes bias */
|
|
BIG_256_56_dmod(m,d,q);
|
|
#ifdef DEBUG_NORM
|
|
m[MPV_256_56]=1;
|
|
m[MNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|
|
/* Set r=a*b mod m */
|
|
/* SU= 96 */
|
|
void BIG_256_56_modmul(BIG_256_56 r,BIG_256_56 a,BIG_256_56 b,BIG_256_56 m)
|
|
{
|
|
DBIG_256_56 d;
|
|
BIG_256_56_mod(a,m);
|
|
BIG_256_56_mod(b,m);
|
|
|
|
BIG_256_56_mul(d,a,b);
|
|
BIG_256_56_dmod(r,d,m);
|
|
}
|
|
|
|
/* Set a=a*a mod m */
|
|
/* SU= 88 */
|
|
void BIG_256_56_modsqr(BIG_256_56 r,BIG_256_56 a,BIG_256_56 m)
|
|
{
|
|
DBIG_256_56 d;
|
|
BIG_256_56_mod(a,m);
|
|
BIG_256_56_sqr(d,a);
|
|
BIG_256_56_dmod(r,d,m);
|
|
}
|
|
|
|
/* Set r=-a mod m */
|
|
/* SU= 16 */
|
|
void BIG_256_56_modneg(BIG_256_56 r,BIG_256_56 a,BIG_256_56 m)
|
|
{
|
|
BIG_256_56_mod(a,m);
|
|
BIG_256_56_sub(r,m,a);
|
|
BIG_256_56_mod(r,m);
|
|
}
|
|
|
|
/* Set a=a/b mod m */
|
|
/* SU= 136 */
|
|
void BIG_256_56_moddiv(BIG_256_56 r,BIG_256_56 a,BIG_256_56 b,BIG_256_56 m)
|
|
{
|
|
DBIG_256_56 d;
|
|
BIG_256_56 z;
|
|
BIG_256_56_mod(a,m);
|
|
BIG_256_56_invmodp(z,b,m);
|
|
|
|
BIG_256_56_mul(d,a,z);
|
|
BIG_256_56_dmod(r,d,m);
|
|
}
|
|
|
|
/* Get jacobi Symbol (a/p). Returns 0, 1 or -1 */
|
|
/* SU= 216 */
|
|
int BIG_256_56_jacobi(BIG_256_56 a,BIG_256_56 p)
|
|
{
|
|
int n8,k,m=0;
|
|
BIG_256_56 t,x,n,zilch,one;
|
|
BIG_256_56_one(one);
|
|
BIG_256_56_zero(zilch);
|
|
if (BIG_256_56_parity(p)==0 || BIG_256_56_comp(a,zilch)==0 || BIG_256_56_comp(p,one)<=0) return 0;
|
|
BIG_256_56_norm(a);
|
|
BIG_256_56_copy(x,a);
|
|
BIG_256_56_copy(n,p);
|
|
BIG_256_56_mod(x,p);
|
|
|
|
while (BIG_256_56_comp(n,one)>0)
|
|
{
|
|
if (BIG_256_56_comp(x,zilch)==0) return 0;
|
|
n8=BIG_256_56_lastbits(n,3);
|
|
k=0;
|
|
while (BIG_256_56_parity(x)==0)
|
|
{
|
|
k++;
|
|
BIG_256_56_shr(x,1);
|
|
}
|
|
if (k%2==1) m+=(n8*n8-1)/8;
|
|
m+=(n8-1)*(BIG_256_56_lastbits(x,2)-1)/4;
|
|
BIG_256_56_copy(t,n);
|
|
|
|
BIG_256_56_mod(t,x);
|
|
BIG_256_56_copy(n,x);
|
|
BIG_256_56_copy(x,t);
|
|
m%=2;
|
|
|
|
}
|
|
if (m==0) return 1;
|
|
else return -1;
|
|
}
|
|
|
|
/* Set r=1/a mod p. Binary method */
|
|
/* SU= 240 */
|
|
void BIG_256_56_invmodp(BIG_256_56 r,BIG_256_56 a,BIG_256_56 p)
|
|
{
|
|
BIG_256_56 u,v,x1,x2,t,one;
|
|
BIG_256_56_mod(a,p);
|
|
BIG_256_56_copy(u,a);
|
|
BIG_256_56_copy(v,p);
|
|
BIG_256_56_one(one);
|
|
BIG_256_56_copy(x1,one);
|
|
BIG_256_56_zero(x2);
|
|
|
|
while (BIG_256_56_comp(u,one)!=0 && BIG_256_56_comp(v,one)!=0)
|
|
{
|
|
while (BIG_256_56_parity(u)==0)
|
|
{
|
|
BIG_256_56_shr(u,1);
|
|
if (BIG_256_56_parity(x1)!=0)
|
|
{
|
|
BIG_256_56_add(x1,p,x1);
|
|
BIG_256_56_norm(x1);
|
|
}
|
|
BIG_256_56_shr(x1,1);
|
|
}
|
|
while (BIG_256_56_parity(v)==0)
|
|
{
|
|
BIG_256_56_shr(v,1);
|
|
if (BIG_256_56_parity(x2)!=0)
|
|
{
|
|
BIG_256_56_add(x2,p,x2);
|
|
BIG_256_56_norm(x2);
|
|
}
|
|
BIG_256_56_shr(x2,1);
|
|
}
|
|
if (BIG_256_56_comp(u,v)>=0)
|
|
{
|
|
BIG_256_56_sub(u,u,v);
|
|
BIG_256_56_norm(u);
|
|
if (BIG_256_56_comp(x1,x2)>=0) BIG_256_56_sub(x1,x1,x2);
|
|
else
|
|
{
|
|
BIG_256_56_sub(t,p,x2);
|
|
BIG_256_56_add(x1,x1,t);
|
|
}
|
|
BIG_256_56_norm(x1);
|
|
}
|
|
else
|
|
{
|
|
BIG_256_56_sub(v,v,u);
|
|
BIG_256_56_norm(v);
|
|
if (BIG_256_56_comp(x2,x1)>=0) BIG_256_56_sub(x2,x2,x1);
|
|
else
|
|
{
|
|
BIG_256_56_sub(t,p,x1);
|
|
BIG_256_56_add(x2,x2,t);
|
|
}
|
|
BIG_256_56_norm(x2);
|
|
}
|
|
}
|
|
if (BIG_256_56_comp(u,one)==0)
|
|
BIG_256_56_copy(r,x1);
|
|
else
|
|
BIG_256_56_copy(r,x2);
|
|
}
|
|
|
|
/* set x = x mod 2^m */
|
|
void BIG_256_56_mod2m(BIG_256_56 x,int m)
|
|
{
|
|
int i,wd,bt;
|
|
chunk msk;
|
|
BIG_256_56_norm(x);
|
|
// if (m>=MODBITS) return;
|
|
wd=m/BASEBITS_256_56;
|
|
bt=m%BASEBITS_256_56;
|
|
msk=((chunk)1<<bt)-1;
|
|
x[wd]&=msk;
|
|
for (i=wd+1; i<NLEN_256_56; i++) x[i]=0;
|
|
}
|
|
|
|
// new
|
|
/* Convert to DBIG number from byte array of given length */
|
|
void BIG_256_56_dfromBytesLen(DBIG_256_56 a,char *b,int s)
|
|
{
|
|
int i,len=s;
|
|
BIG_256_56_dzero(a);
|
|
|
|
for (i=0; i<len; i++)
|
|
{
|
|
BIG_256_56_dshl(a,8);
|
|
a[0]+=(int)(unsigned char)b[i];
|
|
}
|
|
#ifdef DEBUG_NORM
|
|
a[DMPV_256_56]=1;
|
|
a[DMNV_256_56]=0;
|
|
#endif
|
|
}
|
|
|