http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/arch.h ---------------------------------------------------------------------- diff --git a/version22/c/arch.h b/version22/c/arch.h new file mode 100644 index 0000000..21753bd --- /dev/null +++ b/version22/c/arch.h @@ -0,0 +1,119 @@ +/* + 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. +*/ + +/* Architecture definition header file */ + +/** + * @file arch.h + * @author Mike Scott + * @date 23rd February 2016 + * @brief Architecture Header File + * + * Specify Processor Architecture + * + */ + +/* NOTE: There is only one user configurable section in this header - see below */ + +#ifndef ARCH_H +#define ARCH_H + + + + +/*** START OF USER CONFIGURABLE SECTION - set architecture ***/ + +#ifdef CMAKE +#define CHUNK @AMCL_CHUNK@ /**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */ +#else +#define CHUNK 32 /**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */ +#endif + +/*** END OF USER CONFIGURABLE SECTION ***/ + + + +/* Create Integer types */ +/* Support for C99? Note for GCC need to explicitly include -std=c99 in command line */ + +#if __STDC_VERSION__ >= 199901L +/* C99 code */ +#define C99 +#else +/* Not C99 code */ +#endif + +#ifndef C99 /* You are on your own! These are for Microsoft C */ +#define sign32 __int32 /**< 32-bit signed integer */ +#define sign8 signed char /**< 8-bit signed integer */ +#define unsign32 unsigned __int32 /**< 32-bit unsigned integer */ +#define unsign64 unsigned long long /**< 64-bit unsigned integer */ +#else +#include <stdint.h> +#define sign8 int8_t /**< 8-bit signed integer */ +#define sign32 int32_t /**< 32-bit signed integer */ +#define unsign32 uint32_t /**< 32-bit unsigned integer */ +#define unsign64 uint64_t /**< 64-bit unsigned integer */ +#endif + +#define uchar unsigned char /**< Unsigned char */ + +/* Don't mess with anything below this line unless you know what you are doing */ +/* This next is probably OK, but may need changing for non-C99-standard environments */ + +/* This next is probably OK, but may need changing for non-C99-standard environments */ + +#if CHUNK==16 +#ifndef C99 +#define chunk __int16 /**< C type corresponding to word length */ +#define dchunk __int32 /**< Always define double length chunk type if available */ +#else +#define chunk int16_t /**< C type corresponding to word length */ +#define dchunk int32_t /**< Always define double length chunk type if available */ +#endif +#endif + +#if CHUNK == 32 +#ifndef C99 +#define chunk __int32 /**< C type corresponding to word length */ +#define dchunk __int64 /**< Always define double length chunk type if available */ +#else +#define chunk int32_t /**< C type corresponding to word length */ +#define dchunk int64_t /**< Always define double length chunk type if available */ +#endif +#endif + +#if CHUNK == 64 + +#ifndef C99 +#define chunk __int64 /**< C type corresponding to word length */ +/**< Note - no 128-bit type available */ +#else +#define chunk int64_t /**< C type corresponding to word length */ +#ifdef __GNUC__ +#define dchunk __int128 /**< Always define double length chunk type if available - GCC supports 128 bit type ??? */ +#endif +#endif +#endif + +#ifdef dchunk +#define COMBA /**< Use COMBA method for faster BN muls, sqrs and reductions */ +#endif + +#endif
http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/benchtest_ec.c ---------------------------------------------------------------------- diff --git a/version22/c/benchtest_ec.c b/version22/c/benchtest_ec.c new file mode 100644 index 0000000..5929d0b --- /dev/null +++ b/version22/c/benchtest_ec.c @@ -0,0 +1,212 @@ +/* Test and benchmark elliptic curve and RSA functions + First build amcl.a from build_ec batch file + gcc -O3 benchtest_ec.c amcl.a -o benchtest_ec.exe +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include "amcl.h" +#include "rsa.h" + +#define MIN_TIME 10.0 +#define MIN_ITERS 10 + +int main() +{ + csprng RNG; + BIG s,r,x,y; + ECP P,G; + FP12 g; + int i,iterations; + clock_t start; + double elapsed; + char pr[10]; + unsigned long ran; + rsa_public_key pub; + rsa_private_key priv; + char m[RFS],d[RFS],c[RFS]; + octet M= {0,sizeof(m),m}; + octet D= {0,sizeof(d),d}; + octet C= {0,sizeof(c),c}; + +#if CHOICE==NIST256 + printf("NIST256 Curve\n"); +#endif +#if CHOICE==C25519 + printf("C25519 Curve\n"); +#endif +#if CHOICE==BRAINPOOL + printf("BRAINPOOL Curve\n"); +#endif +#if CHOICE==ANSSI + printf("ANSSI Curve\n"); +#endif +#if CHOICE==MF254 + printf("MF254 Curve\n"); +#endif +#if CHOICE==MS255 + printf("MS255 Curve\n"); +#endif +#if CHOICE==MF256 + printf("MF256 Curve\n"); +#endif +#if CHOICE==MS256 + printf("MS256 Curve\n"); +#endif +#if CHOICE==HIFIVE + printf("HIFIVE Curve\n"); +#endif +#if CHOICE==GOLDILOCKS + printf("GOLDILOCKS Curve\n"); +#endif +#if CHOICE==NIST384 + printf("NIST384 Curve\n"); +#endif +#if CHOICE==C41417 + printf("C41417 Curve\n"); +#endif +#if CHOICE==NIST521 + printf("NIST521 Curve\n"); +#endif + +#if CHOICE==BN254 + printf("BN254 Curve\n"); +#endif +#if CHOICE==BN454 + printf("BN454 Curve\n"); +#endif +#if CHOICE==BN646 + printf("BN646 Curve\n"); +#endif + +#if CHOICE==BN254_CX + printf("BN254_CX Curve\n"); +#endif +#if CHOICE==BN254_T + printf("BN254_T Curve\n"); +#endif +#if CHOICE==BN254_T2 + printf("BN254_T2 Curve\n"); +#endif +#if CHOICE==BLS455 + printf("BLS455 Curve\n"); +#endif +#if CHOICE==BLS383 + printf("BLS383 Curve\n"); +#endif + +#if CURVETYPE==WEIERSTRASS + printf("Weierstrass parameterization\n"); +#endif +#if CURVETYPE==EDWARDS + printf("Edwards parameterization\n"); +#endif +#if CURVETYPE==MONTGOMERY + printf("Montgomery parameterization\n"); +#endif + +#if CHUNK==16 + printf("16-bit Build\n"); +#endif +#if CHUNK==32 + printf("32-bit Build\n"); +#endif +#if CHUNK==64 + printf("64-bit Build\n"); +#endif + + time((time_t *)&ran); + pr[0]=ran; + pr[1]=ran>>8; + pr[2]=ran>>16; + pr[3]=ran>>24; + for (i=4;i<10;i++) pr[i]=i; + RAND_seed(&RNG,10,pr); + + BIG_rcopy(x,CURVE_Gx); +#if CURVETYPE!=MONTGOMERY + BIG_rcopy(y,CURVE_Gy); + ECP_set(&G,x,y); +#else + ECP_set(&G,x); +#endif + + BIG_rcopy(r,CURVE_Order); + BIG_randomnum(s,r,&RNG); + ECP_copy(&P,&G); + ECP_mul(&P,r); + + if (!ECP_isinf(&P)) + { + printf("FAILURE - rG!=O\n"); + return 0; + } + + iterations=0; + start=clock(); + do { + ECP_copy(&P,&G); + ECP_mul(&P,s); + + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("EC mul - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + printf("Generating %d-bit RSA public/private key pair\n",FFLEN*BIGBITS); + + iterations=0; + start=clock(); + do { + RSA_KEY_PAIR(&RNG,65537,&priv,&pub,NULL,NULL); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("RSA gen - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + //FF_randomnum(plain,pub.n,&RNG,FFLEN); + + M.len=RFS; + for (i=0;i<RFS;i++) M.val[i]=i%128; + + iterations=0; + start=clock(); + do { + RSA_ENCRYPT(&pub,&M,&C); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("RSA enc - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + iterations=0; + start=clock(); + do { + RSA_DECRYPT(&priv,&C,&D); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("RSA dec - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + for (i=0;i<RFS;i++) + { + if (M.val[i]!=D.val[i]) + { + printf("FAILURE - RSA decryption\n"); + return 0; + } + } + + printf("All tests pass\n"); + + return 0; +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/benchtest_pair.c ---------------------------------------------------------------------- diff --git a/version22/c/benchtest_pair.c b/version22/c/benchtest_pair.c new file mode 100644 index 0000000..c9dcf38 --- /dev/null +++ b/version22/c/benchtest_pair.c @@ -0,0 +1,257 @@ +/* Test and benchmark pairing functions + First build amcl.a from build_pair batch file + gcc -O3 benchtest_pair.c amcl.a -o benchtest_pair.exe +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include "amcl.h" /* Make sure and select a pairing-friendly curve in here! */ + +#define MIN_TIME 10.0 +#define MIN_ITERS 10 + +int main() +{ + csprng RNG; + BIG q,s,r,x,y,a,b,m; + ECP P,G; + FP2 wx,wy,f; + FP4 c,cp,cpm1,cpm2,cr; + ECP2 Q,W; + FP12 g,w; + unsigned long ran; + + int i,iterations; + clock_t start; + double elapsed; + char pr[10]; + +#if CHOICE==BN254 + printf("BN254 Curve\n"); +#endif +#if CHOICE==BN454 + printf("BN454 Curve\n"); +#endif +#if CHOICE==BN646 + printf("BN646 Curve\n"); +#endif + +#if CHOICE==BN254_CX + printf("BN254_CX Curve\n"); +#endif +#if CHOICE==BN254_T + printf("BN254_T Curve\n"); +#endif +#if CHOICE==BN254_T2 + printf("BN254_T2 Curve\n"); +#endif +#if CHOICE==BLS455 + printf("BLS455 Curve\n"); +#endif +#if CHOICE==BLS383 + printf("BLS383 Curve\n"); +#endif + +#if CHUNK==16 + printf("16-bit Build\n"); +#endif +#if CHUNK==32 + printf("32-bit Build\n"); +#endif +#if CHUNK==64 + printf("64-bit Build\n"); +#endif + + time((time_t *)&ran); + pr[0]=ran; + pr[1]=ran>>8; + pr[2]=ran>>16; + pr[3]=ran>>24; + for (i=4;i<10;i++) pr[i]=i; + + RAND_seed(&RNG,10,pr); + + BIG_rcopy(x,CURVE_Gx); + + BIG_rcopy(y,CURVE_Gy); + ECP_set(&G,x,y); + + + BIG_rcopy(r,CURVE_Order); + BIG_randomnum(s,r,&RNG); + ECP_copy(&P,&G); + PAIR_G1mul(&P,r); + + if (!ECP_isinf(&P)) + { + printf("FAILURE - rG!=O\n"); + return 0; + } + + iterations=0; + start=clock(); + do { + ECP_copy(&P,&G); + PAIR_G1mul(&P,s); + + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("G1 mul - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + + BIG_rcopy(wx.a,CURVE_Pxa); FP_nres(wx.a); + BIG_rcopy(wx.b,CURVE_Pxb); FP_nres(wx.b); + BIG_rcopy(wy.a,CURVE_Pya); FP_nres(wy.a); + BIG_rcopy(wy.b,CURVE_Pyb); FP_nres(wy.b); + ECP2_set(&W,&wx,&wy); + + ECP2_copy(&Q,&W); + ECP2_mul(&Q,r); + + if (!ECP2_isinf(&Q)) + { + printf("FAILURE - rQ!=O\n"); + return 0; + } + + iterations=0; + start=clock(); + do { + ECP2_copy(&Q,&W); + PAIR_G2mul(&Q,s); + + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("G2 mul - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + PAIR_ate(&w,&Q,&P); + PAIR_fexp(&w); + + FP12_copy(&g,&w); + + PAIR_GTpow(&g,r); + + if (!FP12_isunity(&g)) + { + printf("FAILURE - g^r!=1\n"); + return 0; + } + + iterations=0; + start=clock(); + do { + FP12_copy(&g,&w); + PAIR_GTpow(&g,s); + + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("GT pow - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + BIG_rcopy(a,CURVE_Fra); + BIG_rcopy(b,CURVE_Frb); + FP2_from_BIGs(&f,a,b); + + BIG_rcopy(q,Modulus); + + BIG_copy(m,q); + BIG_mod(m,r); + + BIG_copy(a,s); + BIG_mod(a,m); + + BIG_copy(b,s); + BIG_sdiv(b,m); + + FP12_copy(&g,&w); + FP12_trace(&c,&g); + + FP12_frob(&g,&f); + FP12_trace(&cp,&g); + + FP12_conj(&w,&w); + FP12_mul(&g,&w); + + FP12_trace(&cpm1,&g); + FP12_mul(&g,&w); + FP12_trace(&cpm2,&g); + + iterations=0; + start=clock(); + do { + FP4_xtr_pow2(&cr,&cp,&c,&cpm1,&cpm2,a,b); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("GT pow (compressed) - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + iterations=0; + start=clock(); + do { + PAIR_ate(&w,&Q,&P); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("PAIRing ATE - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + iterations=0; + start=clock(); + do { + FP12_copy(&g,&w); + PAIR_fexp(&g); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("PAIRing FEXP - %8d iterations ",iterations); + printf(" %8.2lf ms per iteration\n",elapsed); + + ECP_copy(&P,&G); + ECP2_copy(&Q,&W); + + PAIR_G1mul(&P,s); + PAIR_ate(&g,&Q,&P); + PAIR_fexp(&g); + + ECP_copy(&P,&G); + + PAIR_G2mul(&Q,s); + PAIR_ate(&w,&Q,&P); + PAIR_fexp(&w); + + if (!FP12_equals(&g,&w)) + { + printf("FAILURE - e(sQ,p)!=e(Q,sP) \n"); + return 0; + } + + ECP2_copy(&Q,&W); + PAIR_ate(&g,&Q,&P); + PAIR_fexp(&g); + + PAIR_GTpow(&g,s); + + if (!FP12_equals(&g,&w)) + { + printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n"); + return 0; + } + + printf("All tests pass\n"); + + return 0; +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/big.c ---------------------------------------------------------------------- diff --git a/version22/c/big.c b/version22/c/big.c new file mode 100644 index 0000000..1fe6259 --- /dev/null +++ b/version22/c/big.c @@ -0,0 +1,1525 @@ +/* + 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 "amcl.h" + +/* Calculates x*y+c+*r */ + +#ifdef dchunk + +/* Method required to calculate x*y+c+r, bottom half in r, top half returned */ +chunk muladd(chunk x,chunk y,chunk c,chunk *r) +{ + dchunk prod=(dchunk)x*y+c+*r; + *r=(chunk)prod&BMASK; + return (chunk)(prod>>BASEBITS); +} + +#else + +/* No integer type available that can store double the wordlength */ +/* accumulate partial products */ + +chunk muladd(chunk x,chunk y,chunk c,chunk *r) +{ + chunk x0,x1,y0,y1; + chunk bot,top,mid,carry; + x0=x&HMASK; + x1=(x>>HBITS); + y0=y&HMASK; + y1=(y>>HBITS); + bot=x0*y0; + top=x1*y1; + mid=x0*y1+x1*y0; + x0=mid&HMASK1; + x1=(mid>>HBITS1); + bot+=x0<<HBITS; + bot+=*r; + bot+=c; + +#if HDIFF==1 + bot+=(top&HDIFF)<<(BASEBITS-1); + top>>=HDIFF; +#endif + + top+=x1; + carry=bot>>BASEBITS; + bot&=BMASK; + top+=carry; + + *r=bot; + return top; +} + +#endif + +/* + +// Alternative non Standard Solution required if no type available that can store double the wordlength +// The use of compiler intrinsics is permitted + + +#if CHUNK==64 +#ifdef _WIN64 +#include <intrin.h> + +static INLINE chunk muladd(chunk x,chunk y,chunk c,chunk *r) +{ + chunk t,e; + uchunk b; + b=_mul128(x,y,&t); + e=c+*r; + b+=e; +// make correction for possible carry to top half + if (e<0) + t-=(b>e); + else + t+=(b<e); + + *r=b&MASK; + return (chunk)((t<<(CHUNK-BASEBITS)) | (b>>BASEBITS)); +} + +#endif +#endif + +*/ + +/* test a=0? */ +int BIG_iszilch(BIG a) +{ + int i; + for (i=0; i<NLEN; i++) + if (a[i]!=0) return 0; + return 1; +} + +/* test a=0? */ +int BIG_diszilch(DBIG a) +{ + int i; + for (i=0; i<DNLEN; i++) + if (a[i]!=0) return 0; + return 1; +} + +/* SU= 56 */ +/* output a */ +void BIG_output(BIG a) +{ + BIG b; + int i,len; + len=BIG_nbits(a); + if (len%4==0) len/=4; + else + { + len/=4; + len++; + } + if (len<MODBYTES*2) len=MODBYTES*2; + + for (i=len-1; i>=0; i--) + { + BIG_copy(b,a); + BIG_shr(b,i*4); + printf("%01x",(unsigned int) b[0]&15); + } +} + +/* SU= 16 */ +void BIG_rawoutput(BIG a) +{ + int i; + printf("("); + for (i=0; i<NLEN-1; i++) +#if CHUNK==64 + printf("%"PRIxMAX",",(uint64_t) a[i]); + printf("%"PRIxMAX")",(uint64_t) a[NLEN-1]); +#else + printf("%x,",(unsigned int) a[i]); + printf("%x)",(unsigned int) a[NLEN-1]); +#endif +} +/* +void BIG_rawdoutput(DBIG a) +{ + int i; + printf("("); + for (i=0;i<DNLEN-1;i++) +#if CHUNK==64 + printf("%llx,",(long long unsigned int) a[i]); + printf("%llx)",(long long unsigned int) a[DNLEN-1]); +#else + printf("%x,",(unsigned int) a[i]); + printf("%x)",(unsigned int) a[NLEN-1]); +#endif +} +*/ +/* Swap a and b if d=1 */ +void BIG_cswap(BIG a,BIG b,int d) +{ + int i; + chunk t,c=d; + c=~(c-1); +#ifdef DEBUG_NORM + for (i=0; i<=NLEN; i++) +#else + for (i=0; i<NLEN; i++) +#endif + { + t=c&(a[i]^b[i]); + a[i]^=t; + b[i]^=t; + } +} + +/* Move b to a if d=1 */ +void BIG_cmove(BIG f,BIG g,int d) +{ + int i; + chunk b=(chunk)-d; +#ifdef DEBUG_NORM + for (i=0; i<=NLEN; i++) +#else + for (i=0; i<NLEN; i++) +#endif + { + f[i]^=(f[i]^g[i])&b; + } +} + +/* Move g to f if d=1 */ +void BIG_dcmove(DBIG f,DBIG g,int d) +{ + int i; + chunk b=(chunk)-d; +#ifdef DEBUG_NORM + for (i=0; i<=DNLEN; i++) +#else + for (i=0; i<DNLEN; i++) +#endif + { + f[i]^=(f[i]^g[i])&b; + } +} + +/* convert BIG to/from bytes */ +/* SU= 64 */ +void BIG_toBytes(char *b,BIG a) +{ + int i; + BIG c; + BIG_norm(a); + BIG_copy(c,a); + for (i=MODBYTES-1; i>=0; i--) + { + b[i]=c[0]&0xff; + BIG_fshr(c,8); + } +} + +/* SU= 16 */ +void BIG_fromBytes(BIG a,char *b) +{ + int i; + BIG_zero(a); + for (i=0; i<MODBYTES; i++) + { + BIG_fshl(a,8); + a[0]+=(int)(unsigned char)b[i]; + //BIG_inc(a,(int)(unsigned char)b[i]); BIG_norm(a); + } +#ifdef DEBUG_NORM + a[NLEN]=0; +#endif +} + +void BIG_fromBytesLen(BIG a,char *b,int s) +{ + int i,len=s; + BIG_zero(a); + + if (s>MODBYTES) s=MODBYTES; + for (i=0; i<len; i++) + { + BIG_fshl(a,8); + a[0]+=(int)(unsigned char)b[i]; + } +#ifdef DEBUG_NORM + a[NLEN]=0; +#endif +} + + + +/* SU= 88 */ +void BIG_doutput(DBIG a) +{ + DBIG b; + int i,len; + BIG_dnorm(a); + len=BIG_dnbits(a); + if (len%4==0) len/=4; + else + { + len/=4; + len++; + } + + for (i=len-1; i>=0; i--) + { + BIG_dcopy(b,a); + BIG_dshr(b,i*4); + printf("%01x",(unsigned int) b[0]&15); + } +} + +/* Copy b=a */ +void BIG_copy(BIG b,BIG a) +{ + int i; + for (i=0; i<NLEN; i++) + b[i]=a[i]; +#ifdef DEBUG_NORM + b[NLEN]=a[NLEN]; +#endif +} + +/* Copy from ROM b=a */ +void BIG_rcopy(BIG b,const BIG a) +{ + int i; + for (i=0; i<NLEN; i++) + b[i]=a[i]; +#ifdef DEBUG_NORM + b[NLEN]=0; +#endif +} + +/* double length DBIG copy b=a */ +void BIG_dcopy(DBIG b,DBIG a) +{ + int i; + for (i=0; i<DNLEN; i++) + b[i]=a[i]; +#ifdef DEBUG_NORM + b[DNLEN]=a[DNLEN]; +#endif +} + +/* Copy BIG to bottom half of DBIG */ +void BIG_dscopy(DBIG b,BIG a) +{ + int i; + for (i=0; i<NLEN-1; i++) + b[i]=a[i]; + + b[NLEN-1]=a[NLEN-1]&BMASK; /* top word normalized */ + b[NLEN]=a[NLEN-1]>>BASEBITS; + + for (i=NLEN+1; i<DNLEN; i++) b[i]=0; +#ifdef DEBUG_NORM + b[DNLEN]=a[NLEN]; +#endif +} + +/* Copy BIG to top half of DBIG */ +void BIG_dsucopy(DBIG b,BIG a) +{ + int i; + for (i=0; i<NLEN; i++) + b[i]=0; + for (i=NLEN; i<DNLEN; i++) + b[i]=a[i-NLEN]; +#ifdef DEBUG_NORM + b[DNLEN]=a[NLEN]; +#endif +} + +/* Copy bottom half of DBIG to BIG */ +void BIG_sdcopy(BIG b,DBIG a) +{ + int i; + for (i=0; i<NLEN; i++) + b[i]=a[i]; +#ifdef DEBUG_NORM + b[NLEN]=a[DNLEN]; +#endif +} + +/* Copy top half of DBIG to BIG */ +void BIG_sducopy(BIG b,DBIG a) +{ + int i; + for (i=0; i<NLEN; i++) + b[i]=a[i+NLEN]; +#ifdef DEBUG_NORM + b[NLEN]=a[DNLEN]; +#endif +} + +/* Set a=0 */ +void BIG_zero(BIG a) +{ + int i; + for (i=0; i<NLEN; i++) + a[i]=0; +#ifdef DEBUG_NORM + a[NLEN]=0; +#endif +} + +void BIG_dzero(DBIG a) +{ + int i; + for (i=0; i<DNLEN; i++) + a[i]=0; +#ifdef DEBUG_NORM + a[DNLEN]=0; +#endif +} + +/* set a=1 */ +void BIG_one(BIG a) +{ + int i; + a[0]=1; + for (i=1; i<NLEN; i++) + a[i]=0; +#ifdef DEBUG_NORM + a[NLEN]=0; +#endif +} + + + +/* Set c=a+b */ +/* SU= 8 */ +void BIG_add(BIG c,BIG a,BIG b) +{ + int i; + for (i=0; i<NLEN; i++) + c[i]=a[i]+b[i]; +#ifdef DEBUG_NORM + c[NLEN]=a[NLEN]+b[NLEN]+1; + if (c[NLEN]>=NEXCESS) printf("add problem - digit overflow %d\n",c[NLEN]); +#endif +} + +/* Set c=c+d */ +void BIG_inc(BIG c,int d) +{ + BIG_norm(c); + c[0]+=(chunk)d; +#ifdef DEBUG_NORM + c[NLEN]=1; +#endif +} + +/* Set c=a-b */ +/* SU= 8 */ +void BIG_sub(BIG c,BIG a,BIG b) +{ + int i; + for (i=0; i<NLEN; i++) + c[i]=a[i]-b[i]; +#ifdef DEBUG_NORM + c[NLEN]=a[NLEN]+b[NLEN]+1; + if (c[NLEN]>=NEXCESS) printf("sub problem - digit overflow %d\n",c[NLEN]); +#endif +} + +/* SU= 8 */ + +void BIG_dsub(DBIG c,DBIG a,DBIG b) +{ + int i; + for (i=0; i<DNLEN; i++) + c[i]=a[i]-b[i]; +#ifdef DEBUG_NORM + c[DNLEN]=a[DNLEN]+b[DNLEN]+1; + if (c[DNLEN]>=NEXCESS) printf("sub problem - digit overflow %d\n",c[DNLEN]); +#endif +} + + +/* Set c=c-1 */ +void BIG_dec(BIG c,int d) +{ + BIG_norm(c); + c[0]-=(chunk)d; +#ifdef DEBUG_NORM + c[NLEN]=1; +#endif +} + +/* multiplication r=a*c by c<=NEXCESS */ +void BIG_imul(BIG r,BIG a,int c) +{ + int i; + for (i=0; i<NLEN; i++) r[i]=a[i]*c; +#ifdef DEBUG_NORM + r[NLEN]=(a[NLEN]+1)*c-1; + if (r[NLEN]>=NEXCESS) printf("int mul problem - digit overflow %d\n",r[NLEN]); +#endif +} + +/* multiplication r=a*c by larger integer - c<=FEXCESS */ +/* SU= 24 */ +chunk BIG_pmul(BIG r,BIG a,int c) +{ + int i; + chunk ak,carry=0; + BIG_norm(a); + for (i=0; i<NLEN; i++) + { + ak=a[i]; + r[i]=0; + carry=muladd(ak,(chunk)c,carry,&r[i]); + } +#ifdef DEBUG_NORM + r[NLEN]=0; +#endif + return carry; +} + +/* r/=3 */ +/* SU= 16 */ +int BIG_div3(BIG r) +{ + int i; + chunk ak,base,carry=0; + BIG_norm(r); + base=((chunk)1<<BASEBITS); + for (i=NLEN-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_pxmul(DBIG c,BIG a,int b) +{ + int j; + chunk carry; + BIG_dzero(c); + carry=0; + for (j=0; j<NLEN; j++) + carry=muladd(a[j],(chunk)b,carry,&c[j]); + c[NLEN]=carry; +#ifdef DEBUG_NORM + c[DNLEN]=0; +#endif +} + +/* .. if you know the result will fit in a BIG, c must be distinct from a and b */ +/* SU= 40 */ +void BIG_smul(BIG c,BIG a,BIG b) +{ + int i,j; + chunk carry; + BIG_norm(a); + BIG_norm(b); + + BIG_zero(c); + for (i=0; i<NLEN; i++) + { + carry=0; + for (j=0; j<NLEN; j++) + { + if (i+j<NLEN) + carry=muladd(a[i],b[j],carry,&c[i+j]); + } + } +#ifdef DEBUG_NORM + c[NLEN]=0; +#endif +} + +/* Set c=a*b */ +/* SU= 72 */ +void BIG_mul(DBIG c,BIG a,BIG b) +{ + int i; +#ifdef dchunk + dchunk t,co; + dchunk s; + dchunk d[NLEN]; + int k; +#endif + + /* change here - a and b MUST be normed on input */ + +// BIG_norm(a); /* needed here to prevent overflow from addition of partial products */ +// BIG_norm(b); + + /* 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; i++) + d[i]=(dchunk)a[i]*b[i]; + + s=d[0]; + t=s; + c[0]=(chunk)t&BMASK; + co=t>>BASEBITS; + + for (k=1; k<NLEN; 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; + co=t>>BASEBITS; + } + for (k=NLEN; k<2*NLEN-1; k++) + { + s-=d[k-NLEN]; + t=co+s; + for (i=NLEN-1; i>=1+k/2; i--) t+=(dchunk)(a[i]-a[k-i])*(b[k-i]-b[i]); + c[k]=(chunk)t&BMASK; + co=t>>BASEBITS; + } + c[2*NLEN-1]=(chunk)co; + +#endif + +#else + int j; + chunk carry; + BIG_dzero(c); + for (i=0; i<NLEN; i++) + { + carry=0; + for (j=0; j<NLEN; j++) + carry=muladd(a[i],b[j],carry,&c[i+j]); + + c[NLEN+i]=carry; + } + +#endif + +#ifdef DEBUG_NORM + c[DNLEN]=0; +#endif +} + +/* Set c=a*a */ +/* SU= 80 */ +void BIG_sqr(DBIG c,BIG a) +{ + int i,j,last; +#ifdef dchunk + dchunk t,co; +#endif + + /* change here - a MUST be normed on input */ +// BIG_norm(a); + + /* 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; + co=t>>BASEBITS; + t=(dchunk)a[1]*a[0]; + t+=t; + t+=co; + c[1]=(chunk)t&BMASK; + co=t>>BASEBITS; + + last=NLEN-NLEN%2; + for (j=2; j<last; j+=2) + { + 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; + co=t>>BASEBITS; + t=(dchunk)a[j+1]*a[0]; + for (i=1; i<(j+2)/2; i++) t+=(dchunk)a[j+1-i]*a[i]; + t+=t; + t+=co; + c[j+1]=(chunk)t&BMASK; + co=t>>BASEBITS; + } + j=last; +#if NLEN%2==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; + t+=(dchunk)a[j/2]*a[j/2]; + c[j]=(chunk)t&BMASK; + co=t>>BASEBITS; + j++; + t=(dchunk)a[NLEN-1]*a[j-NLEN+1]; + for (i=j-NLEN+2; i<(j+1)/2; i++) t+=(dchunk)a[j-i]*a[i]; + t+=t; + t+=co; + c[j]=(chunk)t&BMASK; + co=t>>BASEBITS; + j++; +#endif + for (; j<DNLEN-2; j+=2) + { + t=(dchunk)a[NLEN-1]*a[j-NLEN+1]; + for (i=j-NLEN+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; + co=t>>BASEBITS; + t=(dchunk)a[NLEN-1]*a[j-NLEN+2]; + for (i=j-NLEN+3; i<(j+2)/2; i++) t+=(dchunk)a[j+1-i]*a[i]; + t+=t; + t+=co; + c[j+1]=(chunk)t&BMASK; + co=t>>BASEBITS; + } + + t=(dchunk)a[NLEN-1]*a[NLEN-1]+co; + c[DNLEN-2]=(chunk)t&BMASK; + co=t>>BASEBITS; + c[DNLEN-1]=(chunk)co; +#endif + +#else + chunk carry; + BIG_dzero(c); + for (i=0; i<NLEN; i++) + { + carry=0; + for (j=i+1; j<NLEN; j++) + carry=muladd(a[i],a[j],carry,&c[i+j]); + c[NLEN+i]=carry; + } + + for (i=0; i<DNLEN; i++) c[i]*=2; + + for (i=0; i<NLEN; i++) + c[2*i+1]+=muladd(a[i],a[i],0,&c[2*i]); + + BIG_dnorm(c); +#endif + + +#ifdef DEBUG_NORM + c[DNLEN]=0; +#endif + +} + +/* Montgomery reduction */ +void BIG_monty(BIG a,BIG md,chunk MC,DBIG d) +{ + int i,k; + +#ifdef dchunk + dchunk t,c,s; + dchunk dd[NLEN]; + chunk v[NLEN]; +#endif + +#ifdef COMBA + +#ifdef UNWOUND + + /* Insert output of faster.c here */ + +#else + + t=d[0]; + v[0]=((chunk)t*MC)&BMASK; + t+=(dchunk)v[0]*md[0]; + c=(t>>BASEBITS)+d[1]; + s=0; + + for (k=1; k<NLEN; 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; + t+=(dchunk)v[k]*md[0]; + c=(t>>BASEBITS)+d[k+1]; + dd[k]=(dchunk)v[k]*md[k]; + s+=dd[k]; + } + for (k=NLEN; k<2*NLEN-1; k++) + { + t=c+s; + for (i=NLEN-1; i>=1+k/2; i--) t+=(dchunk)(v[k-i]-v[i])*(md[i]-md[k-i]); + a[k-NLEN]=(chunk)t&BMASK; + c=(t>>BASEBITS)+d[k+1]; + s-=dd[k-NLEN+1]; + } + a[NLEN-1]=(chunk)c&BMASK; + +#endif + +#ifdef DEBUG_NORM + a[NLEN]=0; +#endif + +#else + int j; + chunk m,carry; + for (i=0; i<NLEN; i++) + { + if (MC==-1) m=(-d[i])&BMASK; + else + { + if (MC==1) m=d[i]; + else m=(MC*d[i])&BMASK; + } + carry=0; + for (j=0; j<NLEN; j++) + carry=muladd(m,md[j],carry,&d[i+j]); + d[NLEN+i]+=carry; + } + BIG_sducopy(a,d); + BIG_norm(a); + +#endif +} + +/* General shift left of a by n bits */ +/* a MUST be normalised */ +/* SU= 32 */ +void BIG_shl(BIG a,int k) +{ + int i; + int n=k%BASEBITS; + int m=k/BASEBITS; + +// a[NLEN-1]=((a[NLEN-1-m]<<n))|(a[NLEN-m-2]>>(BASEBITS-n)); + + a[NLEN-1]=((a[NLEN-1-m]<<n)); + if (NLEN>=m+2) a[NLEN-1]|=(a[NLEN-m-2]>>(BASEBITS-n)); + + for (i=NLEN-2; i>m; i--) + a[i]=((a[i-m]<<n)&BMASK)|(a[i-m-1]>>(BASEBITS-n)); + a[m]=(a[0]<<n)&BMASK; + 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_fshl(BIG a,int n) +{ + int i; + + a[NLEN-1]=((a[NLEN-1]<<n))|(a[NLEN-2]>>(BASEBITS-n)); /* top word not masked */ + for (i=NLEN-2; i>0; i--) + a[i]=((a[i]<<n)&BMASK)|(a[i-1]>>(BASEBITS-n)); + a[0]=(a[0]<<n)&BMASK; + + return (int)(a[NLEN-1]>>((8*MODBYTES)%BASEBITS)); /* 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_dshl(DBIG a,int k) +{ + int i; + int n=k%BASEBITS; + int m=k/BASEBITS; + + a[DNLEN-1]=((a[DNLEN-1-m]<<n))|(a[DNLEN-m-2]>>(BASEBITS-n)); + + for (i=DNLEN-2; i>m; i--) + a[i]=((a[i-m]<<n)&BMASK)|(a[i-m-1]>>(BASEBITS-n)); + a[m]=(a[0]<<n)&BMASK; + for (i=0; i<m; i++) a[i]=0; + +} + +/* General shift rightof a by k bits */ +/* a MUST be normalised */ +/* SU= 32 */ +void BIG_shr(BIG a,int k) +{ + int i; + int n=k%BASEBITS; + int m=k/BASEBITS; + for (i=0; i<NLEN-m-1; i++) + a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS-n))&BMASK); + if (NLEN>m) a[NLEN-m-1]=a[NLEN-1]>>n; + for (i=NLEN-m; i<NLEN; i++) a[i]=0; + +} + +/* Faster shift right of a by k bits. Return shifted out part */ +/* a MUST be normalised */ +/* SU= 16 */ +int BIG_fshr(BIG a,int k) +{ + int i; + chunk r=a[0]&(((chunk)1<<k)-1); /* shifted out part */ + for (i=0; i<NLEN-1; i++) + a[i]=(a[i]>>k)|((a[i+1]<<(BASEBITS-k))&BMASK); + a[NLEN-1]=a[NLEN-1]>>k; + return (int)r; +} + +/* double length right shift of a by k bits - can be > BASEBITS */ +/* SU= 32 */ +void BIG_dshr(DBIG a,int k) +{ + int i; + int n=k%BASEBITS; + int m=k/BASEBITS; + for (i=0; i<DNLEN-m-1; i++) + a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS-n))&BMASK); + a[DNLEN-m-1]=a[DNLEN-1]>>n; + for (i=DNLEN-m; i<DNLEN; 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_split(BIG t,BIG b,DBIG d,int n) +{ + int i; + chunk nw,carry=0; + int m=n%BASEBITS; +// BIG_dnorm(d); + + if (m==0) + { + for (i=0; i<NLEN; i++) b[i]=d[i]; + if (t!=b) + { + for (i=NLEN; i<2*NLEN; i++) t[i-NLEN]=d[i]; + carry=t[NLEN-1]>>BASEBITS; + t[NLEN-1]=t[NLEN-1]&BMASK; /* top word normalized */ + } + return carry; + } + + for (i=0; i<NLEN-1; i++) b[i]=d[i]; + + b[NLEN-1]=d[NLEN-1]&(((chunk)1<<m)-1); + + if (t!=b) + { + carry=(d[DNLEN-1]<<(BASEBITS-m)); + for (i=DNLEN-2; i>=NLEN-1; i--) + { + nw=(d[i]>>m)|carry; + carry=(d[i]<<(BASEBITS-m))&BMASK; + t[i-NLEN+1]=nw; + } + } +#ifdef DEBUG_NORM + t[NLEN]=0; + b[NLEN]=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_norm(BIG a) +{ + int i; + chunk d,carry=0; + for (i=0; i<NLEN-1; i++) + { + d=a[i]+carry; + a[i]=d&BMASK; + carry=d>>BASEBITS; + } + a[NLEN-1]=(a[NLEN-1]+carry); + +#ifdef DEBUG_NORM + a[NLEN]=0; +#endif + return (a[NLEN-1]>>((8*MODBYTES)%BASEBITS)); /* only used in ff.c */ +} + +void BIG_dnorm(DBIG a) +{ + int i; + chunk d,carry=0; + for (i=0; i<DNLEN-1; i++) + { + d=a[i]+carry; + a[i]=d&BMASK; + carry=d>>BASEBITS; + } + a[DNLEN-1]=(a[DNLEN-1]+carry); +#ifdef DEBUG_NORM + a[DNLEN]=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_comp(BIG a,BIG b) +{ + int i; + for (i=NLEN-1; i>=0; i--) + { + if (a[i]==b[i]) continue; + if (a[i]>b[i]) return 1; + else return -1; + } + return 0; +} + +int BIG_dcomp(DBIG a,DBIG b) +{ + int i; + for (i=DNLEN-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_nbits(BIG a) +{ + int bts,k=NLEN-1; + chunk c; + BIG_norm(a); + while (k>=0 && a[k]==0) k--; + if (k<0) return 0; + bts=BASEBITS*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_dnbits(DBIG a) +{ + int bts,k=DNLEN-1; + chunk c; + BIG_dnorm(a); + while (k>=0 && a[k]==0) k--; + if (k<0) return 0; + bts=BASEBITS*k; + c=a[k]; + while (c!=0) + { + c/=2; + bts++; + } + return bts; +} + + +/* Set b=b mod c */ +/* SU= 16 */ +void BIG_mod(BIG b,BIG c) +{ + int k=0; + BIG r; /**/ + + BIG_norm(b); + if (BIG_comp(b,c)<0) + return; + do + { + BIG_fshl(c,1); + k++; + } + while (BIG_comp(b,c)>=0); + + while (k>0) + { + BIG_fshr(c,1); + +// constant time... + BIG_sub(r,b,c); + BIG_norm(r); + BIG_cmove(b,r,1-((r[NLEN-1]>>(CHUNK-1))&1)); + /* + if (BIG_comp(b,c)>=0) + { + BIG_sub(b,b,c); + BIG_norm(b); + } + */ + k--; + } +} + +/* Set a=b mod c, b is destroyed. Slow but rarely used. */ +/* SU= 96 */ +void BIG_dmod(BIG a,DBIG b,BIG c) +{ + int k=0; + DBIG m,r; + BIG_dnorm(b); + BIG_dscopy(m,c); + + if (BIG_dcomp(b,m)<0) + { + BIG_sdcopy(a,b); + return; + } + + do + { + BIG_dshl(m,1); + k++; + } + while (BIG_dcomp(b,m)>=0); + + while (k>0) + { + BIG_dshr(m,1); +// constant time... + BIG_dsub(r,b,m); + BIG_dnorm(r); + BIG_dcmove(b,r,1-((r[DNLEN-1]>>(CHUNK-1))&1)); + /* + if (BIG_dcomp(b,m)>=0) + { + BIG_dsub(b,b,m); + BIG_dnorm(b); + } + */ + k--; + } + BIG_sdcopy(a,b); +} + +/* Set a=b/c, b is destroyed. Slow but rarely used. */ +/* SU= 136 */ + +void BIG_ddiv(BIG a,DBIG b,BIG c) +{ + int d,k=0; + DBIG m,dr; + BIG e,r; + BIG_dnorm(b); + BIG_dscopy(m,c); + + BIG_zero(a); + BIG_zero(e); + BIG_inc(e,1); + + while (BIG_dcomp(b,m)>=0) + { + BIG_fshl(e,1); + BIG_dshl(m,1); + k++; + } + + while (k>0) + { + BIG_dshr(m,1); + BIG_fshr(e,1); + + BIG_dsub(dr,b,m); + BIG_dnorm(dr); + d=1-((dr[DNLEN-1]>>(CHUNK-1))&1); + BIG_dcmove(b,dr,d); + + BIG_add(r,a,e); + BIG_norm(r); + BIG_cmove(a,r,d); + /* + if (BIG_dcomp(b,m)>=0) + { + BIG_add(a,a,e); + BIG_norm(a); + BIG_dsub(b,b,m); + BIG_dnorm(b); + } */ + k--; + } +} + +/* SU= 136 */ + +void BIG_sdiv(BIG a,BIG c) +{ + int d,k=0; + BIG m,e,b,r; + BIG_norm(a); + BIG_copy(b,a); + BIG_copy(m,c); + + BIG_zero(a); + BIG_zero(e); + BIG_inc(e,1); + + while (BIG_comp(b,m)>=0) + { + BIG_fshl(e,1); + BIG_fshl(m,1); + k++; + } + + while (k>0) + { + BIG_fshr(m,1); + BIG_fshr(e,1); + + BIG_sub(r,b,m); + BIG_norm(r); + d=1-((r[NLEN-1]>>(CHUNK-1))&1); + BIG_cmove(b,r,d); + + BIG_add(r,a,e); + BIG_norm(r); + BIG_cmove(a,r,d); + /* + if (BIG_comp(b,m)>=0) + { + BIG_sub(b,b,m); + BIG_norm(b); + BIG_add(a,a,e); + BIG_norm(a); + } */ + k--; + } +} + +/* return LSB of a */ +int BIG_parity(BIG a) +{ + return a[0]%2; +} + +/* return n-th bit of a */ +/* SU= 16 */ +int BIG_bit(BIG a,int n) +{ + if (a[n/BASEBITS]&((chunk)1<<(n%BASEBITS))) 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_lastbits(BIG a,int n) +{ + int msk=(1<<n)-1; + BIG_norm(a); + return ((int)a[0])&msk; +} + +/* get 8*MODBYTES size random number */ +void BIG_random(BIG m,csprng *rng) +{ + int i,b,j=0,r=0; + int len=8*MODBYTES; + + BIG_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_shl(m,1); + m[0]+=b; + j++; + j&=7; + } + +#ifdef DEBUG_NORM + m[NLEN]=0; +#endif +} + +/* get random BIG from rng, modulo q. Done one bit at a time, so its portable */ + +void BIG_randomnum(BIG m,BIG q,csprng *rng) +{ + int i,b,j=0,r=0; + DBIG d; + BIG_dzero(d); + /* generate random DBIG */ + for (i=0; i<2*MODBITS; i++) + { + if (j==0) r=RAND_byte(rng); + else r>>=1; + b=r&1; + BIG_dshl(d,1); + d[0]+=b; + j++; + j&=7; + } + /* reduce modulo a BIG. Removes bias */ + BIG_dmod(m,d,q); +#ifdef DEBUG_NORM + m[NLEN]=0; +#endif +} + +/* Set r=a*b mod m */ +/* SU= 96 */ +void BIG_modmul(BIG r,BIG a,BIG b,BIG m) +{ + DBIG d; + BIG_mod(a,m); + BIG_mod(b,m); +//BIG_norm(a); BIG_norm(b); + BIG_mul(d,a,b); + BIG_dmod(r,d,m); +} + +/* Set a=a*a mod m */ +/* SU= 88 */ +void BIG_modsqr(BIG r,BIG a,BIG m) +{ + DBIG d; + BIG_mod(a,m); +//BIG_norm(a); + BIG_sqr(d,a); + BIG_dmod(r,d,m); +} + +/* Set r=-a mod m */ +/* SU= 16 */ +void BIG_modneg(BIG r,BIG a,BIG m) +{ + BIG_mod(a,m); + BIG_sub(r,m,a); + BIG_mod(r,m); +} + +/* Set a=a/b mod m */ +/* SU= 136 */ +void BIG_moddiv(BIG r,BIG a,BIG b,BIG m) +{ + DBIG d; + BIG z; + BIG_mod(a,m); + BIG_invmodp(z,b,m); +//BIG_norm(a); BIG_norm(z); + BIG_mul(d,a,z); + BIG_dmod(r,d,m); +} + +/* Get jacobi Symbol (a/p). Returns 0, 1 or -1 */ +/* SU= 216 */ +int BIG_jacobi(BIG a,BIG p) +{ + int n8,k,m=0; + BIG t,x,n,zilch,one; + BIG_one(one); + BIG_zero(zilch); + if (BIG_parity(p)==0 || BIG_comp(a,zilch)==0 || BIG_comp(p,one)<=0) return 0; + BIG_norm(a); + BIG_copy(x,a); + BIG_copy(n,p); + BIG_mod(x,p); + + while (BIG_comp(n,one)>0) + { + if (BIG_comp(x,zilch)==0) return 0; + n8=BIG_lastbits(n,3); + k=0; + while (BIG_parity(x)==0) + { + k++; + BIG_shr(x,1); + } + if (k%2==1) m+=(n8*n8-1)/8; + m+=(n8-1)*(BIG_lastbits(x,2)-1)/4; + BIG_copy(t,n); + + BIG_mod(t,x); + BIG_copy(n,x); + BIG_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_invmodp(BIG r,BIG a,BIG p) +{ + BIG u,v,x1,x2,t,one; + BIG_mod(a,p); + BIG_copy(u,a); + BIG_copy(v,p); + BIG_one(one); + BIG_copy(x1,one); + BIG_zero(x2); + + while (BIG_comp(u,one)!=0 && BIG_comp(v,one)!=0) + { + while (BIG_parity(u)==0) + { + BIG_shr(u,1); + if (BIG_parity(x1)!=0) + { + BIG_add(x1,p,x1); + BIG_norm(x1); + } + BIG_shr(x1,1); + } + while (BIG_parity(v)==0) + { + BIG_shr(v,1); + if (BIG_parity(x2)!=0) + { + BIG_add(x2,p,x2); + BIG_norm(x2); + } + BIG_shr(x2,1); + } + if (BIG_comp(u,v)>=0) + { + BIG_sub(u,u,v); + BIG_norm(u); + if (BIG_comp(x1,x2)>=0) BIG_sub(x1,x1,x2); + else + { + BIG_sub(t,p,x2); + BIG_add(x1,x1,t); + } + BIG_norm(x1); + } + else + { + BIG_sub(v,v,u); + BIG_norm(v); + if (BIG_comp(x2,x1)>=0) BIG_sub(x2,x2,x1); + else + { + BIG_sub(t,p,x1); + BIG_add(x2,x2,t); + } + BIG_norm(x2); + } + } + if (BIG_comp(u,one)==0) + BIG_copy(r,x1); + else + BIG_copy(r,x2); +} + +/* set x = x mod 2^m */ +void BIG_mod2m(BIG x,int m) +{ + int i,wd,bt; + chunk msk; +// if (m>=MODBITS) return; + wd=m/BASEBITS; + bt=m%BASEBITS; + msk=((chunk)1<<bt)-1; + x[wd]&=msk; + for (i=wd+1; i<NLEN; i++) x[i]=0; +} + +// new +/* Convert to DBIG number from byte array of given length */ +void BIG_dfromBytesLen(DBIG a,char *b,int s) +{ + int i,len=s; + BIG_dzero(a); + + for (i=0; i<len; i++) + { + BIG_dshl(a,8); + a[0]+=(int)(unsigned char)b[i]; + } +#ifdef DEBUG_NORM + a[NLEN]=0; +#endif +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/build_ec ---------------------------------------------------------------------- diff --git a/version22/c/build_ec b/version22/c/build_ec new file mode 100644 index 0000000..b5dc735 --- /dev/null +++ b/version22/c/build_ec @@ -0,0 +1,22 @@ + +gcc -std=c99 -c -O3 big.c +gcc -std=c99 -c -O3 fp.c +gcc -std=c99 -c -O3 ecp.c +gcc -std=c99 -c -O3 hash.c +gcc -std=c99 -c -O3 rand.c +gcc -std=c99 -c -O3 aes.c +gcc -std=c99 -c -O3 gcm.c +gcc -std=c99 -c -O3 oct.c +gcc -std=c99 -c -O3 rom.c + +gcc -std=c99 -c -O3 ff.c + +rm amcl.a +ar rc amcl.a big.o fp.o ecp.o hash.o ff.o +ar r amcl.a rand.o aes.o gcm.o oct.o rom.o + +gcc -std=c99 -O3 testecdh.c ecdh.c randapi.c amcl.a -o testecdh +gcc -std=c99 -O3 testrsa.c rsa.c randapi.c amcl.a -o testrsa +gcc -std=c99 -O3 benchtest_ec.c rsa.c amcl.a -o benchtest_ec + +rm *.o http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/build_ec.bat ---------------------------------------------------------------------- diff --git a/version22/c/build_ec.bat b/version22/c/build_ec.bat new file mode 100644 index 0000000..a49fc25 --- /dev/null +++ b/version22/c/build_ec.bat @@ -0,0 +1,22 @@ + +gcc -std=c99 -c -O3 big.c +gcc -std=c99 -c -O3 fp.c +gcc -std=c99 -c -O3 ecp.c +gcc -std=c99 -c -O3 hash.c +gcc -std=c99 -c -O3 rand.c +gcc -std=c99 -c -O3 aes.c +gcc -std=c99 -c -O3 gcm.c +gcc -std=c99 -c -O3 oct.c +gcc -std=c99 -c -O3 rom.c + +gcc -std=c99 -c -O3 ff.c + +del amcl.a +ar rc amcl.a big.o fp.o ecp.o hash.o ff.o +ar r amcl.a rand.o aes.o gcm.o oct.o rom.o + +gcc -std=c99 -O3 testecdh.c ecdh.c randapi.c amcl.a -o testecdh.exe +gcc -std=c99 -O3 testrsa.c rsa.c randapi.c amcl.a -o testrsa.exe +gcc -std=c99 -O3 benchtest_ec.c rsa.c amcl.a -o benchtest_ec.exe + +del *.o http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/build_pair ---------------------------------------------------------------------- diff --git a/version22/c/build_pair b/version22/c/build_pair new file mode 100644 index 0000000..6b6bae2 --- /dev/null +++ b/version22/c/build_pair @@ -0,0 +1,27 @@ + +gcc -std=c99 -c -O3 big.c +gcc -std=c99 -c -O3 fp.c +gcc -std=c99 -c -O3 ecp.c +gcc -std=c99 -c -O3 hash.c +gcc -std=c99 -c -O3 rand.c +gcc -std=c99 -c -O3 aes.c +gcc -std=c99 -c -O3 gcm.c +gcc -std=c99 -c -O3 oct.c +gcc -std=c99 -c -O3 rom.c + +gcc -std=c99 -c -O3 fp2.c +gcc -std=c99 -c -O3 ecp2.c +gcc -std=c99 -c -O3 fp4.c +gcc -std=c99 -c -O3 fp12.c +gcc -std=c99 -c -O3 pair.c + +rm amcl.a +ar rc amcl.a big.o fp.o ecp.o hash.o +ar r amcl.a rand.o aes.o gcm.o oct.o rom.o + +ar r amcl.a pair.o fp2.o ecp2.o fp4.o fp12.o + +gcc -std=c99 -O3 testmpin.c mpin.c randapi.c amcl.a -o testmpin +gcc -std=c99 -O3 benchtest_pair.c amcl.a -o benchtest_pair + +rm *.o http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/build_pair.bat ---------------------------------------------------------------------- diff --git a/version22/c/build_pair.bat b/version22/c/build_pair.bat new file mode 100644 index 0000000..88b5daf --- /dev/null +++ b/version22/c/build_pair.bat @@ -0,0 +1,27 @@ + +gcc -std=c99 -c -O3 big.c +gcc -std=c99 -c -O3 fp.c +gcc -std=c99 -c -O3 ecp.c +gcc -std=c99 -c -O3 hash.c +gcc -std=c99 -c -O3 rand.c +gcc -std=c99 -c -O3 aes.c +gcc -std=c99 -c -O3 gcm.c +gcc -std=c99 -c -O3 oct.c +gcc -std=c99 -c -O3 rom.c + +gcc -std=c99 -c -O3 fp2.c +gcc -std=c99 -c -O3 ecp2.c +gcc -std=c99 -c -O3 fp4.c +gcc -std=c99 -c -O3 fp12.c +gcc -std=c99 -c -O3 pair.c + +del amcl.a +ar rc amcl.a big.o fp.o ecp.o hash.o +ar r amcl.a rand.o aes.o gcm.o oct.o rom.o + +ar r amcl.a pair.o fp2.o ecp2.o fp4.o fp12.o + +gcc -std=c99 -O3 testmpin.c mpin.c randapi.c amcl.a -o testmpin.exe +gcc -std=c99 -O3 benchtest_pair.c amcl.a -o benchtest_pair.exe + +del *.o http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/ca.crt ---------------------------------------------------------------------- diff --git a/version22/c/ca.crt b/version22/c/ca.crt new file mode 100644 index 0000000..e3ad02f --- /dev/null +++ b/version22/c/ca.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID6zCCAtOgAwIBAgIJALJxywTGMUA7MA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD +VQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMQ8wDQYD +VQQKDAZNSVJBQ0wxDTALBgNVBAsMBGxhYnMxEzARBgNVBAMMCk1pa2UgU2NvdHQx +JDAiBgkqhkiG9w0BCQEWFW1pa2Uuc2NvdHRAbWlyYWNsLmNvbTAeFw0xNjA2MzAx +NzQyNDFaFw0yMTA2MzAxNzQyNDFaMIGLMQswCQYDVQQGEwJJRTEQMA4GA1UECAwH +SXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMQ8wDQYDVQQKDAZNSVJBQ0wxDTALBgNV +BAsMBGxhYnMxEzARBgNVBAMMCk1pa2UgU2NvdHQxJDAiBgkqhkiG9w0BCQEWFW1p +a2Uuc2NvdHRAbWlyYWNsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAPCTPcPWgiI0ka5Czd0ZzW+gTaMEe9QW7FGu5+9fS6ALrCpdbxdwDX8+OQXZ +uQJpLYEAIq1pDh3fVQguH/jUM9gQQrS2Lmz3KhXC/J3yv85FRotCGv13ztapMedT +y2IxzbtPvoQQc+IAlUPX6DtD8JqBoAstrlQUnkMChKztMGR2OERdjNzXmXm+KMMP +lZzk+EvRwCornVA+SB5QAWj7y/3ISFo0y1WG8ewoQEx3HQYrjXbQP1VTdiLW7dHP +QP86XKoTMtTBEYWuFhKB9ClCeu4Qqqxqa9UPIVfdro7SoZScCt+OX4KhzLnOCFup +oLxE+yTDhDpYcCcmI1yglCv9DpMCAwEAAaNQME4wHQYDVR0OBBYEFFH18YEMoxms +7121N/nQ+Wm3b5smMB8GA1UdIwQYMBaAFFH18YEMoxms7121N/nQ+Wm3b5smMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBALCUob0y2O4DSzsqG76yrtCx +XWxDdgjSkHKzwFK62BzZK5EuCDJrVgCyoLX0SvYvoT9x0wtS+bxJ7TNEGn7Rkp5/ +iSQCUSF7sVRoHqzErk70xVKKDy5FS+zre8k08nJrtRg2u1PmY95NO1SE96BtUVLs ++8rQuqEX283tqlmqE/SF2+lxOb0WaVrya4oCJfj/XT83pRTcd5w9i7huWltMbKba +gkmlQ/5q9Ayp/Jh1lLXmxr+/xEbZ2xEop/y+mgVF0vLxap7R5toBA0Yk7vvirlYv +0hZGqGi5lBc9VeUqm1H/7XCi5xRU3AtJ4QRk4Z1xUa4qAPKfiqlPKd1dVe3Ah3w= +-----END CERTIFICATE----- http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/eccert.pem ---------------------------------------------------------------------- diff --git a/version22/c/eccert.pem b/version22/c/eccert.pem new file mode 100644 index 0000000..b9dfca5 --- /dev/null +++ b/version22/c/eccert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICqjCCAZICCQCk9jKdJYtnjDANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMC +SUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEPMA0GA1UECgwG +TUlSQUNMMQ0wCwYDVQQLDARsYWJzMRMwEQYDVQQDDApNaWtlIFNjb3R0MSQwIgYJ +KoZIhvcNAQkBFhVtaWtlLnNjb3R0QG1pcmFjbC5jb20wHhcNMTYwNjMwMTc0NjQ4 +WhcNMTYwNzMwMTc0NjQ4WjCBjDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxh +bmQxDzANBgNVBAcMBkR1YmxpbjEPMA0GA1UECgwGTUlSQUNMMQ0wCwYDVQQLDARs +YWJzMRgwFgYDVQQDDA9LZWFsYW4gTWNDdXNrZXIxIDAeBgkqhkiG9w0BCQEWEWtl +YWxhbkBtaXJhY2wuY29tMDkwFAYHKoZIzj0CAQYJKwYBBAHaRw8BAyEASiRQmhO9 +PP+SqodOhXYrnSlcyAOog63E6a4KLDFvAzEwDQYJKoZIhvcNAQELBQADggEBALBy +fCM/EhdqWBrEnDHtH2/U8xr1eSylHdcfnDSDR+X6KXH5rIJ/397lZQMHB6QSsEiV +rWzfFDFPPjDN3xEDsZw09ZTT+L8Wi5P3UKR1gtawQCx3ciKEywAU1CU2dV05gvye +bqIsbFUyH7jOlj6/1hIx9zaiLcoEex6D55MYQuWo664HF3CNdJFk1k4HF+fclRhy +l4iryp0F9p0Wl5vyn96kg0NwaBZG860oCWDHZsjRq1JeSSaRf9CKNXWbQwjByeEc +DphpprqmoVcI60cC0TvZZm1x4y7vjCXLD6uCDw3P7fnSp40yce64+IKUr8/cS+QY +us58KHdLaLXsojZHL3c= +-----END CERTIFICATE----- http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/ecdh.c ---------------------------------------------------------------------- diff --git a/version22/c/ecdh.c b/version22/c/ecdh.c new file mode 100644 index 0000000..74694f7 --- /dev/null +++ b/version22/c/ecdh.c @@ -0,0 +1,751 @@ +/* +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. +*/ + +/* ECDH/ECIES/ECDSA Functions - see main program below */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> + +#include "ecdh.h" + +#define ROUNDUP(a,b) ((a)-1)/(b)+1 + +/* general purpose hash function w=hash(p|n|x|y) */ +/* pad or truncate ouput to length pad if pad!=0 */ +static void hashit(int sha,octet *p,int n,octet *x,octet *w,int pad) +{ + int i,c[4],hlen; + hash256 sha256; + hash512 sha512; + char hh[64]; + + switch (sha) + { + case SHA256: + HASH256_init(&sha256); + break; + case SHA384: + HASH384_init(&sha512); + break; + case SHA512: + HASH512_init(&sha512); + break; + } + + hlen=sha; + + for (i=0; i<p->len; i++) + { + switch(sha) + { + case SHA256: + HASH256_process(&sha256,p->val[i]); + break; + case SHA384: + HASH384_process(&sha512,p->val[i]); + break; + case SHA512: + HASH512_process(&sha512,p->val[i]); + break; + } + } + if (n>0) + { + c[0]=(n>>24)&0xff; + c[1]=(n>>16)&0xff; + c[2]=(n>>8)&0xff; + c[3]=(n)&0xff; + for (i=0; i<4; i++) + { + switch(sha) + { + case SHA256: + HASH256_process(&sha256,c[i]); + break; + case SHA384: + HASH384_process(&sha512,c[i]); + break; + case SHA512: + HASH512_process(&sha512,c[i]); + break; + } + } + } + if (x!=NULL) for (i=0; i<x->len; i++) + { + switch(sha) + { + case SHA256: + HASH256_process(&sha256,x->val[i]); + break; + case SHA384: + HASH384_process(&sha512,x->val[i]); + break; + case SHA512: + HASH512_process(&sha512,x->val[i]); + break; + } + } + + switch (sha) + { + case SHA256: + HASH256_hash(&sha256,hh); + break; + case SHA384: + HASH384_hash(&sha512,hh); + break; + case SHA512: + HASH512_hash(&sha512,hh); + break; + } + + OCT_empty(w); + if (!pad) + OCT_jbytes(w,hh,hlen); + else + { + if (pad<=hlen) + OCT_jbytes(w,hh,pad); + else + { + OCT_jbytes(w,hh,hlen); + OCT_jbyte(w,0,pad-hlen); + } + } + return; +} + +/* Hash octet p to octet w */ +void HASH(int sha,octet *p,octet *w) +{ + hashit(sha,p,-1,NULL,w,0); +} + +/* Calculate HMAC of m using key k. HMAC is tag of length olen */ +int HMAC(int sha,octet *m,octet *k,int olen,octet *tag) +{ + /* Input is from an octet m * + * olen is requested output length in bytes. k is the key * + * The output is the calculated tag */ + int hlen,b; + char h[128],k0[128]; + octet H= {0,sizeof(h),h}; + octet K0= {0,sizeof(k0),k0}; + + hlen=sha; + if (hlen>32) b=128; + else b=64; + + if (olen<4 /*|| olen>hlen*/) return 0; + + if (k->len > b) hashit(sha,k,-1,NULL,&K0,0); + else OCT_copy(&K0,k); + + OCT_jbyte(&K0,0,b-K0.len); + + OCT_xorbyte(&K0,0x36); + + hashit(sha,&K0,-1,m,&H,0); + + OCT_xorbyte(&K0,0x6a); /* 0x6a = 0x36 ^ 0x5c */ + hashit(sha,&K0,-1,&H,&H,olen); + + OCT_empty(tag); + + OCT_jbytes(tag,H.val,olen); + + return 1; +} + +/* Key Derivation Functions */ +/* Input octet z */ +/* Output key of length olen */ +/* +void KDF1(octet *z,int olen,octet *key) +{ + char h[32]; + octet H={0,sizeof(h),h}; + int counter,cthreshold; + int hlen=32; + + OCT_empty(key); + + cthreshold=ROUNDUP(olen,hlen); + + for (counter=0;counter<cthreshold;counter++) + { + hashit(z,counter,NULL,NULL,&H); + if (key->len+hlen>olen) OCT_jbytes(key,H.val,olen%hlen); + else OCT_joctet(key,&H); + } +} +*/ +void KDF2(int sha,octet *z,octet *p,int olen,octet *key) +{ + /* NOTE: the parameter olen is the length of the output k in bytes */ + char h[64]; + octet H= {0,sizeof(h),h}; + int counter,cthreshold; + int hlen=sha; + + OCT_empty(key); + + cthreshold=ROUNDUP(olen,hlen); + + for (counter=1; counter<=cthreshold; counter++) + { + hashit(sha,z,counter,p,&H,0); + if (key->len+hlen>olen) OCT_jbytes(key,H.val,olen%hlen); + else OCT_joctet(key,&H); + } + +} + +/* Password based Key Derivation Function */ +/* Input password p, salt s, and repeat count */ +/* Output key of length olen */ +void PBKDF2(int sha,octet *p,octet *s,int rep,int olen,octet *key) +{ + int i,j,len,d=ROUNDUP(olen,sha); + char f[64],u[64]; /*****/ + octet F= {0,sizeof(f),f}; + octet U= {0,sizeof(u),u}; + OCT_empty(key); + + for (i=1; i<=d; i++) + { + len=s->len; + OCT_jint(s,i,4); + + HMAC(sha,s,p,sha,&F); /* sha not EFS */ + + s->len=len; + OCT_copy(&U,&F); + for (j=2; j<=rep; j++) + { + HMAC(sha,&U,p,sha,&U); /* sha not EFS */ + OCT_xor(&F,&U); + } + + OCT_joctet(key,&F); + } + + OCT_chop(key,NULL,olen); +} + +/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */ +void AES_CBC_IV0_ENCRYPT(octet *k,octet *m,octet *c) +{ + /* AES CBC encryption, with Null IV and key k */ + /* Input is from an octet string m, output is to an octet string c */ + /* Input is padded as necessary to make up a full final block */ + amcl_aes a; + int fin; + int i,j,ipt,opt; + char buff[16]; + int padlen; + + OCT_clear(c); + if (m->len==0) return; + AES_init(&a,CBC,k->len,k->val,NULL); + + ipt=opt=0; + fin=0; + for(;;) + { + for (i=0; i<16; i++) + { + if (ipt<m->len) buff[i]=m->val[ipt++]; + else + { + fin=1; + break; + } + } + if (fin) break; + AES_encrypt(&a,buff); + for (i=0; i<16; i++) + if (opt<c->max) c->val[opt++]=buff[i]; + } + + /* last block, filled up to i-th index */ + + padlen=16-i; + for (j=i; j<16; j++) buff[j]=padlen; + AES_encrypt(&a,buff); + for (i=0; i<16; i++) + if (opt<c->max) c->val[opt++]=buff[i]; + AES_end(&a); + c->len=opt; +} + +/* decrypts and returns TRUE if all consistent, else returns FALSE */ +int AES_CBC_IV0_DECRYPT(octet *k,octet *c,octet *m) +{ + /* padding is removed */ + amcl_aes a; + int i,ipt,opt,ch; + char buff[16]; + int fin,bad; + int padlen; + ipt=opt=0; + + OCT_clear(m); + if (c->len==0) return 1; + ch=c->val[ipt++]; + + AES_init(&a,CBC,k->len,k->val,NULL); + fin=0; + + for(;;) + { + for (i=0; i<16; i++) + { + buff[i]=ch; + if (ipt>=c->len) + { + fin=1; + break; + } + else ch=c->val[ipt++]; + } + AES_decrypt(&a,buff); + if (fin) break; + for (i=0; i<16; i++) + if (opt<m->max) m->val[opt++]=buff[i]; + } + AES_end(&a); + bad=0; + padlen=buff[15]; + if (i!=15 || padlen<1 || padlen>16) bad=1; + if (padlen>=2 && padlen<=16) + for (i=16-padlen; i<16; i++) if (buff[i]!=padlen) bad=1; + + if (!bad) for (i=0; i<16-padlen; i++) + if (opt<m->max) m->val[opt++]=buff[i]; + + m->len=opt; + if (bad) return 0; + return 1; +} + +/* Calculate a public/private EC GF(p) key pair. W=S.G mod EC(p), + * where S is the secret key and W is the public key + * and G is fixed generator. + * If RNG is NULL then the private key is provided externally in S + * otherwise it is generated randomly internally */ +int ECP_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W) +{ + BIG r,gx,s; + ECP G; + int res=0; + BIG_rcopy(gx,CURVE_Gx); + +#if CURVETYPE!=MONTGOMERY + BIG gy; + BIG_rcopy(gy,CURVE_Gy); + ECP_set(&G,gx,gy); +#else + ECP_set(&G,gx); +#endif + + BIG_rcopy(r,CURVE_Order); + if (RNG!=NULL) + { + BIG_randomnum(s,r,RNG); + } + else + { + BIG_fromBytes(s,S->val); + BIG_mod(s,r); + } + +#ifdef AES_S + BIG_mod2m(s,2*AES_S); +// BIG_toBytes(S->val,s); +#endif + + ECP_mul(&G,s); +#if CURVETYPE!=MONTGOMERY + ECP_get(gx,gy,&G); +#else + ECP_get(gx,&G); + /* + ECP_rhs(gy,gx); + FP_sqrt(gy,gy); + FP_neg(gy,gy); + FP_inv(gy,gy); + FP_mul(r,gx,gy); + FP_reduce(r); + + BIG_zero(gy); + BIG_inc(gy,486664); + FP_neg(gy,gy); + FP_sqrt(gy,gy); + FP_reduce(gy); + FP_mul(r,r,gy); + FP_reduce(r); + + printf("x= "); BIG_output(r); printf("\n"); + + BIG_copy(r,gx); + BIG_dec(r,1); + BIG_copy(gy,gx); + BIG_inc(gy,1); + FP_inv(gy,gy); + FP_mul(r,r,gy); + FP_reduce(r); + + printf("y= "); BIG_output(r); printf("\n"); + + BIG_zero(r); + BIG_inc(r,121665); + BIG_zero(gy); + BIG_inc(gy,121666); + FP_inv(gy,gy); + FP_mul(r,r,gy); + FP_neg(r,r); + FP_reduce(r); + + printf("d= "); BIG_output(r); printf("\n"); + */ + +#endif + + S->len=EGS; + BIG_toBytes(S->val,s); + +#if CURVETYPE!=MONTGOMERY + W->len=2*EFS+1; + W->val[0]=4; + BIG_toBytes(&(W->val[1]),gx); + BIG_toBytes(&(W->val[EFS+1]),gy); +#else + W->len=EFS+1; + W->val[0]=2; + BIG_toBytes(&(W->val[1]),gx); +#endif + + return res; +} + +/* validate public key. Set full=true for fuller check */ +int ECP_PUBLIC_KEY_VALIDATE(int full,octet *W) +{ + BIG q,r,wx; + ECP WP; + int valid; + int res=0; + + BIG_rcopy(q,Modulus); + BIG_rcopy(r,CURVE_Order); + + BIG_fromBytes(wx,&(W->val[1])); + if (BIG_comp(wx,q)>=0) res=ECDH_INVALID_PUBLIC_KEY; +#if CURVETYPE!=MONTGOMERY + BIG wy; + BIG_fromBytes(wy,&(W->val[EFS+1])); + if (BIG_comp(wy,q)>=0) res=ECDH_INVALID_PUBLIC_KEY; +#endif + if (res==0) + { + +#if CURVETYPE!=MONTGOMERY + valid=ECP_set(&WP,wx,wy); +#else + valid=ECP_set(&WP,wx); +#endif + if (!valid || ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY; + if (res==0 && full) + { + + ECP_mul(&WP,r); + if (!ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY; + } + } + + return res; +} + +/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */ +int ECPSVDP_DH(octet *S,octet *WD,octet *Z) +{ + BIG r,s,wx; + int valid; + ECP W; + int res=0; + + BIG_fromBytes(s,S->val); + + BIG_fromBytes(wx,&(WD->val[1])); +#if CURVETYPE!=MONTGOMERY + BIG wy; + BIG_fromBytes(wy,&(WD->val[EFS+1])); + valid=ECP_set(&W,wx,wy); +#else + valid=ECP_set(&W,wx); +#endif + if (!valid) res=ECDH_ERROR; + if (res==0) + { + BIG_rcopy(r,CURVE_Order); + BIG_mod(s,r); + + ECP_mul(&W,s); + if (ECP_isinf(&W)) res=ECDH_ERROR; + else + { +#if CURVETYPE!=MONTGOMERY + ECP_get(wx,wx,&W); +#else + ECP_get(wx,&W); +#endif + Z->len=MODBYTES; + BIG_toBytes(Z->val,wx); + } + } + return res; +} + +#if CURVETYPE!=MONTGOMERY + +/* IEEE ECDSA Signature, C and D are signature on F using private key S */ +int ECPSP_DSA(int sha,csprng *RNG,octet *K,octet *S,octet *F,octet *C,octet *D) +{ + char h[128]; + octet H= {0,sizeof(h),h}; + + BIG gx,gy,r,s,f,c,d,u,vx,w; + ECP G,V; + + hashit(sha,F,-1,NULL,&H,sha); + BIG_rcopy(gx,CURVE_Gx); + BIG_rcopy(gy,CURVE_Gy); + BIG_rcopy(r,CURVE_Order); + + BIG_fromBytes(s,S->val); + + int hlen=H.len; + if (H.len>MODBYTES) hlen=MODBYTES; + BIG_fromBytesLen(f,H.val,hlen); + + ECP_set(&G,gx,gy); + + do + { + if (RNG!=NULL) + { + BIG_randomnum(u,r,RNG); + BIG_randomnum(w,r,RNG); /* randomize calculation */ + } + else + { + BIG_fromBytes(u,K->val); + BIG_mod(u,r); + } + +#ifdef AES_S + BIG_mod2m(u,2*AES_S); +#endif + ECP_copy(&V,&G); + ECP_mul(&V,u); + + ECP_get(vx,vx,&V); + + BIG_copy(c,vx); + BIG_mod(c,r); + if (BIG_iszilch(c)) continue; + if (RNG!=NULL) + { + BIG_modmul(u,u,w,r); + } + + BIG_invmodp(u,u,r); + BIG_modmul(d,s,c,r); + + BIG_add(d,f,d); + if (RNG!=NULL) + { + BIG_modmul(d,d,w,r); + } + + BIG_modmul(d,u,d,r); + + } + while (BIG_iszilch(d)); + + C->len=D->len=EGS; + + BIG_toBytes(C->val,c); + BIG_toBytes(D->val,d); + + return 0; +} + +/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */ +int ECPVP_DSA(int sha,octet *W,octet *F, octet *C,octet *D) +{ + char h[128]; + octet H= {0,sizeof(h),h}; + + BIG r,gx,gy,wx,wy,f,c,d,h2; + int res=0; + ECP G,WP; + int valid; + + hashit(sha,F,-1,NULL,&H,sha); + BIG_rcopy(gx,CURVE_Gx); + BIG_rcopy(gy,CURVE_Gy); + BIG_rcopy(r,CURVE_Order); + + OCT_shl(C,C->len-MODBYTES); + OCT_shl(D,D->len-MODBYTES); + + BIG_fromBytes(c,C->val); + BIG_fromBytes(d,D->val); + + int hlen=H.len; + if (hlen>MODBYTES) hlen=MODBYTES; + + BIG_fromBytesLen(f,H.val,hlen); + + //BIG_fromBytes(f,H.val); + + if (BIG_iszilch(c) || BIG_comp(c,r)>=0 || BIG_iszilch(d) || BIG_comp(d,r)>=0) + res=ECDH_INVALID; + + if (res==0) + { + BIG_invmodp(d,d,r); + BIG_modmul(f,f,d,r); + BIG_modmul(h2,c,d,r); + + ECP_set(&G,gx,gy); + + BIG_fromBytes(wx,&(W->val[1])); + BIG_fromBytes(wy,&(W->val[EFS+1])); + + valid=ECP_set(&WP,wx,wy); + + if (!valid) res=ECDH_ERROR; + else + { + ECP_mul2(&WP,&G,h2,f); + + if (ECP_isinf(&WP)) res=ECDH_INVALID; + else + { + ECP_get(d,d,&WP); + BIG_mod(d,r); + if (BIG_comp(d,c)!=0) res=ECDH_INVALID; + } + } + } + + return res; +} + +/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */ +void ECP_ECIES_ENCRYPT(int sha,octet *P1,octet *P2,csprng *RNG,octet *W,octet *M,int tlen,octet *V,octet *C,octet *T) +{ + + int i,len; + char z[EFS],vz[3*EFS+1],k[2*EAS],k1[EAS],k2[EAS],l2[8],u[EFS]; + octet Z= {0,sizeof(z),z}; + octet VZ= {0,sizeof(vz),vz}; + octet K= {0,sizeof(k),k}; + octet K1= {0,sizeof(k1),k1}; + octet K2= {0,sizeof(k2),k2}; + octet L2= {0,sizeof(l2),l2}; + octet U= {0,sizeof(u),u}; + + if (ECP_KEY_PAIR_GENERATE(RNG,&U,V)!=0) return; + if (ECPSVDP_DH(&U,W,&Z)!=0) return; + + OCT_copy(&VZ,V); + OCT_joctet(&VZ,&Z); + + KDF2(sha,&VZ,P1,2*EAS,&K); + + K1.len=K2.len=EAS; + for (i=0; i<EAS; i++) + { + K1.val[i]=K.val[i]; + K2.val[i]=K.val[EAS+i]; + } + + AES_CBC_IV0_ENCRYPT(&K1,M,C); + + OCT_jint(&L2,P2->len,8); + + len=C->len; + OCT_joctet(C,P2); + OCT_joctet(C,&L2); + HMAC(sha,C,&K2,tlen,T); + C->len=len; +} + +/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */ +int ECP_ECIES_DECRYPT(int sha,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M) +{ + + int i,len; + char z[EFS],vz[3*EFS+1],k[2*EAS],k1[EAS],k2[EAS],l2[8],tag[32]; + octet Z= {0,sizeof(z),z}; + octet VZ= {0,sizeof(vz),vz}; + octet K= {0,sizeof(k),k}; + octet K1= {0,sizeof(k1),k1}; + octet K2= {0,sizeof(k2),k2}; + octet L2= {0,sizeof(l2),l2}; + octet TAG= {0,sizeof(tag),tag}; + + if (ECPSVDP_DH(U,V,&Z)!=0) return 0; + + OCT_copy(&VZ,V); + OCT_joctet(&VZ,&Z); + + KDF2(sha,&VZ,P1,EFS,&K); + + K1.len=K2.len=EAS; + for (i=0; i<EAS; i++) + { + K1.val[i]=K.val[i]; + K2.val[i]=K.val[EAS+i]; + } + + if (!AES_CBC_IV0_DECRYPT(&K1,C,M)) return 0; + + OCT_jint(&L2,P2->len,8); + + len=C->len; + OCT_joctet(C,P2); + OCT_joctet(C,&L2); + HMAC(sha,C,&K2,T->len,&TAG); + C->len=len; + + if (!OCT_comp(T,&TAG)) return 0; + + return 1; + +} + +#endif http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/ecdh.h ---------------------------------------------------------------------- diff --git a/version22/c/ecdh.h b/version22/c/ecdh.h new file mode 100644 index 0000000..7d0536b --- /dev/null +++ b/version22/c/ecdh.h @@ -0,0 +1,206 @@ +/* +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. +*/ + +/** + * @file ecdh.h + * @author Mike Scott and Kealan McCusker + * @date 2nd June 2015 + * @brief ECDH Header file for implementation of standard EC protocols + * + * declares functions + * + */ + +#ifndef ECDH_H +#define ECDH_H + +#include "amcl.h" + +#define EAS 16 /**< Symmetric Key size - 128 bits */ +#define EGS MODBYTES /**< ECC Group Size in bytes */ +#define EFS MODBYTES /**< ECC Field Size in bytes */ + +#define HASH_TYPE_ECC SHA256 /**< Hash type */ + +#define ECDH_OK 0 /**< Function completed without error */ +/*#define ECDH_DOMAIN_ERROR -1*/ +#define ECDH_INVALID_PUBLIC_KEY -2 /**< Public Key is Invalid */ +#define ECDH_ERROR -3 /**< ECDH Internal Error */ +#define ECDH_INVALID -4 /**< ECDH Internal Error */ +/*#define ECDH_DOMAIN_NOT_FOUND -5 +#define ECDH_OUT_OF_MEMORY -6 +#define ECDH_DIV_BY_ZERO -7 +#define ECDH_BAD_ASSUMPTION -8*/ + +/* ECDH Auxiliary Functions */ + + +/** @brief hash an octet into another octet + * + @param h is the hash type + @param I input octet + @param O output octet - H(I) + */ +extern void HASH(int h,octet *I,octet *O); +/** @brief HMAC of message M using key K to create tag of length len in octet tag + * + IEEE-1363 MAC1 function. Uses SHA256 internally. + @param h is the hash type + @param M input message octet + @param K input encryption key + @param len is output desired length of HMAC tag + @param tag is the output HMAC + @return 0 for bad parameters, else 1 + */ +extern int HMAC(int h,octet *M,octet *K,int len,octet *tag); + +/*extern void KDF1(octet *,int,octet *);*/ + +/** @brief Key Derivation Function - generates key K from inputs Z and P + * + IEEE-1363 KDF2 Key Derivation Function. Uses SHA256 internally. + @param h is the hash type + @param Z input octet + @param P input key derivation parameters - can be NULL + @param len is output desired length of key + @param K is the derived key + */ +extern void KDF2(int h,octet *Z,octet *P,int len,octet *K); +/** @brief Password Based Key Derivation Function - generates key K from password, salt and repeat counter + * + PBKDF2 Password Based Key Derivation Function. Uses SHA256 internally. + @param h is the hash type + @param P input password + @param S input salt + @param rep Number of times to be iterated. + @param len is output desired length + @param K is the derived key + */ +extern void PBKDF2(int h,octet *P,octet *S,int rep,int len,octet *K); +/** @brief AES encrypts a plaintext to a ciphtertext + * + IEEE-1363 AES_CBC_IV0_ENCRYPT function. Encrypts in CBC mode with a zero IV, padding as necessary to create a full final block. + @param K AES key + @param P input plaintext octet + @param C output ciphertext octet + */ +extern void AES_CBC_IV0_ENCRYPT(octet *K,octet *P,octet *C); +/** @brief AES encrypts a plaintext to a ciphtertext + * + IEEE-1363 AES_CBC_IV0_DECRYPT function. Decrypts in CBC mode with a zero IV. + @param K AES key + @param C input ciphertext octet + @param P output plaintext octet + @return 0 if bad input, else 1 + */ +extern int AES_CBC_IV0_DECRYPT(octet *K,octet *C,octet *P); + +/* ECDH primitives - support functions */ +/** @brief Generate an ECC public/private key pair + * + @param R is a pointer to a cryptographically secure random number generator + @param s the private key, an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param W the output public key, which is s.G, where G is a fixed generator + @return 0 or an error code + */ +extern int ECP_KEY_PAIR_GENERATE(csprng *R,octet *s,octet *W); +/** @brief Validate an ECC public key + * + @param f if = 0 just does some simple checks, else tests that W is of the correct order + @param W the input public key to be validated + @return 0 if public key is OK, or an error code + */ +extern int ECP_PUBLIC_KEY_VALIDATE(int f,octet *W); + +/* ECDH primitives */ + +/** @brief Generate Diffie-Hellman shared key + * + IEEE-1363 Diffie-Hellman shared secret calculation + @param s is the input private key, + @param W the input public key of the other party + @param K the output shared key, in fact the x-coordinate of s.W + @return 0 or an error code + */ +extern int ECPSVDP_DH(octet *s,octet *W,octet *K); +/*extern int ECPSVDP_DHC(octet *,octet *,int,octet *);*/ + +/*#if CURVETYPE!=MONTGOMERY */ +/* ECIES functions */ +/*#if CURVETYPE!=MONTGOMERY */ +/* ECIES functions */ +/** @brief ECIES Encryption + * + IEEE-1363 ECIES Encryption + @param h is the hash type + @param P1 input Key Derivation parameters + @param P2 input Encoding parameters + @param R is a pointer to a cryptographically secure random number generator + @param W the input public key of the recieving party + @param M is the plaintext message to be encrypted + @param len the length of the HMAC tag + @param V component of the output ciphertext + @param C the output ciphertext + @param T the output HMAC tag, part of the ciphertext + */ +extern void ECP_ECIES_ENCRYPT(int h,octet *P1,octet *P2,csprng *R,octet *W,octet *M,int len,octet *V,octet *C,octet *T); +/** @brief ECIES Decryption + * + IEEE-1363 ECIES Decryption + @param h is the hash type + @param P1 input Key Derivation parameters + @param P2 input Encoding parameters + @param V component of the input ciphertext + @param C the input ciphertext + @param T the input HMAC tag, part of the ciphertext + @param U the input private key for decryption + @param M the output plaintext message + @return 1 if successful, else 0 + */ +extern int ECP_ECIES_DECRYPT(int h,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M); + +/* ECDSA functions */ +/** @brief ECDSA Signature + * + IEEE-1363 ECDSA Signature + @param h is the hash type + @param R is a pointer to a cryptographically secure random number generator + @param k Ephemeral key. This value is used when R=NULL + @param s the input private signing key + @param M the input message to be signed + @param c component of the output signature + @param d component of the output signature + + */ +extern int ECPSP_DSA(int h,csprng *R,octet *k,octet *s,octet *M,octet *c,octet *d); +/** @brief ECDSA Signature Verification + * + IEEE-1363 ECDSA Signature Verification + @param h is the hash type + @param W the input public key + @param M the input message + @param c component of the input signature + @param d component of the input signature + @return 0 or an error code + */ +extern int ECPVP_DSA(int h,octet *W,octet *M,octet *c,octet *d); +/*#endif*/ + +#endif +
