diff --git a/config.c b/config.c
index 35db823..c57d945 100644
--- a/config.c
+++ b/config.c
@@ -93,9 +93,9 @@ int main()
printf("enter the native wordlength of your computer\n\n");
printf("For your information:-\n");
printf("The size of a char is %d bits\n",bitsinchar);
- printf("The size of a short is %ld bits\n",bitsinchar*sizeof(short));
- printf("The size of an int is %ld bits\n",bitsinchar*sizeof(int));
- printf("The size of a long is %ld bits\n",bitsinchar*sizeof(long));
+ printf("The size of a short is %d bits\n",bitsinchar*sizeof(short));
+ printf("The size of an int is %d bits\n",bitsinchar*sizeof(int));
+ printf("The size of a long is %d bits\n",bitsinchar*sizeof(long));
eps=1.0;
for (dmant=0;;dmant++)
@@ -106,7 +106,7 @@ int main()
eps/=2.0;
}
- printf("The size of a double is %ld bits, its mantissa is %d bits\n",bitsinchar*sizeof(double),dmant);
+ printf("The size of a double is %d bits, its mantissa is %d bits\n",bitsinchar*sizeof(double),dmant);
leps=1.0;
for (lmant=0;;lmant++)
@@ -116,7 +116,7 @@ int main()
if (lx==ly) break;
leps/=2.0;
}
- printf("The size of a long double is %ld bits, its mantissa is %d bits\n",bitsinchar*sizeof(long double),lmant);
+ printf("The size of a long double is %d bits, its mantissa is %d bits\n",bitsinchar*sizeof(long double),lmant);
fp=fopen("mirdef.tst","wt");
@@ -147,7 +147,7 @@ int main()
no64=0;
if (double_type)
{
- fprintf(fp,"#define MIRACL %ld\n",bitsinchar*sizeof(double));
+ fprintf(fp,"#define MIRACL %d\n",bitsinchar*sizeof(double));
fprintf(fp,"#define mr_utype double\n");
fprintf(fp,"#define mr_dltype long double\n");
fprintf(fp,"#define MR_NOFULLWIDTH\n");
@@ -235,8 +235,8 @@ int main()
}
}
- fprintf(fp,"#define MR_IBITS %ld\n",bitsinchar*sizeof(int));
- fprintf(fp,"#define MR_LBITS %ld\n",bitsinchar*sizeof(long));
+ fprintf(fp,"#define MR_IBITS %d\n",bitsinchar*sizeof(int));
+ fprintf(fp,"#define MR_LBITS %d\n",bitsinchar*sizeof(long));
/* Now try to find 32-bit unsigned types */
@@ -488,6 +488,7 @@ int main()
fprintf(fpl,"mrshs256.c\n");
fprintf(fpl,"mraes.c\n");
fprintf(fpl,"mrgcm.c\n");
+ fprintf(fpl,"mrfpe.c\n");
fprintf(fpl,"mrstrong.c\n");
fprintf(fpl,"mrcurve.c\n");
fprintf(fpl,"mrbrick.c\n");
@@ -502,8 +503,11 @@ int main()
fprintf(fpl,"mrfast.c\n");
fprintf(fpl,"mralloc.c\n");
}
- if (chosen64) fprintf(fpl,"mrshs512.c\n");
-
+ if (chosen64)
+ {
+ fprintf(fpl,"mrshs512.c\n");
+ fprintf(fpl,"mrsha3.c\n");
+ }
port=0;
if (chosen && double_length_type)
{
diff --git a/readme.txt b/readme.txt
index 203251a..3755e0e 100644
--- a/readme.txt
+++ b/readme.txt
@@ -15,6 +15,7 @@ The distribution media contains the following files
FASTGF2M.TXT - How to speed up methods based on the field GF(2^m)
WIN64.TXT - 64-bit Windows advice
DEVCPP.TXT - DEV-CPP quick-start instructions
+ TEXASDSP.TXT - Texas C6713 DSP advice
AMD64.TXT - AMD64 processor advice
SSE2.TXT - SSE2 extensions advice
PIC32.TXT - PIC32 processor advice
@@ -242,6 +243,11 @@ In the subdirectory SOURCE
P1363.C - P1363 implementation file
TEST1363.c - test driver for P1363 implementation
RSA.C - quick start RSA application
+ OCTET.C - OCTET string handler
+ OCTET.H - OCTET header
+ ECDH.C - Elliptic Curve Code
+ ECDH.H - Elliptic Curve Header
+ TESTECC.C - Typical MIRACL Elliptic Curve API Implementation - thread-safe - no heap
In the subdirectory SOURCE\CURVE\PAIRING
diff --git a/source/mrcomba.tpl b/source/mrcomba.tpl
index 43d4c47..d7e5aec 100644
--- a/source/mrcomba.tpl
+++ b/source/mrcomba.tpl
@@ -596,7 +596,7 @@ void comba_redc(_MIPD_ big t,big z)
}
if (z->w[MR_COMBA-1]>=modulus->w[MR_COMBA-1])
{
- if (compare(z,modulus)>=0)
+ if (mr_compare(z,modulus)>=0)
{
/*** DECREMENT ***/
}
@@ -957,7 +957,7 @@ comba_sub(z,w,z);
}
if (z->w[MR_COMBA-1]>=modulus->w[MR_COMBA-1])
{
- if (compare(z,modulus)>=0)
+ if (mr_compare(z,modulus)>=0)
{
/*** DECREMENT ***/
}
diff --git a/source/mrsha3.c b/source/mrsha3.c
index ec7755a..b36fa3b 100644
--- a/source/mrsha3.c
+++ b/source/mrsha3.c
@@ -48,12 +48,12 @@ the CertiVox MIRACL Crypto SDK with a closed source product. *
/* round constants */
static const mr_unsign64 RC[24]={
-0x0000000000000001,0x0000000000008082,0x800000000000808A,0x8000000080008000,
-0x000000000000808B,0x0000000080000001,0x8000000080008081,0x8000000000008009,
-0x000000000000008A,0x0000000000000088,0x0000000080008009,0x000000008000000A,
-0x000000008000808B,0x800000000000008B,0x8000000000008089,0x8000000000008003,
-0x8000000000008002,0x8000000000000080,0x000000000000800A,0x800000008000000A,
-0x8000000080008081,0x8000000000008080,0x0000000080000001,0x8000000080008008};
+0x0000000000000001LL,0x0000000000008082LL,0x800000000000808ALL,0x8000000080008000LL,
+0x000000000000808BLL,0x0000000080000001LL,0x8000000080008081LL,0x8000000000008009LL,
+0x000000000000008ALL,0x0000000000000088LL,0x0000000080008009LL,0x000000008000000ALL,
+0x000000008000808BLL,0x800000000000008BLL,0x8000000000008089LL,0x8000000000008003LL,
+0x8000000000008002LL,0x8000000000000080LL,0x000000000000800ALL,0x800000008000000ALL,
+0x8000000080008081LL,0x8000000000008080LL,0x0000000080000001LL,0x8000000080008008LL};
/* functions */
diff --git a/source/mrshs512.c b/source/mrshs512.c
index b7830a3..b11c511 100644
--- a/source/mrshs512.c
+++ b/source/mrshs512.c
@@ -48,8 +48,6 @@ the CertiVox MIRACL Crypto SDK with a closed source product. *
#ifdef mr_unsign64
-
-#ifdef __GNUC__
#define H0 0x6a09e667f3bcc908LL
#define H1 0xbb67ae8584caa73bLL
#define H2 0x3c6ef372fe94f82bLL
@@ -67,28 +65,9 @@ the CertiVox MIRACL Crypto SDK with a closed source product. *
#define HD 0x8eb44a8768581511LL
#define HE 0xdb0c2e0d64f98fa7LL
#define HF 0x47b5481dbefa4fa4LL
-#else
-#define H0 0x6a09e667f3bcc908
-#define H1 0xbb67ae8584caa73b
-#define H2 0x3c6ef372fe94f82b
-#define H3 0xa54ff53a5f1d36f1
-#define H4 0x510e527fade682d1
-#define H5 0x9b05688c2b3e6c1f
-#define H6 0x1f83d9abfb41bd6b
-#define H7 0x5be0cd19137e2179
-
-#define H8 0xcbbb9d5dc1059ed8
-#define H9 0x629a292a367cd507
-#define HA 0x9159015a3070dd17
-#define HB 0x152fecd8f70e5939
-#define HC 0x67332667ffc00b31
-#define HD 0x8eb44a8768581511
-#define HE 0xdb0c2e0d64f98fa7
-#define HF 0x47b5481dbefa4fa4
-#endif
+
/* */
-#ifdef __GNUC__
static const mr_unsign64 K[80]=
{0x428a2f98d728ae22LL,0x7137449123ef65cdLL,0xb5c0fbcfec4d3b2fLL,0xe9b5dba58189dbbcLL,
0x3956c25bf348b538LL,0x59f111f1b605d019LL,0x923f82a4af194f9bLL,0xab1c5ed5da6d8118LL,
@@ -110,29 +89,6 @@ static const mr_unsign64 K[80]=
0x06f067aa72176fbaLL,0x0a637dc5a2c898a6LL,0x113f9804bef90daeLL,0x1b710b35131c471bLL,
0x28db77f523047d84LL,0x32caab7b40c72493LL,0x3c9ebe0a15c9bebcLL,0x431d67c49c100d4cLL,
0x4cc5d4becb3e42b6LL,0x597f299cfc657e2aLL,0x5fcb6fab3ad6faecLL,0x6c44198c4a475817LL};
-#else
-static const mr_unsign64 K[80]=
-{0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
-0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
-0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
-0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
-0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
-0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
-0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
-0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
-0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
-0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
-0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
-0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
-0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
-0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
-0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
-0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
-0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
-0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
-0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
-0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817};
-#endif
#define PAD 0x80
#define ZERO 0
diff --git a/source/p1363/ecdh.c b/source/p1363/ecdh.c
new file mode 100644
index 0000000..c6c1410
--- /dev/null
+++ b/source/p1363/ecdh.c
@@ -0,0 +1,1013 @@
+/***************************************************************************
+ *
+Copyright 2013 CertiVox UK Ltd. *
+ *
+This file is part of CertiVox SkyKey XT Crypto SDK. *
+ *
+The CertiVox SkyKey XT Crypto SDK provides developers with an *
+extensive and efficient set of cryptographic functions. *
+For further information about its features and functionalities please *
+refer to http://www.certivox.com *
+ *
+* The CertiVox SkyKey XT Crypto SDK is free software: you can *
+ redistribute it and/or modify it under the terms of the *
+ GNU Affero General Public License as published by the *
+ Free Software Foundation, either version 3 of the License, *
+ or (at your option) any later version. *
+ *
+* The CertiVox SkyKey XT Crypto SDK is distributed in the hope *
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the *
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ See the GNU Affero General Public License for more details. *
+ *
+* You should have received a copy of the GNU Affero General Public *
+ License along with CertiVox MIRACL Crypto SDK. *
+ If not, see . *
+ *
+You can be released from the requirements of the license by purchasing *
+a commercial license. Buying such a license is mandatory as soon as you *
+develop commercial activities involving the CertiVox SkyKey XT Crypto SDK *
+without disclosing the source code of your own applications, or shipping *
+the CertiVox SkyKey XT Crypto SDK with a closed source product. *
+ *
+***************************************************************************/
+
+/* ECDH/ECIES/ECDSA Functions - see main program below */
+
+/* Note that in production code miracl COMBA mechanism should be invoked for 2-3 times speed up */
+/* Use this mirdef.h for 32-bit processor - note no assembly required
+
+#define MR_LITTLE_ENDIAN
+#define MIRACL 32
+#define mr_utype int
+#define mr_dltype long long
+#define mr_unsign64 unsigned long long
+#define MR_IBITS 32
+#define MR_LBITS 32
+#define mr_unsign32 unsigned int
+#define MR_ALWAYS_BINARY
+#define MR_STATIC 8
+#define MR_GENERIC_MT
+#define MR_STRIPPED_DOWN
+#define MR_NOSUPPORT_COMPRESSION
+#define MR_SIMPLE_BASE
+#define MR_SIMPLE_IO
+#define MR_NOASM
+#define MAXBASE ((mr_small)1<<(MIRACL-1))
+#define MR_BITSINCHAR 8
+*/
+
+/* Use this mirdef.h for 64-bit processor
+
+#define MR_LITTLE_ENDIAN
+#define MIRACL 64
+#define mr_utype long long
+#define mr_unsign64 unsigned long long
+#define MR_IBITS 32
+#define MR_LBITS 32
+#define mr_unsign32 unsigned int
+#define MR_ALWAYS_BINARY
+#define MR_STATIC 4
+#define MR_GENERIC_MT
+#define MR_STRIPPED_DOWN
+#define MR_NOSUPPORT_COMPRESSION
+#define MR_SIMPLE_BASE
+#define MR_SIMPLE_IO
+#define MAXBASE ((mr_small)1<<(MIRACL-1))
+#define MR_BITSINCHAR 8
+
+*/
+
+/* Link to these files
+
+mrcore.c
+mrarth0.c
+mrarth1.c
+mrarth2.c
+mrio1.c
+mrgcd.c
+mrxgcd.c
+mrarth3.c
+mrbits.c
+mrmonty.c
+mrcurve.c
+mraes.c
+mrshs256.c
+mrstrong.c
+
+For 64-bit build using Microsoft compiler mrmuldv.w64 must be included as well
+For 64-bit build using Linux and Intel chips, mrmuldv.g64 must be included as well
+
+
+To use COMBA speed-up, for 32-bit build add
+
+#define MR_COMBA 8
+#define MR_GENERALISED_MERSENNE
+#define MR_SPECIAL
+
+For 64-bit build add
+
+#define MR_COMBA 4
+#define MR_GENERALISED_MERSENNE
+#define MR_SPECIAL
+
+
+to mirdef.h
+
+Also create mrcomba.c using MEX utility, and add mrcomba.c in build
+
+*/
+
+#include
+#include
+#include
+#include
+
+#include "ecdh.h"
+
+/* Elliptic Curve parameters - NIST P256 Curve */
+
+#if MIRACL==64
+
+const mr_small ecrom[]={
+0xffffffffffffffff,0xffffffff,0x0,0xffffffff00000001,
+0x3bce3c3e27d2604b,0x651d06b0cc53b0f6,0xb3ebbd55769886bc,0x5ac635d8aa3a93e7,
+0xf3b9cac2fc632551,0xbce6faada7179e84,0xffffffffffffffff,0xffffffff00000000,
+0xf4a13945d898c296,0x77037d812deb33a0,0xf8bce6e563a440f2,0x6b17d1f2e12c4247,
+0xcbb6406837bf51f5,0x2bce33576b315ece,0x8ee7eb4a7c0f9e16,0x4fe342e2fe1a7f9b};
+
+#endif
+
+#if MIRACL==32
+
+const mr_small ecrom[]={
+0xffffffff,0xffffffff,0xffffffff,0x0,0x0,0x0,0x1,0xffffffff,
+0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55,0xaa3a93e7,0x5ac635d8,
+0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff,0x0,0xffffffff,
+0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5,0xe12c4247,0x6b17d1f2,
+0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a,0xfe1a7f9b,0x4fe342e2};
+
+#endif
+
+
+static void hash(octet *p,int n,octet *x,octet *y,octet *w)
+{
+ int i,hlen,c[4];
+ HASHFUNC sha;
+ char hh[HASH_BYTES];
+
+ hlen=HASH_BYTES;
+
+ SHS_INIT(&sha);
+ if (p!=NULL)
+ for (i=0;ilen;i++) SHS_PROCESS(&sha,p->val[i]);
+ 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++) SHS_PROCESS(&sha,c[i]);
+ }
+ if (x!=NULL)
+ for (i=0;ilen;i++) SHS_PROCESS(&sha,x->val[i]);
+ if (y!=NULL)
+ for (i=0;ilen;i++) SHS_PROCESS(&sha,y->val[i]);
+
+
+ SHS_HASH(&sha,hh);
+
+ OCTET_EMPTY(w);
+ OCTET_JOIN_BYTES(hh,hlen,w);
+ for (i=0;ilen,RAW->val,0L);
+}
+
+void KILL_CSPRNG(csprng *RNG)
+{
+ strong_kill(RNG);
+}
+
+BOOL HMAC(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 i,hlen,b;
+ char h[HASH_BYTES],k0[HASH_BLOCK];
+ octet H={0,sizeof(h),h};
+ octet K0={0,sizeof(k0),k0};
+
+ hlen=HASH_BYTES; b=HASH_BLOCK;
+ if (olen<4 || olen>hlen) return FALSE;
+
+ if (k->len > b) hash(k,-1,NULL,NULL,&K0);
+ else OCTET_COPY(k,&K0);
+
+ OCTET_JOIN_BYTE(0,b-K0.len,&K0);
+
+ OCTET_XOR_BYTE(0x36,&K0);
+
+ hash(&K0,-1,m,NULL,&H);
+
+ OCTET_XOR_BYTE(0x6a,&K0); /* 0x6a = 0x36 ^ 0x5c */
+ hash(&K0,-1,&H,NULL,&H);
+
+ OCTET_EMPTY(tag);
+ OCTET_JOIN_BYTES(H.val,olen,tag);
+
+ return TRUE;
+}
+
+/* Key Derivation Functions */
+/* Input octet z */
+/* Output key of length olen */
+
+void KDF1(octet *z,int olen,octet *key)
+{
+ char h[HASH_BYTES];
+ octet H={0,sizeof(h),h};
+ int counter,cthreshold;
+ int hlen=HASH_BYTES;
+
+ OCTET_EMPTY(key);
+
+ cthreshold=MR_ROUNDUP(olen,hlen);
+
+ for (counter=0;counterlen+hlen>olen) OCTET_JOIN_BYTES(H.val,olen%hlen,key);
+ else OCTET_JOIN_OCTET(&H,key);
+ }
+}
+
+void KDF2(octet *z,octet *p,int olen,octet *key)
+{
+/* NOTE: the parameter olen is the length of the output k in bytes */
+ char h[HASH_BYTES];
+ octet H={0,sizeof(h),h};
+ int counter,cthreshold;
+ int hlen=HASH_BYTES;
+
+ OCTET_EMPTY(key);
+
+ cthreshold=MR_ROUNDUP(olen,hlen);
+
+ for (counter=1;counter<=cthreshold;counter++)
+ {
+ hash(z,counter,p,NULL,&H);
+ if (key->len+hlen>olen) OCTET_JOIN_BYTES(H.val,olen%hlen,key);
+ else OCTET_JOIN_OCTET(&H,key);
+ }
+}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+
+void PBKDF2(octet *p,octet *s,int rep,int olen,octet *key)
+{
+ int i,j,len,d=MR_ROUNDUP(olen,HASH_BYTES);
+ char f[EFS],u[EFS];
+ octet F={0,sizeof(f),f};
+ octet U={0,sizeof(u),u};
+ OCTET_EMPTY(key);
+
+ for (i=1;i<=d;i++)
+ {
+ len=s->len;
+ OCTET_JOIN_LONG(i,4,s);
+ HMAC(s,p,EFS,&F);
+ s->len=len;
+ OCTET_COPY(&F,&U);
+ for (j=2;j<=rep;j++)
+ {
+ HMAC(&U,p,EFS,&U);
+ OCTET_XOR(&U,&F);
+ }
+
+ OCTET_JOIN_OCTET(&F,key);
+ }
+ OCTET_CHOP(key,olen,NULL);
+}
+
+/* AES encryption/decryption */
+
+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 */
+ aes a;
+ BOOL fin;
+ int i,j,ipt,opt,ch;
+ char buff[16];
+ int padlen;
+
+ OCTET_CLEAR(c);
+ if (m->len==0) return;
+ if (!aes_init(&a,MR_CBC,k->len,k->val,NULL)) return;
+
+ ipt=opt=0;
+ fin=FALSE;
+ forever
+ {
+ for (i=0;i<16;i++)
+ {
+ if (iptlen) buff[i]=m->val[ipt++];
+ else {fin=TRUE; break;}
+ }
+ if (fin) break;
+ aes_encrypt(&a,buff);
+ for (i=0;i<16;i++)
+ if (optmax) 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 (optmax) c->val[opt++]=buff[i];
+ aes_end(&a);
+ c->len=opt;
+}
+
+/* returns TRUE if all consistent, else returns FALSE */
+
+BOOL AES_CBC_IV0_DECRYPT(octet *k,octet *c,octet *m)
+{ /* padding is removed */
+ aes a;
+ int i,ipt,opt,ch;
+ char buff[16];
+ BOOL fin,bad;
+ int padlen;
+ ipt=opt=0;
+
+ OCTET_CLEAR(m);
+ if (c->len==0) return TRUE;
+ ch=c->val[ipt++];
+
+ if (!aes_init(&a,MR_CBC,k->len,k->val,NULL)) return FALSE;
+ fin=FALSE;
+
+ forever
+ {
+ for (i=0;i<16;i++)
+ {
+ buff[i]=ch;
+ if (ipt>=c->len) {fin=TRUE; break;}
+ else ch=c->val[ipt++];
+ }
+ aes_decrypt(&a,buff);
+ if (fin) break;
+ for (i=0;i<16;i++)
+ if (optmax) m->val[opt++]=buff[i];
+ }
+ aes_end(&a);
+ bad=FALSE;
+ padlen=buff[15];
+ if (i!=15 || padlen<1 || padlen>16) bad=TRUE;
+ if (padlen>=2 && padlen<=16)
+ for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=TRUE;
+
+ if (!bad) for (i=0;i<16-padlen;i++)
+ if (optmax) m->val[opt++]=buff[i];
+
+ m->len=opt;
+ if (bad) return FALSE;
+ return TRUE;
+}
+
+
+/*** EC GF(p) primitives - support functions ***/
+/* destroy the EC GF(p) domain structure */
+
+void ECP_DOMAIN_KILL(ecp_domain *DOM)
+{
+ int i;
+ for (i=0;iQ[i]=0;
+ DOM->A[i]=0;
+ DOM->B[i]=0;
+ DOM->Gx[i]=0;
+ DOM->Gy[i]=0;
+ }
+ for (i=0;iR[i]=0;
+}
+
+/* Initialise the EC GF(p) domain structure
+ * It is assumed that the EC domain details are obtained from ROM
+ */
+
+int ECP_DOMAIN_INIT(ecp_domain *DOM,const void *rom)
+{ /* get domain details from ROM */
+
+ FILE *fp;
+#ifdef MR_GENERIC_AND_STATIC
+ miracl instance;
+ miracl *mr_mip=mirsys(&instance,2*EFS,16);
+#else
+ miracl *mr_mip=mirsys(2*EFS,16);
+#endif
+ BOOL fileinput=TRUE;
+ big q,r,gx,gy,a,b;
+ int words,promptr,err,res=0;
+#ifndef MR_STATIC
+ char *mem=(char *)memalloc(_MIPP_ 6);
+#else
+ char mem[MR_BIG_RESERVE(6)];
+ memset(mem,0,MR_BIG_RESERVE(6));
+#endif
+
+ DOM->nibbles=2*EFS;
+ words=MR_ROUNDUP(EFS*8,MIRACL);
+
+ if (mr_mip==NULL || mem==NULL) res= ECDH_OUT_OF_MEMORY;
+
+ mr_mip->ERCON=TRUE;
+
+ if (res==0)
+ {
+ q=mirvar_mem(_MIPP_ mem, 0);
+ a=mirvar_mem(_MIPP_ mem, 1);
+ b=mirvar_mem(_MIPP_ mem, 2);
+ r=mirvar_mem(_MIPP_ mem, 3);
+ gx=mirvar_mem(_MIPP_ mem, 4);
+ gy=mirvar_mem(_MIPP_ mem, 5);
+
+ promptr=0;
+ init_big_from_rom(q,words,(const mr_small *)rom,words*5,&promptr); /* Read in prime modulus q from ROM */
+ init_big_from_rom(b,words,(const mr_small *)rom,words*5,&promptr); /* Read in curve parameter b from ROM */
+ init_big_from_rom(r,words,(const mr_small *)rom,words*5,&promptr); /* Read in curve parameter r from ROM */
+ init_big_from_rom(gx,words,(const mr_small *)rom,words*5,&promptr); /* Read in curve parameter gx from ROM */
+ init_big_from_rom(gy,words,(const mr_small *)rom,words*5,&promptr); /* Read in curve parameter gy from ROM */
+ convert(_MIPP_ -3,a);
+ add(_MIPP_ q,a,a);
+
+ big_to_bytes(_MIPP_ EFS,q,DOM->Q,TRUE);
+ big_to_bytes(_MIPP_ EFS,a,DOM->A,TRUE);
+ big_to_bytes(_MIPP_ EFS,b,DOM->B,TRUE);
+ big_to_bytes(_MIPP_ EGS,r,DOM->R,TRUE);
+ big_to_bytes(_MIPP_ EFS,gx,DOM->Gx,TRUE);
+ big_to_bytes(_MIPP_ EFS,gy,DOM->Gy,TRUE);
+ }
+#ifndef MR_STATIC
+ memkill(_MIPP_ mem,6);
+#else
+ memset(mem,0,MR_BIG_RESERVE(6));
+#endif
+ err=mr_mip->ERNUM;
+ mirexit(_MIPPO_ );
+ if (err==MR_ERR_OUT_OF_MEMORY) return ECDH_OUT_OF_MEMORY;
+ if (err==MR_ERR_DIV_BY_ZERO) return ECDH_DIV_BY_ZERO;
+ if (err!=0) return -(1000+err);
+ return res;
+}
+
+/* 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
+ * If RNG is NULL then the private key is provided externally in S
+ * otherwise it is generated randomly internally */
+
+int ECP_KEY_PAIR_GENERATE(ecp_domain *DOM,csprng *RNG,octet* S,octet *W)
+{
+#ifdef MR_GENERIC_AND_STATIC
+ miracl instance;
+ miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
+#else
+ miracl *mr_mip=mirsys(DOM->nibbles,16);
+#endif
+ big q,a,b,r,gx,gy,s,wx,wy;
+ epoint *G,*WP;
+ int err,res=0;
+#ifndef MR_STATIC
+ char *mem=(char *)memalloc(_MIPP_ 9);
+ char *mem1=(char *)ecp_memalloc(_MIPP_ 2);
+#else
+ char mem[MR_BIG_RESERVE(9)];
+ char mem1[MR_ECP_RESERVE(2)];
+ memset(mem,0,MR_BIG_RESERVE(9));
+ memset(mem1,0,MR_ECP_RESERVE(2));
+#endif
+
+ if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECDH_OUT_OF_MEMORY;
+ mr_mip->ERCON=TRUE;
+
+
+ if (res==0)
+ {
+ q=mirvar_mem(_MIPP_ mem, 0);
+ a=mirvar_mem(_MIPP_ mem, 1);
+ b=mirvar_mem(_MIPP_ mem, 2);
+ r=mirvar_mem(_MIPP_ mem, 3);
+ gx=mirvar_mem(_MIPP_ mem, 4);
+ gy=mirvar_mem(_MIPP_ mem, 5);
+ s=mirvar_mem(_MIPP_ mem, 6);
+ wx=mirvar_mem(_MIPP_ mem, 7);
+ wy=mirvar_mem(_MIPP_ mem, 8);
+
+ bytes_to_big(_MIPP_ EFS,DOM->Q,q);
+ bytes_to_big(_MIPP_ EFS,DOM->A,a);
+ bytes_to_big(_MIPP_ EFS,DOM->B,b);
+ bytes_to_big(_MIPP_ EGS,DOM->R,r);
+ bytes_to_big(_MIPP_ EFS,DOM->Gx,gx);
+ bytes_to_big(_MIPP_ EFS,DOM->Gy,gy);
+
+ ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
+ G=epoint_init_mem(_MIPP_ mem1,0);
+ WP=epoint_init_mem(_MIPP_ mem1,1);
+ epoint_set(_MIPP_ gx,gy,0,G);
+
+ if (RNG!=NULL)
+ strong_bigrand(_MIPP_ RNG,r,s);
+ else
+ {
+ bytes_to_big(_MIPP_ S->len,S->val,s);
+ divide(_MIPP_ s,r,r);
+ }
+
+ ecurve_mult(_MIPP_ s,G,WP);
+ epoint_get(_MIPP_ WP,wx,wy);
+
+ if (RNG!=NULL) S->len=big_to_bytes(_MIPP_ 0,s,S->val,FALSE);
+
+ W->len=2*EFS+1; W->val[0]=4;
+ big_to_bytes(_MIPP_ EFS,wx,&(W->val[1]),TRUE);
+ big_to_bytes(_MIPP_ EFS,wy,&(W->val[EFS+1]),TRUE);
+ }
+
+#ifndef MR_STATIC
+ memkill(_MIPP_ mem,9);
+ ecp_memkill(_MIPP_ mem1,2);
+#else
+ memset(mem,0,MR_BIG_RESERVE(9));
+ memset(mem1,0,MR_ECP_RESERVE(2));
+#endif
+ err=mr_mip->ERNUM;
+ mirexit(_MIPPO_ );
+ if (err==MR_ERR_OUT_OF_MEMORY) return ECDH_OUT_OF_MEMORY;
+ if (err==MR_ERR_DIV_BY_ZERO) return ECDH_DIV_BY_ZERO;
+ if (err!=0) return -(1000+err);
+ return res;
+}
+
+/* validate an EC GF(p) public key. Set full=TRUE for fuller,
+ * but more time-consuming test */
+
+int ECP_PUBLIC_KEY_VALIDATE(ecp_domain *DOM,BOOL full,octet *W)
+{
+#ifdef MR_GENERIC_AND_STATIC
+ miracl instance;
+ miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
+#else
+ miracl *mr_mip=mirsys(DOM->nibbles,16);
+#endif
+ big q,a,b,r,wx,wy;
+ epoint *WP;
+ BOOL valid;
+ int err,res=0;
+#ifndef MR_STATIC
+ char *mem=(char *)memalloc(_MIPP_ 6);
+ char *mem1=(char *)ecp_memalloc(_MIPP_ 1);
+#else
+ char mem[MR_BIG_RESERVE(6)];
+ char mem1[MR_ECP_RESERVE(1)];
+ memset(mem,0,MR_BIG_RESERVE(6));
+ memset(mem1,0,MR_ECP_RESERVE(1));
+#endif
+
+ if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECDH_OUT_OF_MEMORY;
+ mr_mip->ERCON=TRUE;
+
+ if (res==0)
+ {
+ q=mirvar_mem(_MIPP_ mem, 0);
+ a=mirvar_mem(_MIPP_ mem, 1);
+ b=mirvar_mem(_MIPP_ mem, 2);
+ r=mirvar_mem(_MIPP_ mem, 3);
+ wx=mirvar_mem(_MIPP_ mem, 4);
+ wy=mirvar_mem(_MIPP_ mem, 5);
+
+
+ bytes_to_big(_MIPP_ EFS,DOM->Q,q);
+ bytes_to_big(_MIPP_ EFS,DOM->A,a);
+ bytes_to_big(_MIPP_ EFS,DOM->B,b);
+ bytes_to_big(_MIPP_ EGS,DOM->R,r);
+
+ bytes_to_big(_MIPP_ EFS,&(W->val[1]),wx);
+ bytes_to_big(_MIPP_ EFS,&(W->val[EFS+1]),wy);
+
+ if (mr_compare(wx,q)>=0 || mr_compare (wy,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
+ }
+ if (res==0)
+ {
+ ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
+ WP=epoint_init_mem(_MIPP_ mem1,0);
+
+ valid=epoint_set(_MIPP_ wx,wy,0,WP);
+
+ if (!valid || WP->marker==MR_EPOINT_INFINITY) res=ECDH_INVALID_PUBLIC_KEY;
+ if (res==0 && full)
+ {
+ ecurve_mult(_MIPP_ r,WP,WP);
+ if (WP->marker!=MR_EPOINT_INFINITY) res=ECDH_INVALID_PUBLIC_KEY;
+ }
+
+ }
+#ifndef MR_STATIC
+ memkill(_MIPP_ mem,6);
+ ecp_memkill(_MIPP_ mem1,1);
+#else
+ memset(mem,0,MR_BIG_RESERVE(6));
+ memset(mem1,0,MR_ECP_RESERVE(1));
+#endif
+ err=mr_mip->ERNUM;
+ mirexit(_MIPPO_ );
+ if (err==MR_ERR_OUT_OF_MEMORY) return ECDH_OUT_OF_MEMORY;
+ if (err==MR_ERR_DIV_BY_ZERO) return ECDH_DIV_BY_ZERO;
+ if (err!=0) return -(1000+err);
+ return res;
+}
+
+/*** P1363 EC GF(p) primitives ***/
+/* See P1363 documentation for specification */
+
+int ECPSVDP_DH(ecp_domain *DOM,octet *S,octet *WD,octet *Z)
+{
+#ifdef MR_GENERIC_AND_STATIC
+ miracl instance;
+ miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
+#else
+ miracl *mr_mip=mirsys(DOM->nibbles,16);
+#endif
+ big q,a,b,s,wx,wy,z;
+ BOOL valid;
+ epoint *W;
+ int err,res=0;
+#ifndef MR_STATIC
+ char *mem=(char *)memalloc(_MIPP_ 7);
+ char *mem1=(char *)ecp_memalloc(_MIPP_ 1);
+#else
+ char mem[MR_BIG_RESERVE(7)];
+ char mem1[MR_ECP_RESERVE(1)];
+ memset(mem,0,MR_BIG_RESERVE(7));
+ memset(mem1,0,MR_ECP_RESERVE(1));
+#endif
+
+ if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECDH_OUT_OF_MEMORY;
+ mr_mip->ERCON=TRUE;
+
+ if (res==0)
+ {
+ q=mirvar_mem(_MIPP_ mem, 0);
+ a=mirvar_mem(_MIPP_ mem, 1);
+ b=mirvar_mem(_MIPP_ mem, 2);
+ s=mirvar_mem(_MIPP_ mem, 3);
+ wx=mirvar_mem(_MIPP_ mem, 4);
+ wy=mirvar_mem(_MIPP_ mem, 5);
+ z=mirvar_mem(_MIPP_ mem, 6);
+
+ bytes_to_big(_MIPP_ EFS,DOM->Q,q);
+ bytes_to_big(_MIPP_ EFS,DOM->A,a);
+ bytes_to_big(_MIPP_ EFS,DOM->B,b);
+
+ bytes_to_big(_MIPP_ S->len,S->val,s);
+
+ ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
+ W=epoint_init_mem(_MIPP_ mem1,0);
+
+ bytes_to_big(_MIPP_ EFS,&(WD->val[1]),wx);
+ bytes_to_big(_MIPP_ EFS,&(WD->val[EFS+1]),wy);
+
+ valid=epoint_set(_MIPP_ wx,wy,0,W);
+
+ if (!valid) res=ECDH_ERROR;
+ }
+ if (res==0)
+ {
+ ecurve_mult(_MIPP_ s,W,W);
+ if (W->marker==MR_EPOINT_INFINITY) res=ECDH_ERROR;
+ else
+ {
+ epoint_get(_MIPP_ W,z,z);
+ Z->len=big_to_bytes(_MIPP_ EFS,z,Z->val,TRUE);
+ }
+ }
+#ifndef MR_STATIC
+ memkill(_MIPP_ mem,7);
+ ecp_memkill(_MIPP_ mem1,1);
+#else
+ memset(mem,0,MR_BIG_RESERVE(7));
+ memset(mem1,0,MR_ECP_RESERVE(1));
+#endif
+
+ err=mr_mip->ERNUM;
+ mirexit(_MIPPO_ );
+ if (err==MR_ERR_OUT_OF_MEMORY) return ECDH_OUT_OF_MEMORY;
+ if (err==MR_ERR_DIV_BY_ZERO) return ECDH_DIV_BY_ZERO;
+ if (err!=0) return -(1000+err);
+ return res;
+}
+
+/* Sign octet F using private key S. Signature in C and D. Must supply RNG */
+
+int ECPSP_DSA(ecp_domain *DOM,csprng *RNG,octet *S,octet *F,octet *C,octet *D)
+{
+ char h[HASH_BYTES];
+ octet H={0,sizeof(h),h};
+#ifdef MR_GENERIC_AND_STATIC
+ miracl instance;
+ miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
+#else
+ miracl *mr_mip=mirsys(DOM->nibbles,16);
+#endif
+ big q,a,b,gx,gy,r,s,f,c,d,u,vx;
+ epoint *G,*V;
+ int err,res=0;
+#ifndef MR_STATIC
+ char *mem=(char *)memalloc(_MIPP_ 12);
+ char *mem1=(char *)ecp_memalloc(_MIPP_ 2);
+#else
+ char mem[MR_BIG_RESERVE(12)];
+ char mem1[MR_ECP_RESERVE(2)];
+ memset(mem,0,MR_BIG_RESERVE(12));
+ memset(mem1,0,MR_ECP_RESERVE(2));
+#endif
+ if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECDH_OUT_OF_MEMORY;
+ mr_mip->ERCON=TRUE;
+
+ hash(F,-1,NULL,NULL,&H); /* hash message */
+ if (res==0)
+ {
+ q=mirvar_mem(_MIPP_ mem, 0);
+ a=mirvar_mem(_MIPP_ mem, 1);
+ b=mirvar_mem(_MIPP_ mem, 2);
+ gx=mirvar_mem(_MIPP_ mem, 3);
+ gy=mirvar_mem(_MIPP_ mem, 4);
+ r=mirvar_mem(_MIPP_ mem, 5);
+ s=mirvar_mem(_MIPP_ mem, 6);
+ f=mirvar_mem(_MIPP_ mem, 7);
+ c=mirvar_mem(_MIPP_ mem, 8);
+ d=mirvar_mem(_MIPP_ mem, 9);
+ u=mirvar_mem(_MIPP_ mem, 10);
+ vx=mirvar_mem(_MIPP_ mem,11);
+
+ bytes_to_big(_MIPP_ EFS,DOM->Q,q);
+ bytes_to_big(_MIPP_ EGS,DOM->R,r);
+ bytes_to_big(_MIPP_ EFS,DOM->Gx,gx);
+ bytes_to_big(_MIPP_ EFS,DOM->Gy,gy);
+ bytes_to_big(_MIPP_ EFS,DOM->A,a);
+ bytes_to_big(_MIPP_ EFS,DOM->B,b);
+ bytes_to_big(_MIPP_ S->len,S->val,s);
+ bytes_to_big(_MIPP_ H.len,H.val,f);
+
+ ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
+ G=epoint_init_mem(_MIPP_ mem1,0);
+ V=epoint_init_mem(_MIPP_ mem1,1);
+ epoint_set(_MIPP_ gx,gy,0,G);
+
+ do {
+ if (mr_mip->ERNUM) break;
+ strong_bigrand(_MIPP_ RNG,r,u);
+
+ ecurve_mult(_MIPP_ u,G,V);
+ epoint_get(_MIPP_ V,vx,vx);
+
+ copy(vx,c);
+ divide(_MIPP_ c,r,r);
+ if (size(c)==0) continue;
+ xgcd(_MIPP_ u,r,u,u,u);
+ mad(_MIPP_ s,c,f,r,r,d);
+ mad(_MIPP_ u,d,u,r,r,d);
+
+ } while (size(d)==0);
+
+ if (res==0)
+ {
+ C->len=big_to_bytes(_MIPP_ EGS,c,C->val,TRUE);
+ D->len=big_to_bytes(_MIPP_ EGS,d,D->val,TRUE);
+ }
+ }
+#ifndef MR_STATIC
+ memkill(_MIPP_ mem,12);
+ ecp_memkill(_MIPP_ mem1,2);
+#else
+ memset(mem,0,MR_BIG_RESERVE(12));
+ memset(mem1,0,MR_ECP_RESERVE(2));
+#endif
+
+ err=mr_mip->ERNUM;
+ mirexit(_MIPPO_ );
+ if (err==MR_ERR_OUT_OF_MEMORY) return ECDH_OUT_OF_MEMORY;
+ if (err==MR_ERR_DIV_BY_ZERO) return ECDH_DIV_BY_ZERO;
+ if (err!=0) return -(1000+err);
+ return res;
+}
+
+/* Verify Signature (C, D) on F using public key W */
+
+int ECPVP_DSA(ecp_domain *DOM,octet *W,octet *F, octet *C,octet *D)
+{
+ char h[HASH_BYTES];
+ octet H={0,sizeof(h),h};
+#ifdef MR_GENERIC_AND_STATIC
+ miracl instance;
+ miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
+#else
+ miracl *mr_mip=mirsys(DOM->nibbles,16);
+#endif
+ big q,r,a,b,gx,gy,wx,wy,f,c,d,h2;
+ int bit,err,res=0;
+ epoint *G,*WP,*P;
+ BOOL compressed,valid;
+#ifndef MR_STATIC
+ char *mem=(char *)memalloc(_MIPP_ 12);
+ char *mem1=(char *)ecp_memalloc(_MIPP_ 3);
+#else
+ char mem[MR_BIG_RESERVE(12)];
+ char mem1[MR_ECP_RESERVE(3)];
+ memset(mem,0,MR_BIG_RESERVE(12));
+ memset(mem1,0,MR_ECP_RESERVE(3));
+#endif
+ if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECDH_OUT_OF_MEMORY;
+ mr_mip->ERCON=TRUE;
+
+ hash(F,-1,NULL,NULL,&H); /* hash message */
+ if (res==0)
+ {
+ q=mirvar_mem(_MIPP_ mem, 0);
+ a=mirvar_mem(_MIPP_ mem, 1);
+ b=mirvar_mem(_MIPP_ mem, 2);
+ gx=mirvar_mem(_MIPP_ mem, 3);
+ gy=mirvar_mem(_MIPP_ mem, 4);
+ r=mirvar_mem(_MIPP_ mem, 5);
+ wx=mirvar_mem(_MIPP_ mem, 6);
+ wy=mirvar_mem(_MIPP_ mem, 7);
+ f=mirvar_mem(_MIPP_ mem, 8);
+ c=mirvar_mem(_MIPP_ mem, 9);
+ d=mirvar_mem(_MIPP_ mem, 10);
+ h2=mirvar_mem(_MIPP_ mem,11);
+
+ bytes_to_big(_MIPP_ EFS,DOM->Q,q);
+ bytes_to_big(_MIPP_ EGS,DOM->R,r);
+ bytes_to_big(_MIPP_ EFS,DOM->Gx,gx);
+ bytes_to_big(_MIPP_ EFS,DOM->Gy,gy);
+ bytes_to_big(_MIPP_ EFS,DOM->A,a);
+ bytes_to_big(_MIPP_ EFS,DOM->B,b);
+ bytes_to_big(_MIPP_ C->len,C->val,c);
+ bytes_to_big(_MIPP_ D->len,D->val,d);
+ bytes_to_big(_MIPP_ H.len,H.val,f);
+
+ if (size(c)<1 || mr_compare(c,r)>=0 || size(d)<1 || mr_compare(d,r)>=0)
+ res=ECDH_INVALID;
+ }
+
+ if (res==0)
+ {
+ xgcd(_MIPP_ d,r,d,d,d);
+ mad(_MIPP_ f,d,f,r,r,f);
+ mad(_MIPP_ c,d,c,r,r,h2);
+
+ ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
+ G=epoint_init_mem(_MIPP_ mem1,0);
+ WP=epoint_init_mem(_MIPP_ mem1,1);
+ P=epoint_init_mem(_MIPP_ mem1,2);
+ epoint_set(_MIPP_ gx,gy,0,G);
+
+ bytes_to_big(_MIPP_ EFS,&(W->val[1]),wx);
+ bytes_to_big(_MIPP_ EFS,&(W->val[EFS+1]),wy);
+
+ valid=epoint_set(_MIPP_ wx,wy,0,WP);
+
+ if (!valid) res=ECDH_ERROR;
+ else
+ {
+ ecurve_mult2(_MIPP_ f,G,h2,WP,P);
+ if (P->marker==MR_EPOINT_INFINITY) res=ECDH_INVALID;
+ else
+ {
+ epoint_get(_MIPP_ P,d,d);
+ divide(_MIPP_ d,r,r);
+ if (mr_compare(d,c)!=0) res=ECDH_INVALID;
+ }
+ }
+ }
+#ifndef MR_STATIC
+ memkill(_MIPP_ mem,12);
+ ecp_memkill(_MIPP_ mem1,3);
+#else
+ memset(mem,0,MR_BIG_RESERVE(12));
+ memset(mem1,0,MR_ECP_RESERVE(3));
+#endif
+
+ err=mr_mip->ERNUM;
+ mirexit(_MIPPO_ );
+ if (err==MR_ERR_OUT_OF_MEMORY) return ECDH_OUT_OF_MEMORY;
+ if (err==MR_ERR_DIV_BY_ZERO) return ECDH_DIV_BY_ZERO;
+ if (err!=0) return -(1000+err);
+ return res;
+}
+
+
+void ECP_ECIES_ENCRYPT(ecp_domain *DOM,octet *P1,octet *P2,csprng *RNG,octet *W,octet *M,int tlen,octet *V,octet *C,octet *T)
+{ /* Inputs: Input params, random number generator, his public key, the message to be encrypted and the MAC length */
+ /* Outputs: my one-time public key, the ciphertext and the MAC tag */
+
+ int i,len;
+ char z[EFS],vz[3*EFS+2],k[32],k1[16],k2[16],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(DOM,RNG,&U,V)!=0) return; /* one time key pair */
+ if (ECPSVDP_DH(DOM,&U,W,&Z)!=0) return;
+
+ OCTET_COPY(V,&VZ);
+ OCTET_JOIN_OCTET(&Z,&VZ);
+
+ KDF2(&VZ,P1,EFS,&K);
+
+/* split key into AES encryption key and MAC key */
+
+ K1.len=K2.len=16;
+ for (i=0;i<16;i++) {K1.val[i]=K.val[i]; K2.val[i]=K.val[16+i];}
+
+ AES_CBC_IV0_ENCRYPT(&K1,M,C);
+
+ OCTET_JOIN_LONG((long)P2->len,8,&L2);
+
+ len=C->len;
+ OCTET_JOIN_OCTET(P2,C);
+ OCTET_JOIN_OCTET(&L2,C);
+ HMAC(C,&K2,tlen,T);
+ C->len=len;
+}
+
+/* ECIES Decryption */
+
+BOOL ECP_ECIES_DECRYPT(ecp_domain *DOM,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M)
+{ /* Inputs: Input params, ciphertext triple V,C,T and recipients private key */
+ /* Output: recovered plaintext M */
+
+ int i,len;
+ char z[EFS],vz[3*EFS+2],k[32],k1[16],k2[16],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(DOM,U,V,&Z)!=0) return FALSE;
+
+ OCTET_COPY(V,&VZ);
+ OCTET_JOIN_OCTET(&Z,&VZ);
+
+ KDF2(&VZ,P1,EFS,&K);
+
+/* split key into AES decryption key and MAC key */
+
+ K1.len=K2.len=16;
+ for (i=0;i<16;i++) {K1.val[i]=K.val[i]; K2.val[i]=K.val[16+i];}
+
+ if (!AES_CBC_IV0_DECRYPT(&K1,C,M)) return FALSE;
+
+ OCTET_JOIN_LONG((long)P2->len,8,&L2);
+
+ len=C->len;
+ OCTET_JOIN_OCTET(P2,C);
+ OCTET_JOIN_OCTET(&L2,C);
+ HMAC(C,&K2,T->len,&TAG);
+ C->len=len;
+
+ if (!OCTET_COMPARE(T,&TAG)) return FALSE;
+
+ return TRUE;
+
+}
+
diff --git a/source/p1363/ecdh.h b/source/p1363/ecdh.h
new file mode 100644
index 0000000..96b8041
--- /dev/null
+++ b/source/p1363/ecdh.h
@@ -0,0 +1,141 @@
+/***************************************************************************
+ *
+Copyright 2013 CertiVox UK Ltd. *
+ *
+This file is part of CertiVox SkyKey XT Crypto SDK. *
+ *
+The CertiVox SkyKey XT Crypto SDK provides developers with an *
+extensive and efficient set of cryptographic functions. *
+For further information about its features and functionalities please *
+refer to http://www.certivox.com *
+ *
+* The CertiVox SkyKey XT Crypto SDK is free software: you can *
+ redistribute it and/or modify it under the terms of the *
+ GNU Affero General Public License as published by the *
+ Free Software Foundation, either version 3 of the License, *
+ or (at your option) any later version. *
+ *
+* The CertiVox SkyKey XT Crypto SDK is distributed in the hope *
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the *
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ See the GNU Affero General Public License for more details. *
+ *
+* You should have received a copy of the GNU Affero General Public *
+ License along with CertiVox MIRACL Crypto SDK. *
+ If not, see . *
+ *
+You can be released from the requirements of the license by purchasing *
+a commercial license. Buying such a license is mandatory as soon as you *
+develop commercial activities involving the CertiVox SkyKey XT Crypto SDK *
+without disclosing the source code of your own applications, or shipping *
+the CertiVox SkyKey XT Crypto SDK with a closed source product. *
+ *
+***************************************************************************/
+
+/*
+ * MIRACL ECDH header file
+ * Author: M. Scott 2013
+ */
+
+#ifndef ECDH_H
+#define ECDH_H
+
+#include "miracl.h"
+#include "octet.h"
+
+#define EAS 16 /* Symmetric Key size - 128 bits */
+#define EGS 32 /* ECCSI Group Size - 256 bits */
+#define EFS 32 /* ECCSI Field Size - 256 bits */
+
+#define ECDH_OK 0
+#define ECDH_DOMAIN_ERROR -1
+#define ECDH_INVALID_PUBLIC_KEY -2
+#define ECDH_ERROR -3
+#define ECDH_INVALID -4
+#define ECDH_DOMAIN_NOT_FOUND -5
+#define ECDH_OUT_OF_MEMORY -6
+#define ECDH_DIV_BY_ZERO -7
+#define ECDH_BAD_ASSUMPTION -8
+
+extern const mr_small ecrom[];
+
+/* ECp domain parameters */
+
+typedef struct
+{
+ int nibbles;
+ char Q[EFS];
+ char A[EFS];
+ char B[EFS];
+ char R[EGS];
+ char Gx[EFS];
+ char Gy[EFS];
+} ecp_domain;
+
+#define HASH_BYTES 32
+
+#if HASH_BYTES==20
+ #define HASHFUNC sha
+ #define SHS_INIT shs_init
+ #define SHS_PROCESS shs_process
+ #define SHS_HASH shs_hash
+ #define HASH_BLOCK 64
+#endif
+
+#if HASH_BYTES==32
+ #define HASHFUNC sha256
+ #define SHS_INIT shs256_init
+ #define SHS_PROCESS shs256_process
+ #define SHS_HASH shs256_hash
+ #define HASH_BLOCK 64
+#endif
+
+#if HASH_BYTES==48
+ #define HASHFUNC sha384
+ #define SHS_INIT shs384_init
+ #define SHS_PROCESS shs384_process
+ #define SHS_HASH shs384_hash
+ #define HASH_BLOCK 128
+#endif
+
+#if HASH_BYTES==64
+ #define HASHFUNC sha512
+ #define SHS_INIT shs512_init
+ #define SHS_PROCESS shs512_process
+ #define SHS_HASH shs512_hash
+ #define HASH_BLOCK 128
+#endif
+
+/* ECDH Auxiliary Functions */
+
+extern void CREATE_CSPRNG(csprng *,octet *);
+extern void KILL_CSPRNG(csprng *);
+extern void HASH(octet *,octet *);
+extern BOOL HMAC(octet *,octet *,int,octet *);
+extern void KDF1(octet *,int,octet *);
+extern void KDF2(octet *,octet *,int,octet *);
+extern void PBKDF2(octet *,octet *,int,int,octet *);
+extern void AES_CBC_IV0_ENCRYPT(octet *,octet *,octet *);
+extern BOOL AES_CBC_IV0_DECRYPT(octet *,octet *,octet *);
+
+/* ECDH primitives - support functions */
+
+extern void ECP_DOMAIN_KILL(ecp_domain *);
+extern int ECP_DOMAIN_INIT(ecp_domain *,const void *);
+extern int ECP_KEY_PAIR_GENERATE(ecp_domain *,csprng *,octet *,octet *);
+extern int ECP_PUBLIC_KEY_VALIDATE(ecp_domain *,BOOL,octet *);
+
+/* ECDH primitives */
+
+extern int ECPSVDP_DH(ecp_domain *,octet *,octet *,octet *);
+extern int ECPSVDP_DHC(ecp_domain *,octet *,octet *,BOOL,octet *);
+
+/* ECIES functions */
+extern void ECP_ECIES_ENCRYPT(ecp_domain *,octet *,octet *,csprng *,octet *,octet *,int,octet *,octet *,octet *);
+extern BOOL ECP_ECIES_DECRYPT(ecp_domain *,octet *,octet *,octet *,octet *,octet *,octet *,octet *);
+
+/* ECDSA functions */
+extern int ECPSP_DSA(ecp_domain *,csprng *,octet *,octet *,octet *,octet *);
+extern int ECPVP_DSA(ecp_domain *,octet *,octet *,octet *,octet *);
+#endif
+
diff --git a/source/p1363/octet.c b/source/p1363/octet.c
new file mode 100644
index 0000000..3b99fa7
--- /dev/null
+++ b/source/p1363/octet.c
@@ -0,0 +1,313 @@
+/***************************************************************************
+ *
+Copyright 2013 CertiVox UK Ltd. *
+ *
+This file is part of CertiVox Crypto SDK. *
+ *
+The CertiVox Crypto SDK provides developers with an *
+extensive and efficient set of cryptographic functions. *
+For further information about its features and functionalities please *
+refer to http://www.certivox.com *
+ *
+* The CertiVox Crypto SDK is free software: you can *
+ redistribute it and/or modify it under the terms of the *
+ GNU Affero General Public License as published by the *
+ Free Software Foundation, either version 3 of the License, *
+ or (at your option) any later version. *
+ *
+* The CertiVox Crypto SDK is distributed in the hope *
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the *
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ See the GNU Affero General Public License for more details. *
+ *
+* You should have received a copy of the GNU Affero General Public *
+ License along with CertiVox MIRACL Crypto SDK. *
+ If not, see . *
+ *
+You can be released from the requirements of the license by purchasing *
+a commercial license. Buying such a license is mandatory as soon as you *
+develop commercial activities involving the CertiVox Crypto SDK *
+without disclosing the source code of your own applications, or shipping *
+the CertiVox Crypto SDK with a closed source product. *
+ *
+***************************************************************************/
+
+
+/*** Basic Octet string maintainance routines ***/
+
+#include "octet.h"
+
+/* Output an octet string (Debug Only) */
+
+void OCTET_OUTPUT(octet *w)
+{
+ int i;
+ unsigned char ch;
+ for (i=0;ilen;i++)
+ {
+ ch=w->val[i];
+ printf("%02x",ch);
+ }
+ printf("\n");
+}
+
+void OCTET_OUTPUT_STRING(octet *w)
+{
+ int i;
+ unsigned char ch;
+ for (i=0;ilen;i++)
+ {
+ ch=w->val[i];
+ printf("%c",ch);
+ }
+ /* printf("\n"); */
+}
+
+/* Convert C string to octet format - truncates if no room */
+
+void OCTET_JOIN_STRING(char *s,octet *y)
+{
+ int i,j;
+ i=y->len;
+ j=0;
+ while (s[j]!=0 && imax)
+ {
+ y->val[i]=s[j];
+ y->len++;
+ i++; j++;
+ }
+}
+
+/* compare 2 octet strings.
+ * If x==y return TRUE, else return FALSE */
+
+int OCTET_COMPARE(octet *x,octet *y)
+{
+ int i;
+ if (x->len>y->len) return 0;
+ if (x->lenlen) return 0;
+ for (i=0;ilen;i++)
+ {
+ if (x->val[i]!=y->val[i]) return 0;
+ }
+ return 1;
+}
+
+/* Append binary string to octet - truncates if no room */
+
+void OCTET_JOIN_BYTES(char *b,int len,octet *y)
+{
+ int i,j;
+ i=y->len;
+ for (j=0;jmax;j++)
+ {
+ y->val[i]=b[j];
+ y->len++;
+ i++;
+ }
+}
+
+/* Concatenates two octet strings */
+
+void OCTET_JOIN_OCTET(octet *x,octet *y)
+{ /* y=y || x */
+ int i,j;
+ if (x==NULL) return;
+
+ for (i=0;ilen;i++)
+ {
+ j=y->len+i;
+ if (j>=y->max)
+ {
+ y->len=y->max;
+ return;
+ }
+ y->val[j]=x->val[i];
+ }
+ y->len+=x->len;
+}
+
+/* Append byte to octet rep times */
+
+void OCTET_JOIN_BYTE(int ch,int rep,octet *y)
+{
+ int i,j;
+ i=y->len;
+ for (j=0;jmax;j++)
+ {
+ y->val[i]=ch;
+ y->len++;
+ i++;
+ }
+}
+
+/* XOR common bytes of x with y */
+
+void OCTET_XOR(octet *x,octet *y)
+{ /* xor first x->len bytes of y */
+
+ int i;
+ for (i=0;ilen && ilen;i++)
+ {
+ y->val[i]^=x->val[i];
+ }
+}
+
+/* clear an octet */
+
+void OCTET_EMPTY(octet *w)
+{
+ w->len=0;
+}
+
+/* Kill an octet string - Zeroise it for security */
+
+void OCTET_CLEAR(octet *w)
+{
+ int i;
+ for (i=0;imax;i++) w->val[i]=0;
+ w->len=0;
+}
+
+/* OCTET_JOIN_LONG primitive */
+/* appends long x of length len bytes to OCTET string */
+
+void OCTET_JOIN_LONG(long x,int len,octet *y)
+{
+ int i,j,n;
+ n=y->len+len;
+ if (n>y->max || len<=0) return;
+ for (i=y->len;ival[i]=0;
+ y->len=n;
+
+ i=y->len;
+ while (x>0 && i>0)
+ {
+ i--;
+ y->val[i]=x%256;
+ x/=256;
+ }
+}
+
+/* Pad an octet to a given length */
+
+void OCTET_PAD(int n,octet *w)
+{
+ int i,d;
+ if (w->len>=n || n>w->max) return;
+ d=n-w->len;
+ for (i=n-1;i>=d;i--)
+ w->val[i]=w->val[i-d];
+ for (i=d-1;i>=0;i--)
+ w->val[i]=0;
+ w->len=n;
+}
+
+/* Convert an octet string to base64 string */
+
+void OCTET_TO_BASE64(octet *w,char *b)
+{
+ int i,j,k,rem,last;
+ int c,ch[4];
+ unsigned char ptr[3];
+ rem=w->len%3; j=k=0; last=4;
+ while (jlen)
+ {
+ for (i=0;i<3;i++)
+ {
+ if (jlen) ptr[i]=w->val[j++];
+ else {ptr[i]=0; last--;}
+ }
+ ch[0]=(ptr[0]>>2)&0x3f;
+ ch[1]=((ptr[0]<<4)|(ptr[1]>>4))&0x3f;
+ ch[2]=((ptr[1]<<2)|(ptr[2]>>6))&0x3f;
+ ch[3]=ptr[2]&0x3f;
+ for (i=0;i=26 && c<52) c+=71;
+ if (c>=52 && c<62) c-=4;
+ if (c==62) c='+';
+ if (c==63) c='/';
+ b[k++]=c;
+ }
+ }
+ if (rem>0) for (i=rem;i<3;i++) b[k++]='=';
+ b[k]='\0'; // dangerous!
+}
+
+void OCTET_FROM_BASE64(char *b,octet *w)
+{
+ int i,j,k,pads,len=strlen(b);
+ int c,ch[4],ptr[3];
+ int lead=1;
+ j=k=0;
+ while (jmax)
+ {
+ pads=0;
+ for (i=0;i<4;i++)
+ {
+ c=80+b[j++];
+ if (c<=112) continue; /* ignore white space */
+ if (c>144 && c<171) c-=145;
+ if (c>176 && c<203) c-=151;
+ if (c>127 && c<138) c-=76;
+ if (c==123) c=62;
+ if (c==127) c=63;
+ if (c==141) {pads++; continue;} /* ignore pads '=' */
+ ch[i]=c;
+ }
+ ptr[0]=(ch[0]<<2)|(ch[1]>>4);
+ ptr[1]=(ch[1]<<4)|(ch[2]>>2);
+ ptr[2]=(ch[2]<<6)|ch[3];
+ for (i=0;i<3-pads && kmax;i++)
+ { /* don't put in leading zeros */
+ /* if (lead && ptr[i]==0) continue; */
+ w->val[k++]=ptr[i];
+ lead=0;
+ }
+
+ }
+ w->len=k;
+}
+
+/* copy an octet string - truncates if no room */
+
+void OCTET_COPY(octet *x,octet *y)
+{
+ int i;
+ OCTET_CLEAR(y);
+ y->len=x->len;
+ if (y->len>y->max) y->len=y->max;
+
+ for (i=0;ilen;i++)
+ y->val[i]=x->val[i];
+}
+
+/* XOR m with all of x */
+
+void OCTET_XOR_BYTE(int m,octet *x)
+{
+ int i;
+ for (i=0;ilen;i++) x->val[i]^=m;
+}
+
+/* truncates x to n bytes and places the rest in y (if y is not NULL) */
+
+void OCTET_CHOP(octet *x,int n,octet *y)
+{
+ int i;
+ if (n>=x->len)
+ {
+ if (y!=NULL) y->len=0;
+ return;
+ }
+ if (y!=NULL) y->len=x->len-n;
+ x->len=n;
+
+ if (y!=NULL)
+ {
+ for (i=0;ilen && imax;i++) y->val[i]=x->val[i+n];
+ }
+}
diff --git a/source/p1363/octet.h b/source/p1363/octet.h
new file mode 100644
index 0000000..f950f98
--- /dev/null
+++ b/source/p1363/octet.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ *
+Copyright 2013 CertiVox UK Ltd. *
+ *
+This file is part of CertiVox Crypto SDK. *
+ *
+The CertiVox Crypto SDK provides developers with an *
+extensive and efficient set of cryptographic functions. *
+For further information about its features and functionalities please *
+refer to http://www.certivox.com *
+ *
+* The CertiVox Crypto SDK is free software: you can *
+ redistribute it and/or modify it under the terms of the *
+ GNU Affero General Public License as published by the *
+ Free Software Foundation, either version 3 of the License, *
+ or (at your option) any later version. *
+ *
+* The CertiVox Crypto SDK is distributed in the hope *
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the *
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ See the GNU Affero General Public License for more details. *
+ *
+* You should have received a copy of the GNU Affero General Public *
+ License along with CertiVox MIRACL Crypto SDK. *
+ If not, see . *
+ *
+You can be released from the requirements of the license by purchasing *
+a commercial license. Buying such a license is mandatory as soon as you *
+develop commercial activities involving the CertiVox Crypto SDK *
+without disclosing the source code of your own applications, or shipping *
+the CertiVox Crypto SDK with a closed source product. *
+ *
+***************************************************************************/
+
+
+#ifndef OCTET_H
+#define OCTET_H
+
+#include
+#include
+#include
+
+/* portable representation of a big positive number */
+
+typedef struct
+{
+ int len;
+ int max;
+ char *val;
+} octet;
+
+/* Octet string handlers */
+
+extern void OCTET_OUTPUT(octet *);
+extern void OCTET_OUTPUT_STRING(octet *);
+extern void OCTET_CLEAR(octet *);
+extern int OCTET_COMPARE(octet *,octet *);
+extern void OCTET_JOIN_STRING(char *,octet *);
+extern void OCTET_JOIN_BYTES(char *,int,octet *);
+extern void OCTET_JOIN_BYTE(int,int,octet *);
+extern void OCTET_JOIN_OCTET(octet *,octet *);
+extern void OCTET_XOR(octet *,octet *);
+extern void OCTET_EMPTY(octet *);
+extern void OCTET_PAD(int,octet *);
+extern void OCTET_TO_BASE64(octet *,char *);
+extern void OCTET_FROM_BASE64(char *,octet *);
+extern void OCTET_COPY(octet *,octet *);
+extern void OCTET_XOR_BYTE(int,octet *);
+extern void OCTET_CHOP(octet *,int,octet *);
+extern void OCTET_JOIN_LONG(long,int,octet *);
+
+#endif
diff --git a/source/p1363/testecc.c b/source/p1363/testecc.c
new file mode 100644
index 0000000..2953659
--- /dev/null
+++ b/source/p1363/testecc.c
@@ -0,0 +1,206 @@
+/***************************************************************************
+ *
+Copyright 2013 CertiVox UK Ltd. *
+ *
+This file is part of CertiVox Crypto SDK. *
+ *
+The CertiVox Crypto SDK provides developers with an *
+extensive and efficient set of cryptographic functions. *
+For further information about its features and functionalities please *
+refer to http://www.certivox.com *
+ *
+* The CertiVox Crypto SDK is free software: you can *
+ redistribute it and/or modify it under the terms of the *
+ GNU Affero General Public License as published by the *
+ Free Software Foundation, either version 3 of the License, *
+ or (at your option) any later version. *
+ *
+* The CertiVox Crypto SDK is distributed in the hope *
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the *
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ See the GNU Affero General Public License for more details. *
+ *
+* You should have received a copy of the GNU Affero General Public *
+ License along with CertiVox MIRACL Crypto SDK. *
+ If not, see . *
+ *
+You can be released from the requirements of the license by purchasing *
+a commercial license. Buying such a license is mandatory as soon as you *
+develop commercial activities involving the CertiVox Crypto SDK *
+without disclosing the source code of your own applications, or shipping *
+the CertiVox Crypto SDK with a closed source product. *
+ *
+***************************************************************************/
+
+/* This file implements a typical thread-safe API for MIRACL */
+/* Static build - requires no heap */
+/* See comments in ecdh.c for more details on the build */
+/* Derived from p1363.c code */
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA Functions */
+/* cl /O2 testecc.c ecdh.c octet.c miracl.lib */
+
+#include
+#include
+#include
+#include
+#include "ecdh.h"
+
+int main(int argc,char **argv)
+{
+ int i,res;
+ BOOL result;
+ char *pp="M0ng00se";
+/* These octets are automatically protected against buffer overflow attacks */
+/* Note salt must be big enough to include an appended word */
+/* Note ECIES ciphertext C must be big enough to include at least 1 appended block */
+/* Recall EFS is field size in bytes. So EFS=32 for 256-bit curve */
+ char s0[EGS],s1[EGS],w0[2*EFS+1],w1[2*EFS+1],z0[EFS],z1[EFS],raw[100],key[EAS],salt[32],pw[20],b64[4+((8*EFS+4)/3)],p1[30],p2[30],v[2*EFS+1],m[32],c[64],t[32],cs[EGS],ds[EGS];
+ octet S0={0,sizeof(s0),s0};
+ octet S1={0,sizeof(s1),s1};
+ octet W0={0,sizeof(w0),w0};
+ octet W1={0,sizeof(w1),w1};
+ octet Z0={0,sizeof(z0),z0};
+ octet Z1={0,sizeof(z1),z1};
+ octet RAW={0,sizeof(raw),raw};
+ octet KEY={0,sizeof(key),key};
+ octet SALT={0,sizeof(salt),salt};
+ octet PW={0,sizeof(pw),pw};
+ octet P1={0,sizeof(p1),p1};
+ octet P2={0,sizeof(p2),p2};
+ octet V={0,sizeof(v),v};
+ octet M={0,sizeof(m),m};
+ octet C={0,sizeof(c),c};
+ octet T={0,sizeof(t),t};
+ octet CS={0,sizeof(cs),cs};
+ octet DS={0,sizeof(ds),ds};
+
+ ecp_domain epdom;
+ csprng RNG; /* Crypto Strong RNG */
+
+ RAW.len=100; /* fake random seed source */
+ for (i=0;i<100;i++) RAW.val[i]=i+1;
+
+ CREATE_CSPRNG(&RNG,&RAW); /* initialise strong RNG */
+
+ SALT.len=8;
+ for (i=0;i<8;i++) SALT.val[i]=i+1; // set Salt
+
+ printf("Alice's Passphrase= %s\n",pp);
+
+ OCTET_JOIN_STRING(pp,&PW); // set Password from string
+
+/* First set up Elliptic Curve from ROM data */
+
+ ECP_DOMAIN_INIT(&epdom,ecrom);
+
+/* private key S0 of size EGS bytes derived from Password and Salt */
+
+ PBKDF2(&PW,&SALT,1000,EGS,&S0);
+ OCTET_TO_BASE64(&S0,b64);
+ printf("Alices private key= %s\n",b64);
+
+/* Generate Key pair S/W */
+
+ ECP_KEY_PAIR_GENERATE(&epdom,NULL,&S0,&W0);
+ res=ECP_PUBLIC_KEY_VALIDATE(&epdom,TRUE,&W0);
+ if (res!=0)
+ {
+ printf("ECP Public Key is invalid!\n");
+ return 0;
+ }
+ OCTET_TO_BASE64(&W0,b64);
+ printf("Alice's public key= %s\n",b64);
+ OCTET_FROM_BASE64(b64,&W0);
+
+/* Random private key for other party */
+
+ S1.len=3; S1.val[0]=0x01; S1.val[1]=0x23; S1.val[2]=0x45;
+
+ ECP_KEY_PAIR_GENERATE(&epdom,NULL,&S1,&W1);
+ res=ECP_PUBLIC_KEY_VALIDATE(&epdom,TRUE,&W1);
+ if (res!=0)
+ {
+ printf("ECP Public Key is invalid!\n");
+ return 0;
+ }
+ OCTET_TO_BASE64(&W1,b64);
+ printf("Servers public key= %s\n",b64);
+ OCTET_FROM_BASE64(b64,&W1);
+
+/* Calculate common key using DH - IEEE 1363 method */
+
+ ECPSVDP_DH(&epdom,&S0,&W1,&Z0);
+ ECPSVDP_DH(&epdom,&S1,&W0,&Z1);
+
+ if (!OCTET_COMPARE(&Z0,&Z1))
+ {
+ printf("*** ECPSVDP-DH Failed\n");
+ return 0;
+ }
+
+ KDF1(&Z0,EAS,&KEY);
+ printf("Alice's DH Key= "); for (i=0;i