You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@milagro.apache.org by br...@apache.org on 2018/11/07 23:49:44 UTC
[07/51] [partial] incubator-milagro-crypto git commit: update code
http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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/70e3a3a3/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
+