http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/mpin.c ---------------------------------------------------------------------- diff --git a/version22/c/mpin.c b/version22/c/mpin.c new file mode 100644 index 0000000..5086ad5 --- /dev/null +++ b/version22/c/mpin.c @@ -0,0 +1,1212 @@ +/* +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. +*/ + +/* MPIN Functions */ + +/* Version 3.0 - supports Time Permits */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "mpin.h" + +#define ROUNDUP(a,b) ((a)-1)/(b)+1 + +/* Special mpin hashing */ +static void mpin_hash(int sha,FP4 *f, ECP *P,octet *w) +{ + int i; + BIG x,y; + char h[64]; + hash256 sha256; + hash512 sha512; + char t[6*MODBYTES]; // to hold 6 BIGs + int hlen=sha; + BIG_copy(x,f->a.a); + FP_redc(x); + BIG_toBytes(&t[0],x); + BIG_copy(x,f->a.b); + FP_redc(x); + BIG_toBytes(&t[MODBYTES],x); + BIG_copy(x,f->b.a); + FP_redc(x); + BIG_toBytes(&t[2*MODBYTES],x); + BIG_copy(x,f->b.b); + FP_redc(x); + BIG_toBytes(&t[3*MODBYTES],x); + ECP_get(x,y,P); + BIG_toBytes(&t[4*MODBYTES],x); + BIG_toBytes(&t[5*MODBYTES],y); + + OCT_empty(w); + switch (sha) + { + case SHA256: + HASH256_init(&sha256); + for (i=0; i<6*MODBYTES; i++) HASH256_process(&sha256,t[i]); + HASH256_hash(&sha256,h); + break; + case SHA384: + HASH384_init(&sha512); + for (i=0; i<6*MODBYTES; i++) HASH384_process(&sha512,t[i]); + HASH384_hash(&sha512,h); + break; + case SHA512: + HASH512_init(&sha512); + for (i=0; i<6*MODBYTES; i++) HASH512_process(&sha512,t[i]); + HASH512_hash(&sha512,h); + break; + } + + OCT_jbytes(w,h,PAS); + for (i=0; i<hlen; i++) h[i]=0; +} + +/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */ +/* maps a random u to a point on the curve */ +static void map(ECP *P,BIG u,int cb) +{ + BIG x,q; + + BIG_rcopy(q,Modulus); + BIG_copy(x,u); + BIG_mod(x,q); + + while (!ECP_setx(P,x,cb)) + BIG_inc(x,1); +} + +/* returns u derived from P. Random value in range 1 to return value should then be added to u */ +static int unmap(BIG u,int *cb,ECP *P) +{ + int s,r=0; + BIG x; + + s=ECP_get(x,x,P); + BIG_copy(u,x); + do + { + BIG_dec(u,1); + r++; + } + while (!ECP_setx(P,u,s)); + ECP_setx(P,x,s); + + *cb=s; + + return r; +} + +/* map octet string containing hash to point on curve of correct order */ +static void mapit(octet *h,ECP *P) +{ + BIG q,x,c; + BIG_fromBytes(x,h->val); + BIG_rcopy(q,Modulus); + BIG_mod(x,q); + + while (!ECP_setx(P,x,0)) + BIG_inc(x,1); + + BIG_rcopy(c,CURVE_Cof); + ECP_mul(P,c); +} + +/* needed for SOK */ +/* static void mapit2(octet *h,ECP2 *Q) */ +/* { */ +/* BIG q,one,Fx,Fy,x,hv; */ +/* FP2 X; */ +/* ECP2 T,K; */ +/* BIG_fromBytes(hv,h->val); */ +/* BIG_rcopy(q,Modulus); */ +/* BIG_one(one); */ +/* BIG_mod(hv,q); */ + +/* for (;;) */ +/* { */ +/* FP2_from_BIGs(&X,one,hv); */ +/* if (ECP2_setx(Q,&X)) break; */ +/* BIG_inc(hv,1); */ +/* } */ + +/* /\* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez *\/ */ +/* BIG_rcopy(Fx,CURVE_Fra); */ +/* BIG_rcopy(Fy,CURVE_Frb); */ +/* FP2_from_BIGs(&X,Fx,Fy); */ +/* BIG_rcopy(x,CURVE_Bnx); */ + +/* ECP2_copy(&T,Q); */ +/* ECP2_mul(&T,x); */ +/* ECP2_neg(&T); /\* our x is negative *\/ */ +/* ECP2_copy(&K,&T); */ +/* ECP2_dbl(&K); */ +/* ECP2_add(&K,&T); */ +/* ECP2_affine(&K); */ + +/* ECP2_frob(&K,&X); */ +/* ECP2_frob(Q,&X); ECP2_frob(Q,&X); ECP2_frob(Q,&X); */ +/* ECP2_add(Q,&T); */ +/* ECP2_add(Q,&K); */ +/* ECP2_frob(&T,&X); ECP2_frob(&T,&X); */ +/* ECP2_add(Q,&T); */ +/* ECP2_affine(Q); */ +/* } */ + + + +/* general purpose hash function w=hash(p|n|x|y) */ +static void hashit(int sha,int n,octet *x,octet *w) +{ + 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; + + 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; + } + } + + for (i=0; i<hlen; i++) hh[i]=0; + 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 (hlen>=MODBYTES) + OCT_jbytes(w,hh,MODBYTES); + else + { + OCT_jbytes(w,hh,hlen); + OCT_jbyte(w,0,MODBYTES-hlen); + } +} + +unsign32 MPIN_today(void) +{ + /* return time in slots since epoch */ + unsign32 ti=(unsign32)time(NULL); + return (uint32_t)(ti/(60*TIME_SLOT_MINUTES)); +} + +/* Hash the M-Pin transcript - new */ + +void MPIN_HASH_ALL(int sha,octet *HID,octet *xID,octet *xCID,octet *SEC,octet *Y,octet *R,octet *W,octet *H) +{ + char t[10*MODBYTES+4]; + octet T= {0,sizeof(t),t}; + + OCT_joctet(&T,HID); + if (xCID!=NULL) OCT_joctet(&T,xCID); + else OCT_joctet(&T,xID); + OCT_joctet(&T,SEC); + OCT_joctet(&T,Y); + OCT_joctet(&T,R); + OCT_joctet(&T,W); + + hashit(sha,0,&T,H); +} + +void MPIN_HASH_ID(int sha,octet *ID,octet *HID) +{ + hashit(sha,0,ID,HID); +} + +/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */ +/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */ +/* Note that u and v are indistinguisible from random strings */ +int MPIN_ENCODING(csprng *RNG,octet *E) +{ + int rn,m,su,sv,res=0; + + BIG q,u,v; + ECP P,W; + + if (!ECP_fromOctet(&P,E)) res=MPIN_INVALID_POINT; + + if (res==0) + { + BIG_rcopy(q,Modulus); + + BIG_randomnum(u,q,RNG); + + su=RAND_byte(RNG); + if (su<0) su=-su; + su%=2; + map(&W,u,su); + ECP_sub(&P,&W); + + rn=unmap(v,&sv,&P); + m=RAND_byte(RNG); + if (m<0) m=-m; + m%=rn; + BIG_inc(v,m+1); + E->val[0]=su+2*sv; + BIG_toBytes(&(E->val[1]),u); + BIG_toBytes(&(E->val[PFS+1]),v); + } + + return res; +} + +int MPIN_DECODING(octet *D) +{ + int su,sv; + BIG u,v; + ECP P,W; + int res=0; + + if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT; + if (res==0) + { + + BIG_fromBytes(u,&(D->val[1])); + BIG_fromBytes(v,&(D->val[PFS+1])); + + su=D->val[0]&1; + sv=(D->val[0]>>1)&1; + + map(&W,u,su); + map(&P,v,sv); + + ECP_add(&P,&W); + ECP_toOctet(D,&P); + } + return res; +} + +/* R=R1+R2 in group G1 */ +int MPIN_RECOMBINE_G1(octet *R1,octet *R2,octet *R) +{ + ECP P,T; + int res=0; + if (res==0) + { + if (!ECP_fromOctet(&P,R1)) res=MPIN_INVALID_POINT; + if (!ECP_fromOctet(&T,R2)) res=MPIN_INVALID_POINT; + } + if (res==0) + { + ECP_add(&P,&T); + ECP_toOctet(R,&P); + } + return res; +} + +/* W=W1+W2 in group G2 */ +int MPIN_RECOMBINE_G2(octet *W1,octet *W2,octet *W) +{ + ECP2 Q,T; + int res=0; + if (!ECP2_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT; + if (!ECP2_fromOctet(&T,W2)) res=MPIN_INVALID_POINT; + if (res==0) + { + ECP2_add(&Q,&T); + ECP2_toOctet(W,&Q); + } + return res; +} + +/* create random secret S */ +int MPIN_RANDOM_GENERATE(csprng *RNG,octet* S) +{ + BIG r,s; + + BIG_rcopy(r,CURVE_Order); + BIG_randomnum(s,r,RNG); +#ifdef AES_S + BIG_mod2m(s,2*AES_S); +#endif + BIG_toBytes(S->val,s); + S->len=MODBYTES; + return 0; +} + +/* Extract PIN from TOKEN for identity CID */ +int MPIN_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN) +{ + ECP P,R; + int res=0; + char h[MODBYTES]; + octet H= {0,sizeof(h),h}; + + if (!ECP_fromOctet(&P,TOKEN)) res=MPIN_INVALID_POINT; + if (res==0) + { + hashit(sha,-1,CID,&H); + mapit(&H,&R); + + pin%=MAXPIN; + + ECP_pinmul(&R,pin,PBLEN); + ECP_sub(&P,&R); + + ECP_toOctet(TOKEN,&P); + } + return res; +} + +/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */ +int MPIN_CLIENT_2(octet *X,octet *Y,octet *SEC) +{ + BIG px,py,r; + ECP P; + int res=0; + BIG_rcopy(r,CURVE_Order); + if (!ECP_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT; + if (res==0) + { + BIG_fromBytes(px,X->val); + BIG_fromBytes(py,Y->val); + BIG_add(px,px,py); + BIG_mod(px,r); + // BIG_sub(px,r,px); + PAIR_G1mul(&P,px); + ECP_neg(&P); + ECP_toOctet(SEC,&P); + } + return res; +} + +/* + W=x*H(G); + if RNG == NULL then X is passed in + if RNG != NULL the X is passed out + if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve +*/ + +int MPIN_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W) +{ + ECP P; + BIG r,x; + int res=0; + if (RNG!=NULL) + { + BIG_rcopy(r,CURVE_Order); + BIG_randomnum(x,r,RNG); +#ifdef AES_S + BIG_mod2m(x,2*AES_S); +#endif + X->len=MODBYTES; + BIG_toBytes(X->val,x); + } + else + BIG_fromBytes(x,X->val); + + if (type==0) + { + if (!ECP_fromOctet(&P,G)) res=MPIN_INVALID_POINT; + } + else mapit(G,&P); + + if (res==0) + { + PAIR_G1mul(&P,x); + ECP_toOctet(W,&P); + } + return res; +} + +/* + if RNG == NULL then X is passed in + if RNG != NULL the X is passed out + W=x*G where G is point on the curve + if type==1 W=(x^-1)G +*/ + +int MPIN_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W) +{ + ECP2 P; + BIG r,x; + int res=0; + BIG_rcopy(r,CURVE_Order); + if (RNG!=NULL) + { + BIG_randomnum(x,r,RNG); +#ifdef AES_S + BIG_mod2m(x,2*AES_S); +#endif + X->len=MODBYTES; + BIG_toBytes(X->val,x); + } + else + { + BIG_fromBytes(x,X->val); + if (type==1) BIG_invmodp(x,x,r); + } + + if (!ECP2_fromOctet(&P,G)) res=MPIN_INVALID_POINT; + + if (res==0) + { + PAIR_G2mul(&P,x); + ECP2_toOctet(W,&P); + } + return res; +} + + + +/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */ +/* CID is hashed externally */ +int MPIN_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST) +{ + return MPIN_GET_G1_MULTIPLE(NULL,1,S,CID,CST); +} + +/* Implement step 1 on client side of MPin protocol */ +int MPIN_CLIENT_1(int sha,int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT) +{ + BIG r,x; + ECP P,T,W; + int res=0; + char h[MODBYTES]; + octet H= {0,sizeof(h),h}; + + BIG_rcopy(r,CURVE_Order); + if (RNG!=NULL) + { + BIG_randomnum(x,r,RNG); +#ifdef AES_S + BIG_mod2m(x,2*AES_S); +#endif + X->len=MODBYTES; + BIG_toBytes(X->val,x); + } + else + BIG_fromBytes(x,X->val); + + hashit(sha,-1,CLIENT_ID,&H); + mapit(&H,&P); + + if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT; + + if (res==0) + { + pin%=MAXPIN; + + ECP_copy(&W,&P); // W=H(ID) + ECP_pinmul(&W,pin,PBLEN); // W=alpha.H(ID) + ECP_add(&T,&W); // T=Token+alpha.H(ID) = s.H(ID) + + if (date) + { + if (PERMIT!=NULL) + { + if (!ECP_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT; + ECP_add(&T,&W); // SEC=s.H(ID)+s.H(T|ID) + } + hashit(sha,date,&H,&H); + mapit(&H,&W); + if (xID!=NULL) + { + PAIR_G1mul(&P,x); // P=x.H(ID) + ECP_toOctet(xID,&P); // xID + PAIR_G1mul(&W,x); // W=x.H(T|ID) + ECP_add(&P,&W); + } + else + { + ECP_add(&P,&W); + PAIR_G1mul(&P,x); + } + if (xCID!=NULL) ECP_toOctet(xCID,&P); // U + } + else + { + if (xID!=NULL) + { + PAIR_G1mul(&P,x); // P=x.H(ID) + ECP_toOctet(xID,&P); // xID + } + } + } + + if (res==0) + ECP_toOctet(SEC,&T); // V + + return res; +} + +/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ +int MPIN_GET_SERVER_SECRET(octet *S,octet *SST) +{ + BIG r,s; + FP2 qx,qy; + ECP2 Q; + int res=0; + + BIG_rcopy(r,CURVE_Order); + BIG_rcopy(qx.a,CURVE_Pxa); + FP_nres(qx.a); + BIG_rcopy(qx.b,CURVE_Pxb); + FP_nres(qx.b); + BIG_rcopy(qy.a,CURVE_Pya); + FP_nres(qy.a); + BIG_rcopy(qy.b,CURVE_Pyb); + FP_nres(qy.b); + ECP2_set(&Q,&qx,&qy); + + if (res==0) + { + BIG_fromBytes(s,S->val); + PAIR_G2mul(&Q,s); + ECP2_toOctet(SST,&Q); + } + + return res; +} + + +/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */ +int MPIN_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT) +{ + BIG s; + ECP P; + char h[MODBYTES]; + octet H= {0,sizeof(h),h}; + + hashit(sha,date,CID,&H); + + mapit(&H,&P); + BIG_fromBytes(s,S->val); + PAIR_G1mul(&P,s); + + ECP_toOctet(CTT,&P); + return 0; +} + +// if date=0 only use HID, set HCID=NULL +// if date and PE, use HID and HCID + +/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */ +void MPIN_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID) +{ + char h[MODBYTES]; + octet H= {0,sizeof(h),h}; + ECP P,R; + +#ifdef USE_ANONYMOUS + mapit(CID,&P); +#else + hashit(sha,-1,CID,&H); + mapit(&H,&P); +#endif + + ECP_toOctet(HID,&P); // new + + if (date) + { + // if (HID!=NULL) ECP_toOctet(HID,&P); +#ifdef USE_ANONYMOUS + hashit(sha,date,CID,&H); +#else + hashit(sha,date,&H,&H); +#endif + mapit(&H,&R); + ECP_add(&P,&R); + ECP_toOctet(HTID,&P); + } + //else ECP_toOctet(HID,&P); + +} + +/* Implement M-Pin on server side */ +int MPIN_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F) +{ + BIG px,py,y; + FP2 qx,qy; + FP12 g; + ECP2 Q,sQ; + ECP P,R; + int res=0; + + BIG_rcopy(qx.a,CURVE_Pxa); + FP_nres(qx.a); + BIG_rcopy(qx.b,CURVE_Pxb); + FP_nres(qx.b); + BIG_rcopy(qy.a,CURVE_Pya); + FP_nres(qy.a); + BIG_rcopy(qy.b,CURVE_Pyb); + FP_nres(qy.b); + + if (!ECP2_set(&Q,&qx,&qy)) res=MPIN_INVALID_POINT; + + if (res==0) + { + if (!ECP2_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT; + } + + if (res==0) + { + if (date) + { + BIG_fromBytes(px,&(xCID->val[1])); + BIG_fromBytes(py,&(xCID->val[PFS+1])); + } + else + { + BIG_fromBytes(px,&(xID->val[1])); + BIG_fromBytes(py,&(xID->val[PFS+1])); + } + if (!ECP_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT) + } + if (res==0) + { + BIG_fromBytes(y,Y->val); + if (date) + { + if (!ECP_fromOctet(&P,HTID)) res=MPIN_INVALID_POINT; + } + else + { + if (!ECP_fromOctet(&P,HID)) res=MPIN_INVALID_POINT; + } + } + if (res==0) + { + PAIR_G1mul(&P,y); // y(A+AT) + ECP_add(&P,&R); // x(A+AT)+y(A+T) + if (!ECP_fromOctet(&R,mSEC)) res=MPIN_INVALID_POINT; // V + } + if (res==0) + { + PAIR_double_ate(&g,&Q,&R,&sQ,&P); + PAIR_fexp(&g); + + if (!FP12_isunity(&g)) + { + if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL) + { + /* xID is set to NULL if there is no way to calculate PIN error */ + FP12_toOctet(E,&g); + + /* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */ + + if (date) + { + if (!ECP_fromOctet(&P,HID)) res=MPIN_INVALID_POINT; + if (!ECP_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U + + if (res==0) + { + PAIR_G1mul(&P,y); // yA + ECP_add(&P,&R); // yA+xA + } + } + if (res==0) + { + PAIR_ate(&g,&Q,&P); + PAIR_fexp(&g); + FP12_toOctet(F,&g); + } + } + res=MPIN_BAD_PIN; + } + } + + return res; +} + +#if MAXPIN==10000 +#define MR_TS 10 /* 2^10/10 approx = sqrt(MAXPIN) */ +#define TRAP 200 /* 2*sqrt(MAXPIN) */ +#endif + +#if MAXPIN==1000000 +#define MR_TS 14 +#define TRAP 2000 +#endif + +/* Pollards kangaroos used to return PIN error */ +int MPIN_KANGAROO(octet *E,octet *F) +{ + int i,j,m,s,dn,dm,steps; + int distance[MR_TS]; + FP12 ge,gf,t,table[MR_TS]; + int res=0; + // BIG w; + + FP12_fromOctet(&ge,E); + FP12_fromOctet(&gf,F); + + FP12_copy(&t,&gf); + + for (s=1,m=0; m<MR_TS; m++) + { + distance[m]=s; + FP12_copy(&table[m],&t); + s*=2; + FP12_usqr(&t,&t); + FP12_reduce(&t); + } + + FP12_one(&t); + + for (dn=0,j=0; j<TRAP; j++) + { + + //BIG_copy(w,t.a.a.a); + //FP_redc(w); + //i=BIG_lastbits(w,20)%MR_TS; + + i=t.a.a.a[0]%MR_TS; + + FP12_mul(&t,&table[i]); + FP12_reduce(&t); + dn+=distance[i]; + } + + FP12_conj(&gf,&t); + steps=0; + dm=0; + while (dm-dn<MAXPIN) + { + steps++; + if (steps>4*TRAP) break; + + //BIG_copy(w,ge.a.a.a); + //FP_redc(w); + //i=BIG_lastbits(w,20)%MR_TS; + + i=ge.a.a.a[0]%MR_TS; + + FP12_mul(&ge,&table[i]); + FP12_reduce(&ge); + dm+=distance[i]; + if (FP12_equals(&ge,&t)) + { + res=dm-dn; + break; + } + if (FP12_equals(&ge,&gf)) + { + res=dn-dm; + break; + } + } + if (steps>4*TRAP || dm-dn>=MAXPIN) + { + res=0; /* Trap Failed - probable invalid token */ + } + + return res; +} + +/* Functions to support M-Pin Full */ + +int MPIN_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2) +{ + ECP P,T; + ECP2 Q; + FP2 qx,qy; + FP12 g; + int res=0; + + if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT; + + if (res==0) + { + mapit(CID,&P); + if (CP!=NULL) + { + if (!ECP2_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT; + } + else + { + BIG_rcopy(qx.a,CURVE_Pxa); + FP_nres(qx.a); + BIG_rcopy(qx.b,CURVE_Pxb); + FP_nres(qx.b); + BIG_rcopy(qy.a,CURVE_Pya); + FP_nres(qy.a); + BIG_rcopy(qy.b,CURVE_Pyb); + FP_nres(qy.b); + if (!ECP2_set(&Q,&qx,&qy)) res=MPIN_INVALID_POINT; + } + } + if (res==0) + { + PAIR_ate(&g,&Q,&T); + PAIR_fexp(&g); + + FP12_toOctet(G1,&g); + if (G2!=NULL) + { + PAIR_ate(&g,&Q,&P); + PAIR_fexp(&g); + FP12_toOctet(G2,&g); + } + } + return res; +} + +/* calculate common key on client side */ +/* wCID = w.(A+AT) */ +int MPIN_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK) +{ + FP12 g1,g2; + FP4 c,cp,cpm1,cpm2; + FP2 f; + ECP W; + int res=0; + BIG r,z,x,q,m,a,b,h; + + FP12_fromOctet(&g1,G1); + FP12_fromOctet(&g2,G2); + BIG_fromBytes(z,R->val); + BIG_fromBytes(x,X->val); + BIG_fromBytes(h,H->val); + + if (!ECP_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT; + + if (res==0) + { + BIG_rcopy(r,CURVE_Order); + BIG_add(z,z,h); // new + BIG_mod(z,r); + + PAIR_G1mul(&W,x); + + 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,z); + BIG_mod(a,m); + + BIG_copy(b,z); + BIG_sdiv(b,m); + + FP12_pinpow(&g2,pin,PBLEN); + FP12_mul(&g1,&g2); + + FP12_trace(&c,&g1); + + FP12_copy(&g2,&g1); + FP12_frob(&g2,&f); + FP12_trace(&cp,&g2); + + FP12_conj(&g1,&g1); + FP12_mul(&g2,&g1); + FP12_trace(&cpm1,&g2); + FP12_mul(&g2,&g1); + FP12_trace(&cpm2,&g2); + + FP4_xtr_pow2(&c,&cp,&c,&cpm1,&cpm2,a,b); + mpin_hash(sha,&c,&W,CK); + + } + return res; +} + +/* calculate common key on server side */ +/* Z=r.A - no time permits involved */ + +int MPIN_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK) +{ + int res=0; + FP12 g; + FP4 c; + ECP R,U,A; + ECP2 sQ; + BIG w,h; + + if (!ECP2_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT; + if (!ECP_fromOctet(&R,Z)) res=MPIN_INVALID_POINT; + + + if (!ECP_fromOctet(&A,HID)) res=MPIN_INVALID_POINT; + + // new + if (xCID!=NULL) + { + if (!ECP_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT; + } + else + { + if (!ECP_fromOctet(&U,xID)) res=MPIN_INVALID_POINT; + } + BIG_fromBytes(w,W->val); + BIG_fromBytes(h,H->val); + + + PAIR_ate(&g,&sQ,&A); + PAIR_fexp(&g); + + if (res==0) + { + PAIR_G1mul(&A,h); + ECP_add(&R,&A); // new + PAIR_ate(&g,&sQ,&R); + PAIR_fexp(&g); + PAIR_G1mul(&U,w); + FP12_trace(&c,&g); + mpin_hash(sha,&c,&U,SK); + } + return res; +} + +unsign32 MPIN_GET_TIME(void) +{ + return (unsign32)time(NULL); +} + +/* Generate Y = H(TimeValue, xCID/xID) */ +void MPIN_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y) +{ + BIG q,y; + char h[MODBYTES]; + octet H= {0,sizeof(h),h}; + + hashit(sha,TimeValue,xCID,&H); + BIG_fromBytes(y,H.val); + BIG_rcopy(q,CURVE_Order); + BIG_mod(y,q); + BIG_toBytes(Y->val,y); + Y->len=PGS; +} + +/* One pass MPIN Client */ +int MPIN_CLIENT(int sha,int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y) +{ + int rtn=0; + char m[M_SIZE]; + octet M= {0,sizeof(m),m}; + + octet *pID; + if (date == 0) + pID = U; + else + pID = UT; + + rtn = MPIN_CLIENT_1(sha,date,ID,RNG,X,pin,TOKEN,V,U,UT,TP); + if (rtn != 0) + return rtn; + + OCT_joctet(&M,pID); + if (MESSAGE!=NULL) + { + OCT_joctet(&M,MESSAGE); + } + + MPIN_GET_Y(sha,TimeValue,&M,Y); + + rtn = MPIN_CLIENT_2(X,Y,V); + if (rtn != 0) + return rtn; + + return 0; +} + +/* One pass MPIN Server */ +int MPIN_SERVER(int sha,int date,octet *HID,octet *HTID,octet *Y,octet *sQ,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue) +{ + int rtn=0; + char m[M_SIZE]; + octet M= {0,sizeof(m),m}; + + octet *pU; + if (date == 0) + pU = U; + else + pU = UT; + + MPIN_SERVER_1(sha,date,ID,HID,HTID); + + OCT_joctet(&M,pU); + if (MESSAGE!=NULL) + { + OCT_joctet(&M,MESSAGE); + } + + MPIN_GET_Y(sha,TimeValue,&M,Y); + + rtn = MPIN_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F); + if (rtn != 0) + return rtn; + + return 0; +} + +/* AES-GCM Encryption of octets, K is key, H is header, + P is plaintext, C is ciphertext, T is authentication tag */ +void MPIN_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T) +{ + gcm g; + GCM_init(&g,K->len,K->val,IV->len,IV->val); + GCM_add_header(&g,H->val,H->len); + GCM_add_plain(&g,C->val,P->val,P->len); + C->len=P->len; + GCM_finish(&g,T->val); + T->len=16; +} + +/* AES-GCM Decryption of octets, K is key, H is header, + P is plaintext, C is ciphertext, T is authentication tag */ +void MPIN_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T) +{ + gcm g; + GCM_init(&g,K->len,K->val,IV->len,IV->val); + GCM_add_header(&g,H->val,H->len); + GCM_add_cipher(&g,P->val,C->val,C->len); + P->len=C->len; + GCM_finish(&g,T->val); + T->len=16; +} + +/* Return the Field size */ +int MPIN_FS() +{ + return PFS; +} + +/* Return the Group size */ +int MPIN_GS() +{ + return PGS; +} + +/* +int MPIN_TEST_PAIRING(octet *CID,octet *R) +{ + BIG b,px; + FP2 qx,qy; + FP12 g; + ECP2 Q; + ECP P; + int res=0; + + hashit(-1,CID,&P); + BIG_rcopy(qx.a,CURVE_Pxa); FP_nres(qx.a); + BIG_rcopy(qx.b,CURVE_Pxb); FP_nres(qx.b); + BIG_rcopy(qy.a,CURVE_Pya); FP_nres(qy.a); + BIG_rcopy(qy.b,CURVE_Pyb); FP_nres(qy.b); + + if (!ECP2_set(&Q,&qx,&qy)) res=MPIN_INVALID_POINT; + + if (res==0) + { + PAIR_ate(&g,&Q,&P); + PAIR_fexp(&g); + FP12_trace(&(g.a),&g); + + BIG_copy(b,g.a.a.a); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n"); + BIG_copy(b,g.a.a.b); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n"); + BIG_copy(b,g.a.b.a); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n"); + BIG_copy(b,g.a.b.b); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n"); + + } + + return res; +} +*/ + +/* +int main() +{ + ECP2 X; + FP2 x,y,rhs; + BIG r; + char hcid[HASH_BYTES],client_id[100]; + octet HCID={0,sizeof(hcid),hcid}; + octet CLIENT_ID={0,sizeof(client_id),client_id}; + + OCT_jstring(&CLIENT_ID,"[email protected]"); + MPIN_HASH_ID(&CLIENT_ID,&HCID); + + printf("Client ID= "); OCT_output_string(&CLIENT_ID); printf("\n"); + + mapit2(&HCID,&X); + + ECP2_output(&X); + + BIG_rcopy(r,CURVE_Order); + + ECP2_mul(&X,r); + + ECP2_output(&X); + +} +*/
http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/mpin.h ---------------------------------------------------------------------- diff --git a/version22/c/mpin.h b/version22/c/mpin.h new file mode 100644 index 0000000..9627eb8 --- /dev/null +++ b/version22/c/mpin.h @@ -0,0 +1,408 @@ +/* +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 mpin.h + * @author Mike Scott and Kealan McCusker + * @date 2nd June 2015 + * @brief M-Pin Header file + * + * Allows some user configuration + * defines structures + * declares functions + * + */ + +#ifndef MPIN_H +#define MPIN_H + +#include "amcl.h" + +/* Field size is assumed to be greater than or equal to group size */ + +#define PGS MODBYTES /**< MPIN Group Size */ +#define PFS MODBYTES /**< MPIN Field Size */ +#define PAS 16 /**< MPIN Symmetric Key Size */ + +#define MPIN_OK 0 /**< Function completed without error */ +#define MPIN_INVALID_POINT -14 /**< Point is NOT on the curve */ +#define MPIN_BAD_PIN -19 /**< Bad PIN number entered */ + + +/* Configure your PIN here */ + +#ifdef CMAKE +#define MAXPIN @AMCL_MAXPIN@ /**< max PIN */ +#define PBLEN @AMCL_PBLEN@ /**< max length of PIN in bits */ +#else +#define MAXPIN 10000 /**< max PIN */ +#define PBLEN 14 /**< max length of PIN in bits */ +#endif + +#define TIME_SLOT_MINUTES 1440 /**< Time Slot = 1 day */ +#define HASH_TYPE_MPIN SHA256 /**< Choose Hash function */ + +#define MESSAGE_SIZE 256 /**< Signature message size */ +#define M_SIZE (MESSAGE_SIZE+2*PFS+1) /**< Signature message size and G1 size */ + +/* MPIN support functions */ + +/* MPIN primitives */ + +/** @brief Hash an M-Pin Identity to an octet string + * + @param h is the hash type + @param ID an octet containing the identity + @param HID an octet containing the hashed identity + */ +void MPIN_HASH_ID(int h,octet *ID,octet *HID); +/** @brief Get epoch time as unsigned integer + * + @return current epoch time in seconds + */ +unsign32 MPIN_GET_TIME(void); +/** @brief Generate Y=H(s,O), where s is epoch time, O is an octet, and H(.) is a hash function + * + @param h is the hash type + @param t is epoch time in seconds + @param O is an input octet + @param Y is the output octet + */ +void MPIN_GET_Y(int h,int t,octet *O,octet *Y); +/** @brief Extract a PIN number from a client secret + * + @param h is the hash type + @param ID is the input client identity + @param pin is an input PIN number + @param CS is the client secret from which the PIN is to be extracted + @return 0 or an error code + */ +int MPIN_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS); +/** @brief Perform client side of the one-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated. + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param ID is the input client identity + @param R is a pointer to a cryptographically secure random number generator + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param pin is the input PIN number + @param T is the input M-Pin token (the client secret with PIN portion removed) + @param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit + @param U is output = x.H(ID) + @param UT is output = x.(H(ID)+H(d|H(ID))) + @param TP is the input time permit + @param MESSAGE is the message to be signed + @param t is input epoch time in seconds - a timestamp + @param y is output H(t|U) or H(t|UT) if Time Permits enabled + @return 0 or an error code + */ +int MPIN_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y); +/** @brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated. + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param ID is the input client identity + @param R is a pointer to a cryptographically secure random number generator + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param pin is the input PIN number + @param T is the input M-Pin token (the client secret with PIN portion removed) + @param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit + @param U is output = x.H(ID) + @param UT is output = x.(H(ID)+H(d|H(ID))) + @param TP is the input time permit + @return 0 or an error code + */ +int MPIN_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP); +/** @brief Generate a random group element + * + @param R is a pointer to a cryptographically secure random number generator + @param S is the output random octet + @return 0 or an error code + */ +int MPIN_RANDOM_GENERATE(csprng *R,octet *S); +/** @brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol + * + @param x an input, a locally generated random number + @param y an input random challenge from the server + @param V on output = -(x+y).V + @return 0 or an error code + */ +int MPIN_CLIENT_2(octet *x,octet *y,octet *V); +/** @brief Perform server side of the one-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required. + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param HID is output H(ID), a hash of the client ID + @param HTID is output H(ID)+H(d|H(ID)) + @param y is output H(t|U) or H(t|UT) if Time Permits enabled + @param SS is the input server secret + @param U is input from the client = x.H(ID) + @param UT is input from the client= x.(H(ID)+H(d|H(ID))) + @param V is an input from the client + @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param ID is the input claimed client identity + @param MESSAGE is the message to be signed + @param t is input epoch time in seconds - a timestamp + @return 0 or an error code + */ +int MPIN_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t); +/** @brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol + * + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param ID is the input claimed client identity + @param HID is output H(ID), a hash of the client ID + @param HTID is output H(ID)+H(d|H(ID)) + @return 0 or an error code + */ +void MPIN_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID); +/** @brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required. + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param HID is input H(ID), a hash of the client ID + @param HTID is input H(ID)+H(d|H(ID)) + @param y is the input server's randomly generated challenge + @param SS is the input server secret + @param U is input from the client = x.H(ID) + @param UT is input from the client= x.(H(ID)+H(d|H(ID))) + @param V is an input from the client + @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required + @return 0 or an error code + */ +int MPIN_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F); +/** @brief Add two members from the group G1 + * + @param Q1 an input member of G1 + @param Q2 an input member of G1 + @param Q an output member of G1 = Q1+Q2 + @return 0 or an error code + */ +int MPIN_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q); +/** @brief Add two members from the group G2 + * + @param P1 an input member of G2 + @param P2 an input member of G2 + @param P an output member of G2 = P1+P2 + @return 0 or an error code + */ +int MPIN_RECOMBINE_G2(octet *P1,octet *P2,octet *P); +/** @brief Use Kangaroos to find PIN error + * + @param E a member of the group GT + @param F a member of the group GT = E^e + @return 0 if Kangaroos failed, or the PIN error e + */ +int MPIN_KANGAROO(octet *E,octet *F); +/** @brief Encoding of a Time Permit to make it indistinguishable from a random string + * + @param R is a pointer to a cryptographically secure random number generator + @param TP is the input time permit, obfuscated on output + @return 0 or an error code + */ +int MPIN_ENCODING(csprng *R,octet *TP); +/** @brief Encoding of an obfuscated Time Permit + * + @param TP is the input obfuscated time permit, restored on output + @return 0 or an error code + */ +int MPIN_DECODING(octet *TP); +/** @brief Supply today's date as days from the epoch + * + @return today's date, as number of days elapsed since the epoch + */ +unsign32 MPIN_today(void); + +/** @brief Find a random multiple of a point in G1 + * + @param R is a pointer to a cryptographically secure random number generator + @param type determines type of action to be taken + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param G if type=0 a point in G1, else an octet to be mapped to G1 + @param W the output =x.G or x.M(G), where M(.) is a mapping + @return 0 or an error code + */ +int MPIN_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W); +/** @brief Find a random multiple of a point in G1 + * + @param R is a pointer to a cryptographically secure random number generator + @param type determines type of action to betaken + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param G a point in G2 + @param W the output =x.G or (1/x).G + @return 0 or an error code + */ +int MPIN_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W); +/** @brief Hash the session transcript + @param h is the hash type + @param I is the hashed input client ID = H(ID) + @param U is the client output = x.H(ID) + @param CU is the client output = x.(H(ID)+H(T|H(ID))) + @param Y is the server challenge + @param V is the client part response + @param R is the client part response + @param W is the server part response + @param H the output is the hash of all of the above that apply +*/ +void MPIN_HASH_ALL(int h,octet *I,octet *U,octet *CU,octet *Y,octet *V,octet *R,octet *W,octet *H); +/** @brief Create a client secret in G1 from a master secret and the client ID + * + @param S is an input master secret + @param ID is the input client identity + @param CS is the full client secret = s.H(ID) + @return 0 or an error code + */ +int MPIN_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS); +/** @brief Create a Time Permit in G1 from a master secret and the client ID + * + @param h is the hash type + @param d is input date, in days since the epoch. + @param S is an input master secret + @param ID is the input client identity + @param TP is a Time Permit for the given date = s.H(d|H(ID)) + @return 0 or an error code + */ +int MPIN_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP); +/** @brief Create a server secret in G2 from a master secret + * + @param S is an input master secret + @param SS is the server secret = s.Q where Q is a fixed generator of G2 + @return 0 or an error code + */ +int MPIN_GET_SERVER_SECRET(octet *S,octet *SS); +/* int MPIN_TEST_PAIRING(octet *,octet *); */ + +/* For M-Pin Full */ +/** @brief Precompute values for use by the client side of M-Pin Full + * + @param T is the input M-Pin token (the client secret with PIN portion removed) + @param ID is the input client identity + @param CP is Public Key (or NULL) + @param g1 precomputed output + @param g2 precomputed output + @return 0 or an error code + */ +int MPIN_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2); +/** @brief Calculate Key on Server side for M-Pin Full + * + Uses UT internally for the key calculation, unless not available in which case U is used + @param h is the hash type + @param Z is the input Client-side Diffie-Hellman component + @param SS is the input server secret + @param w is an input random number generated by the server + @param p is an input, hash of the protocol transcript + @param I is the hashed input client ID = H(ID) + @param U is input from the client = x.H(ID) + @param UT is input from the client= x.(H(ID)+H(d|H(ID))) + @param K is the output calculated shared key + @return 0 or an error code + */ +int MPIN_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K); +/** @brief Calculate Key on Client side for M-Pin Full + * + @param h is the hash type + @param g1 precomputed input + @param g2 precomputed input + @param pin is the input PIN number + @param r is an input, a locally generated random number + @param x is an input, a locally generated random number + @param p is an input, hash of the protocol transcript + @param T is the input Server-side Diffie-Hellman component + @param K is the output calculated shared key + @return 0 or an error code + */ +int MPIN_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K); + +/** @brief AES-GCM Encryption + * + @param K AES key + @param IV Initialization vector + @param H Header + @param P Plaintext + @param C Ciphertext + @param T Checksum + */ +void MPIN_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T); + +/** @brief AES-GCM Decryption + * + @param K AES key + @param IV Initialization vector + @param H Header + @param P Plaintext + @param C Ciphertext + @param T Checksum + */ +void MPIN_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T); + +/** + * @brief Return the field size + * + * Return the field size. + * + * @return Field size + */ +int MPIN_FS(); + +/** + * @brief Return the group size + * + * Return the group size. + * + * @return Group size + */ +int MPIN_GS(); + +/** @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 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 + */ +//int HMAC(octet *M,octet *K,int len,octet *tag); + +/** @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 P input password + @param S input salt + @param rep Number of times to be iterated. + @param len is output desired length of key + @param K is the derived key + */ +//void PBKDF2(octet *P,octet *S,int rep,int len,octet *K); + +#endif + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/oct.c ---------------------------------------------------------------------- diff --git a/version22/c/oct.c b/version22/c/oct.c new file mode 100644 index 0000000..8d5bdb2 --- /dev/null +++ b/version22/c/oct.c @@ -0,0 +1,428 @@ +/* +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. +*/ + +/*** Basic Octet string maintainance routines ***/ +/* SU=m, m is Stack Usage */ + +#include <string.h> +#include "amcl.h" + +/* Output an octet string (Debug Only) */ + +/* SU= 16 */ +/* output octet */ +void OCT_output(octet *w) +{ + int i; + unsigned char ch; + for (i=0; i<w->len; i++) + { + ch=w->val[i]; + printf("%02x",ch); + } + printf("\n"); +} + +/* SU= 16 */ +void OCT_output_string(octet *w) +{ + int i; + unsigned char ch; + for (i=0; i<w->len; i++) + { + ch=w->val[i]; + printf("%c",ch); + } + /* printf("\n"); */ +} + +/* Convert C string to octet format - truncates if no room */ +void OCT_jstring(octet *y,char *s) +{ + int i,j; + i=y->len; + j=0; + while (s[j]!=0 && i<y->max) + { + y->val[i]=s[j]; + y->len++; + i++; + j++; + } +} + +/* compare 2 octet strings. + * If x==y return TRUE, else return FALSE */ +/* SU= 8 */ +int OCT_comp(octet *x,octet *y) +{ + int i; + if (x->len>y->len) return 0; + if (x->len<y->len) return 0; + for (i=0; i<x->len; i++) + { + if (x->val[i]!=y->val[i]) return 0; + } + return 1; +} + +/* check are first n bytes the same */ + +int OCT_ncomp(octet *x,octet *y,int n) +{ + int i; + if (n>y->len || n>x->len) return 0; + for (i=0; i<n; i++) + { + if (x->val[i]!=y->val[i]) return 0; + } + return 1; +} + +/* Shift octet to the left by n bytes. Leftmost bytes disappear */ +void OCT_shl(octet *x,int n) +{ + int i; + if (n>=x->len) + { + x->len=0; + return; + } + x->len-=n; + for (i=0; i<x->len; i++) + x->val[i]=x->val[i+n]; +} + +/* Append binary string to octet - truncates if no room */ +/* SU= 12 */ +void OCT_jbytes(octet *y,char *b,int len) +{ + int i,j; + i=y->len; + for (j=0; j<len && i<y->max; j++) + { + y->val[i]=b[j]; + y->len++; + i++; + } +} + +/* Concatenates two octet strings */ +/* SU= 8 */ +void OCT_joctet(octet *y,octet *x) +{ + /* y=y || x */ + int i,j; + if (x==NULL) return; + + for (i=0; i<x->len; 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 */ +/* SU= 8 */ +void OCT_jbyte(octet *y,int ch,int rep) +{ + int i,j; + i=y->len; + for (j=0; j<rep && i<y->max; j++) + { + y->val[i]=ch; + y->len++; + i++; + } +} + +/* XOR common bytes of x with y */ +/* SU= 8 */ +void OCT_xor(octet *y,octet *x) +{ + /* xor first x->len bytes of y */ + + int i; + for (i=0; i<x->len && i<y->len; i++) + { + y->val[i]^=x->val[i]; + } +} + +/* clear an octet */ +void OCT_empty(octet *w) +{ + w->len=0; +} + +/* Kill an octet string - Zeroise it for security */ +void OCT_clear(octet *w) +{ + int i; + for (i=0; i<w->max; i++) w->val[i]=0; + w->len=0; +} + +/* appends int x of length len bytes to OCTET string */ +/* SU= 8 */ +void OCT_jint(octet *y,int x,int len) +{ + int i,n; + n=y->len+len; + if (n>y->max || len<=0) return; + for (i=y->len; i<n; i++) y->val[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 */ +/* SU= 8 */ +int OCT_pad(octet *w,int n) +{ + int i,d; + if (w->len>n || n>w->max) return 0; + if (n==w->len) return 1; + 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; + return 1; +} + + +/* Convert an octet string to base64 string */ +/* SU= 56 */ +void OCT_tobase64(char *b,octet *w) +{ + int i,j,k,rem,last; + int c,ch[4]; + unsigned char ptr[3]; + rem=w->len%3; + j=k=0; + last=4; + while (j<w->len) + { + for (i=0; i<3; i++) + { + if (j<w->len) 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<last; i++) + { + c=ch[i]; + if (c<26) c+=65; + if (c>=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! */ +} + +/* SU= 56 */ +void OCT_frombase64(octet *w,char *b) +{ + int i,j,k,pads,len=(int)strlen(b); + int c,ch[4],ptr[3]; + /* int lead=1; */ + j=k=0; + while (j<len && k<w->max) + { + 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++; /* ignore pads '=' */ + continue; + } + 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 && k<w->max; 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 */ +/* SU= 16 */ +void OCT_copy(octet *y,octet *x) +{ + int i; + OCT_clear(y); + y->len=x->len; + if (y->len>y->max) y->len=y->max; + + for (i=0; i<y->len; i++) + y->val[i]=x->val[i]; +} + +/* XOR m with all of x */ +void OCT_xorbyte(octet *x,int m) +{ + int i; + for (i=0; i<x->len; i++) x->val[i]^=m; +} + +/* truncates x to n bytes and places the rest in y (if y is not NULL) */ +/* SU= 8 */ +void OCT_chop(octet *x,octet *y,int n) +{ + 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; i<y->len && i<y->max; i++) y->val[i]=x->val[i+n]; + } +} + +/* set x to len random bytes */ +void OCT_rand(octet *x,csprng *RNG,int len) +{ + int i; + if (len>x->max) len=x->max; + x->len=len; + + for (i=0; i<len; i++) x->val[i]=RAND_byte(RNG); +} + +/* Convert an octet to a hex string */ +void OCT_toHex(octet *src,char *dst) +{ + int i; + unsigned char ch; + for (i=0; i<src->len; i++) + { + ch=src->val[i]; + sprintf(&dst[i*2],"%02x", ch); + } +} + +static int char2int(char input) +{ + if(input >= '0' && input <= '9') + return input - '0'; + if(input >= 'A' && input <= 'F') + return input - 'A' + 10; + if(input >= 'a' && input <= 'f') + return input - 'a' + 10; + return 0; +} + +/* Convert from a hex string */ +void OCT_fromHex(octet *dst,char *src) +{ + int i=0; + int j=0; + OCT_clear(dst); + + while(src[j]!=0) + { + dst->val[i++] = char2int(src[j])*16 + char2int(src[j+1]); + j += 2; + } + dst->len=i; +} + + +/* Convert an octet to a string */ +void OCT_toStr(octet *src,char *dst) +{ + int i; + unsigned char ch; + for (i=0; i<src->len; i++) + { + ch=src->val[i]; + sprintf(&dst[i],"%c", ch); + } +} + +/* Test program +#include <stdio.h> +#include "amcl.h" + +char test[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + +int main() +{ + char gm[100],gn[100],t[100]; + octet m={0,sizeof(gm),gm}; + octet n={0,sizeof(gn),gn}; + + OCT_jbytes(&m,test,strlen(test)); + OCT_output(&m); + + OCT_tobase64(t,&m); + printf(t); printf("\n"); + + OCT_frombase64(&n,t); + OCT_output(&n); + + return 0; +} +*/ http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/pair.c ---------------------------------------------------------------------- diff --git a/version22/c/pair.c b/version22/c/pair.c new file mode 100644 index 0000000..5b4e987 --- /dev/null +++ b/version22/c/pair.c @@ -0,0 +1,828 @@ +/* +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 BN Curve pairing functions */ + +//#define HAS_MAIN + +#include "amcl.h" + +/* Line function */ +static void PAIR_line(FP12 *v,ECP2 *A,ECP2 *B,BIG Qx,BIG Qy) +{ + ECP2 P; + FP2 Z3,X,Y,ZZ,T,NY; + FP4 a,b,c; + int D; + ECP2_copy(&P,A); + if (A==B) + D=ECP2_dbl(A); // check these return numbers... + else + D=ECP2_add(A,B); + if (D<0) + { + /* Infinity */ + FP12_one(v); + return; + } + + FP2_copy(&Z3,&(A->z)); + FP4_zero(&c); + FP2_sqr(&ZZ,&(P.z)); /* ZZ=Z^2 */ + if (D==0) + { + /* addition */ + ECP2_get(&X,&Y,B); + FP2_mul(&T,&(P.z),&Y); /* T=Z*Y2 */ + + FP2_mul(&ZZ,&ZZ,&T); + + FP2_neg(&NY,&(P.y)); + FP2_add(&ZZ,&ZZ,&NY); /* ZZ=Z^3*Y2-Y (slope numerator) */ + FP2_pmul(&Z3,&Z3,Qy); /* Z3*Qy */ + FP2_mul(&T,&T,&(P.x)); + FP2_mul(&X,&X,&NY); + FP2_add(&T,&T,&X); /* Z*Y2*X-X2*Y */ + FP4_from_FP2s(&a,&Z3,&T); /* a=[Z3*Qy,Z*Y2*X-X2*Y] */ + FP2_neg(&ZZ,&ZZ); + FP2_pmul(&ZZ,&ZZ,Qx); + FP4_from_FP2(&b,&ZZ); /* b=-slope*Qx */ + } + else + { + /* doubling */ + FP2_sqr(&T,&(P.x)); + FP2_imul(&T,&T,3); /* T=3X^2 (slope numerator) */ + FP2_sqr(&Y,&(P.y)); + + FP2_add(&Y,&Y,&Y); /* Y=2Y^2 */ + FP2_mul(&Z3,&Z3,&ZZ); /* Z3=Z3*ZZ */ + FP2_pmul(&Z3,&Z3,Qy); /* Z3=Z3*ZZ*Qy */ + + FP2_mul(&X,&(P.x),&T); + FP2_sub(&X,&X,&Y); /* X=X*slope-2Y^2 */ + FP4_from_FP2s(&a,&Z3,&X); /* a=[Z3*ZZ*Qy , X*slope-2Y^2] */ + FP2_neg(&T,&T); + FP2_mul(&ZZ,&ZZ,&T); + FP2_pmul(&ZZ,&ZZ,Qx); + FP4_from_FP2(&b,&ZZ); /* b=-slope*ZZ*Qx */ + } + + FP12_from_FP4s(v,&a,&b,&c); +} + +/* Optimal R-ate pairing r=e(P,Q) */ +void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q) +{ + FP2 X; + BIG x,n,Qx,Qy; + int i,nb; + ECP2 A; + FP12 lv; +#if CHOICE<BLS_CURVES + ECP2 KA; +#endif + + BIG_rcopy(Qx,CURVE_Fra); + BIG_rcopy(Qy,CURVE_Frb); + FP2_from_BIGs(&X,Qx,Qy); + + BIG_rcopy(x,CURVE_Bnx); + +#if CHOICE<BLS_CURVES + BIG_pmul(n,x,6); + BIG_dec(n,2); +#else + BIG_copy(n,x); +#endif + + BIG_norm(n); + + ECP2_affine(P); + ECP_affine(Q); + + BIG_copy(Qx,Q->x); + BIG_copy(Qy,Q->y); + + ECP2_copy(&A,P); + FP12_one(r); + nb=BIG_nbits(n); + + /* Main Miller Loop */ + for (i=nb-2; i>=1; i--) + { + PAIR_line(&lv,&A,&A,Qx,Qy); + FP12_smul(r,&lv); + if (BIG_bit(n,i)) + { + + PAIR_line(&lv,&A,P,Qx,Qy); + FP12_smul(r,&lv); + } + FP12_sqr(r,r); + } + + PAIR_line(&lv,&A,&A,Qx,Qy); + FP12_smul(r,&lv); + + if (BIG_parity(n)) + { + PAIR_line(&lv,&A,P,Qx,Qy); + FP12_smul(r,&lv); + } + + /* R-ate fixup required for BN curves */ +#if CHOICE<BLS_CURVES + ECP2_copy(&KA,P); + ECP2_frob(&KA,&X); + + ECP2_neg(&A); + FP12_conj(r,r); + + PAIR_line(&lv,&A,&KA,Qx,Qy); + FP12_smul(r,&lv); + ECP2_frob(&KA,&X); + ECP2_neg(&KA); + PAIR_line(&lv,&A,&KA,Qx,Qy); + FP12_smul(r,&lv); +#endif +} + +/* Optimal R-ate double pairing e(P,Q).e(R,S) */ +void PAIR_double_ate(FP12 *r,ECP2 *P,ECP *Q,ECP2 *R,ECP *S) +{ + FP2 X; + BIG x,n,Qx,Qy,Sx,Sy; + int i,nb; + ECP2 A,B; + FP12 lv; +#if CHOICE<BLS_CURVES + ECP2 K; +#endif + BIG_rcopy(Qx,CURVE_Fra); + BIG_rcopy(Qy,CURVE_Frb); + FP2_from_BIGs(&X,Qx,Qy); + + BIG_rcopy(x,CURVE_Bnx); + +#if CHOICE<BLS_CURVES + BIG_pmul(n,x,6); + BIG_dec(n,2); +#else + BIG_copy(n,x); +#endif + + BIG_norm(n); + + ECP2_affine(P); + ECP_affine(Q); + + ECP2_affine(R); + ECP_affine(S); + + BIG_copy(Qx,Q->x); + BIG_copy(Qy,Q->y); + + BIG_copy(Sx,S->x); + BIG_copy(Sy,S->y); + + ECP2_copy(&A,P); + ECP2_copy(&B,R); + FP12_one(r); + nb=BIG_nbits(n); + + /* Main Miller Loop */ + for (i=nb-2; i>=1; i--) + { + PAIR_line(&lv,&A,&A,Qx,Qy); + FP12_smul(r,&lv); + PAIR_line(&lv,&B,&B,Sx,Sy); + FP12_smul(r,&lv); + + if (BIG_bit(n,i)) + { + PAIR_line(&lv,&A,P,Qx,Qy); + FP12_smul(r,&lv); + + PAIR_line(&lv,&B,R,Sx,Sy); + FP12_smul(r,&lv); + } + FP12_sqr(r,r); + } + + PAIR_line(&lv,&A,&A,Qx,Qy); + FP12_smul(r,&lv); + + PAIR_line(&lv,&B,&B,Sx,Sy); + FP12_smul(r,&lv); + + if (BIG_parity(n)) + { + PAIR_line(&lv,&A,P,Qx,Qy); + FP12_smul(r,&lv); + + PAIR_line(&lv,&B,R,Sx,Sy); + FP12_smul(r,&lv); + } + + /* R-ate fixup required for BN curves */ +#if CHOICE<BLS_CURVES + FP12_conj(r,r); + + ECP2_copy(&K,P); + ECP2_frob(&K,&X); + ECP2_neg(&A); + PAIR_line(&lv,&A,&K,Qx,Qy); + FP12_smul(r,&lv); + ECP2_frob(&K,&X); + ECP2_neg(&K); + PAIR_line(&lv,&A,&K,Qx,Qy); + FP12_smul(r,&lv); + + ECP2_copy(&K,R); + ECP2_frob(&K,&X); + ECP2_neg(&B); + PAIR_line(&lv,&B,&K,Sx,Sy); + FP12_smul(r,&lv); + ECP2_frob(&K,&X); + ECP2_neg(&K); + PAIR_line(&lv,&B,&K,Sx,Sy); + FP12_smul(r,&lv); +#endif +} + +/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ +void PAIR_fexp(FP12 *r) +{ + FP2 X; + BIG x,a,b; + FP12 t0,y0,y1,y2,y3; + + BIG_rcopy(x,CURVE_Bnx); + BIG_rcopy(a,CURVE_Fra); + BIG_rcopy(b,CURVE_Frb); + FP2_from_BIGs(&X,a,b); + + /* Easy part of final exp */ + + FP12_inv(&t0,r); + FP12_conj(r,r); + + FP12_mul(r,&t0); + FP12_copy(&t0,r); + + FP12_frob(r,&X); + FP12_frob(r,&X); + FP12_mul(r,&t0); + + /* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */ +#if CHOICE<BLS_CURVES + FP12_pow(&t0,r,x); // t0=f^-u + FP12_usqr(&y3,&t0); // y3=t0^2 + FP12_copy(&y0,&t0); + FP12_mul(&y0,&y3); // y0=t0*y3 + FP12_copy(&y2,&y3); + FP12_frob(&y2,&X); // y2=y3^p + FP12_mul(&y2,&y3); //y2=y2*y3 + FP12_usqr(&y2,&y2); //y2=y2^2 + FP12_mul(&y2,&y3); // y2=y2*y3 + + FP12_pow(&t0,&y0,x); //t0=y0^-u + FP12_conj(&y0,r); //y0=~r + FP12_copy(&y1,&t0); + FP12_frob(&y1,&X); + FP12_frob(&y1,&X); //y1=t0^p^2 + FP12_mul(&y1,&y0); // y1=y0*y1 + FP12_conj(&t0,&t0); // t0=~t0 + FP12_copy(&y3,&t0); + FP12_frob(&y3,&X); //y3=t0^p + FP12_mul(&y3,&t0); // y3=t0*y3 + FP12_usqr(&t0,&t0); // t0=t0^2 + FP12_mul(&y1,&t0); // y1=t0*y1 + + FP12_pow(&t0,&y3,x); // t0=y3^-u + FP12_usqr(&t0,&t0); //t0=t0^2 + FP12_conj(&t0,&t0); //t0=~t0 + FP12_mul(&y3,&t0); // y3=t0*y3 + + FP12_frob(r,&X); + FP12_copy(&y0,r); + FP12_frob(r,&X); + FP12_mul(&y0,r); + FP12_frob(r,&X); + FP12_mul(&y0,r); + + FP12_usqr(r,&y3); //r=y3^2 + FP12_mul(r,&y2); //r=y2*r + FP12_copy(&y3,r); + FP12_mul(&y3,&y0); // y3=r*y0 + FP12_mul(r,&y1); // r=r*y1 + FP12_usqr(r,r); // r=r^2 + FP12_mul(r,&y3); // r=r*y3 + FP12_reduce(r); +#else +// Ghamman & Fouotsa Method + + FP12_usqr(&y0,r); + FP12_pow(&y1,&y0,x); + BIG_fshr(x,1); + FP12_pow(&y2,&y1,x); + BIG_fshl(x,1); // x must be even + FP12_conj(&y3,r); + FP12_mul(&y1,&y3); + + FP12_conj(&y1,&y1); + FP12_mul(&y1,&y2); + + FP12_pow(&y2,&y1,x); + + FP12_pow(&y3,&y2,x); + FP12_conj(&y1,&y1); + FP12_mul(&y3,&y1); + + FP12_conj(&y1,&y1); + FP12_frob(&y1,&X); + FP12_frob(&y1,&X); + FP12_frob(&y1,&X); + FP12_frob(&y2,&X); + FP12_frob(&y2,&X); + FP12_mul(&y1,&y2); + + FP12_pow(&y2,&y3,x); + FP12_mul(&y2,&y0); + FP12_mul(&y2,r); + + FP12_mul(&y1,&y2); + FP12_copy(&y2,&y3); + FP12_frob(&y2,&X); + FP12_mul(&y1,&y2); + FP12_copy(r,&y1); + FP12_reduce(r); + +// Aranha et al method as described by Ghamman & Fouotsa + /* + FP12_usqr(&y0,r); // t0=f^2 + FP12_conj(&y3,&y0); // t0=f^-2 + FP12_pow(&t0,r,x); // t5=f^u + FP12_usqr(&y1,&t0); // t1=t5^2 + FP12_mul(&y3,&t0); // t3=t0*t5 + + FP12_pow(&y0,&y3,x); + + FP12_pow(&y2,&y0,x); + + FP12_pow(&y4,&y2,x); + + FP12_mul(&y4,&y1); + FP12_pow(&y1,&y4,x); + FP12_conj(&y3,&y3); + FP12_mul(&y1,&y3); + FP12_mul(&y1,r); + + FP12_conj(&y3,r); + FP12_mul(&y0,r); + FP12_frob(&y0,&X); FP12_frob(&y0,&X); FP12_frob(&y0,&X); + + FP12_mul(&y4,&y3); + FP12_frob(&y4,&X); + + FP12_mul(&t0,&y2); + FP12_frob(&t0,&X); FP12_frob(&t0,&X); + + FP12_mul(&t0,&y0); + FP12_mul(&t0,&y4); + FP12_mul(&t0,&y1); + FP12_copy(r,&t0); + FP12_reduce(r);*/ + +//----------------------------------- + /* + FP12_copy(&y0,r); // y0=r; + FP12_copy(&y1,r); // y1=r; + FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); + FP12_conj(&y3,&t0); FP12_mul(&y1,&y3); // y1*=inverse(t0); + FP12_frob(&t0,&X); FP12_frob(&t0,&X); // t0=Frobenius(t0,X,2); + FP12_mul(&y1,&t0); // y1*=t0; + + FP12_pow(r,r,x); // r=pow(r,x); + FP12_conj(&y3,r); FP12_mul(&y1,&y3); // y1*=inverse(r); + FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); + FP12_mul(&y0,&t0); // y0*=t0; + FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); + FP12_mul(&y1,&t0); // y1*=t0; + FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); + FP12_conj(&y3,&t0); FP12_mul(&y0,&y3); // y0*=inverse(t0); + + FP12_pow(r,r,x); // r=pow(r,x); + FP12_mul(&y0,r); // y0*=r; + FP12_copy(&t0,r); FP12_frob(&t0,&X); FP12_frob(&t0,&X); // t0=Frobenius(r,X,2); + FP12_conj(&y3,&t0); FP12_mul(&y0,&y3); // y0*=inverse(t0); + FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); + FP12_mul(&y1,&t0); // y1*=t0; + + FP12_pow(r,r,x); // r=pow(r,x); // r^x3 + FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); + FP12_conj(&y3,&t0); FP12_mul(&y0,&y3); // y0*=inverse(t0); + FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); + FP12_mul(&y1,&t0); // y1*=t0; + + FP12_pow(r,r,x); // r=pow(r,x); // r^x4 + FP12_conj(&y3,r); FP12_mul(&y0,&y3); // y0*=inverse(r); + FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); + FP12_mul(&y1,&t0); //y1*=t0; + + FP12_pow(r,r,x); // r=pow(r,x); // r^x5 + FP12_mul(&y1,r); // y1*=r; + + FP12_usqr(&y0,&y0); // r=y0*y0*y1; + FP12_mul(&y0,&y1); + FP12_copy(r,&y0); + FP12_reduce(r); */ +#endif +} + +#ifdef USE_GLV +/* GLV method */ +static void glv(BIG u[2],BIG e) +{ +#if CHOICE<BLS_CURVES + int i,j; + BIG v[2],t,q; + DBIG d; + BIG_rcopy(q,CURVE_Order); + for (i=0; i<2; i++) + { + BIG_rcopy(t,CURVE_W[i]); +//BIG_norm(t); BIG_norm(e); + BIG_mul(d,t,e); + BIG_ddiv(v[i],d,q); + BIG_zero(u[i]); + } + BIG_copy(u[0],e); + for (i=0; i<2; i++) + for (j=0; j<2; j++) + { + BIG_rcopy(t,CURVE_SB[j][i]); + BIG_modmul(t,v[j],t,q); + BIG_add(u[i],u[i],q); + BIG_sub(u[i],u[i],t); + BIG_mod(u[i],q); + } + +#else +// -(x^2).P = (Beta.x,y) + + BIG x,x2,q; + BIG_rcopy(x,CURVE_Bnx); + BIG_smul(x2,x,x); + BIG_copy(u[0],e); + BIG_mod(u[0],x2); + BIG_copy(u[1],e); + BIG_sdiv(u[1],x2); + + BIG_rcopy(q,CURVE_Order); + BIG_sub(u[1],q,u[1]); + +#endif + + return; +} +#endif // USE_GLV + +/* Galbraith & Scott Method */ +static void gs(BIG u[4],BIG e) +{ + int i; +#if CHOICE<BLS_CURVES + int j; + BIG v[4],t,q; + DBIG d; + BIG_rcopy(q,CURVE_Order); + for (i=0; i<4; i++) + { + BIG_rcopy(t,CURVE_WB[i]); +//BIG_norm(t); BIG_norm(e); + BIG_mul(d,t,e); + BIG_ddiv(v[i],d,q); + BIG_zero(u[i]); + } + + BIG_copy(u[0],e); + for (i=0; i<4; i++) + for (j=0; j<4; j++) + { + BIG_rcopy(t,CURVE_BB[j][i]); + BIG_modmul(t,v[j],t,q); + BIG_add(u[i],u[i],q); + BIG_sub(u[i],u[i],t); + BIG_mod(u[i],q); + } + +#else + + BIG x,w; + BIG_rcopy(x,CURVE_Bnx); + BIG_copy(w,e); + + for (i=0; i<4; i++) + { + BIG_copy(u[i],w); + BIG_mod(u[i],x); + BIG_sdiv(w,x); + } + +#endif + return; +} + +/* Multiply P by e in group G1 */ +void PAIR_G1mul(ECP *P,BIG e) +{ +#ifdef USE_GLV /* Note this method is patented */ + int np,nn; + ECP Q; + BIG cru,t,q; + BIG u[2]; + + BIG_rcopy(q,CURVE_Order); + glv(u,e); + + ECP_affine(P); + ECP_copy(&Q,P); + BIG_rcopy(cru,CURVE_Cru); + FP_nres(cru); + FP_mul(Q.x,Q.x,cru); + + /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */ + + np=BIG_nbits(u[0]); + BIG_modneg(t,u[0],q); + nn=BIG_nbits(t); + if (nn<np) + { + BIG_copy(u[0],t); + ECP_neg(P); + } + + np=BIG_nbits(u[1]); + BIG_modneg(t,u[1],q); + nn=BIG_nbits(t); + if (nn<np) + { + BIG_copy(u[1],t); + ECP_neg(&Q); + } + + ECP_mul2(P,&Q,u[0],u[1]); + +#else + ECP_mul(P,e); +#endif +} + +/* Multiply P by e in group G2 */ +void PAIR_G2mul(ECP2 *P,BIG e) +{ +#ifdef USE_GS_G2 /* Well I didn't patent it :) */ + int i,np,nn; + ECP2 Q[4]; + FP2 X; + BIG x,y; + BIG u[4]; + + BIG_rcopy(x,CURVE_Fra); + BIG_rcopy(y,CURVE_Frb); + FP2_from_BIGs(&X,x,y); + + BIG_rcopy(y,CURVE_Order); + gs(u,e); + + + ECP2_affine(P); + + ECP2_copy(&Q[0],P); + for (i=1; i<4; i++) + { + ECP2_copy(&Q[i],&Q[i-1]); + ECP2_frob(&Q[i],&X); + } + + for (i=0; i<4; i++) + { + np=BIG_nbits(u[i]); + BIG_modneg(x,u[i],y); + nn=BIG_nbits(x); + if (nn<np) + { + BIG_copy(u[i],x); + ECP2_neg(&Q[i]); + } + } + + ECP2_mul4(P,Q,u); + +#else + ECP2_mul(P,e); +#endif +} + +/* f=f^e */ +void PAIR_GTpow(FP12 *f,BIG e) +{ +#ifdef USE_GS_GT /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see fp4.c */ + int i,np,nn; + FP12 g[4]; + FP2 X; + BIG t,q,x,y; + BIG u[4]; + + BIG_rcopy(x,CURVE_Fra); + BIG_rcopy(y,CURVE_Frb); + FP2_from_BIGs(&X,x,y); + + BIG_rcopy(q,CURVE_Order); + gs(u,e); + + FP12_copy(&g[0],f); + for (i=1; i<4; i++) + { + FP12_copy(&g[i],&g[i-1]); + FP12_frob(&g[i],&X); + } + + for (i=0; i<4; i++) + { + np=BIG_nbits(u[i]); + BIG_modneg(t,u[i],q); + nn=BIG_nbits(t); + if (nn<np) + { + BIG_copy(u[i],t); + FP12_conj(&g[i],&g[i]); + } + } + FP12_pow4(f,g,u); + +#else + FP12_pow(f,f,e); +#endif +} + +/* test group membership test - no longer needed */ +/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */ + +/* +int PAIR_GTmember(FP12 *m) +{ + BIG a,b; + FP2 X; + FP12 r,w; + if (FP12_isunity(m)) return 0; + FP12_conj(&r,m); + FP12_mul(&r,m); + if (!FP12_isunity(&r)) return 0; + + BIG_rcopy(a,CURVE_Fra); + BIG_rcopy(b,CURVE_Frb); + FP2_from_BIGs(&X,a,b); + + + FP12_copy(&r,m); FP12_frob(&r,&X); FP12_frob(&r,&X); + FP12_copy(&w,&r); FP12_frob(&w,&X); FP12_frob(&w,&X); + FP12_mul(&w,m); + + +#ifndef GT_STRONG + if (!FP12_equals(&w,&r)) return 0; + + BIG_rcopy(a,CURVE_Bnx); + + FP12_copy(&r,m); FP12_pow(&w,&r,a); FP12_pow(&w,&w,a); + FP12_sqr(&r,&w); FP12_mul(&r,&w); FP12_sqr(&r,&r); + + FP12_copy(&w,m); FP12_frob(&w,&X); + #endif + + return FP12_equals(&w,&r); +} + +*/ + + +#ifdef HAS_MAIN +/* +#if CHOICE==BN254_T + +const BIG TEST_Gx={0x18AFF11A,0xF2EF406,0xAF68220,0x171F2E27,0x6BA0959,0x124C50E0,0x450BE27,0x7003EA8,0x8A914}; +const BIG TEST_Gy={0x6E010F4,0xA71D07E,0x7ECADA8,0x8260E8E,0x1F79C328,0x17A09412,0xBFAE690,0x1C57CBD1,0x17DF54}; + +const BIG TEST_Pxa={0x1047D566,0xD83CD71,0x10322E9D,0x991FA93,0xA282C48,0x18AEBEC8,0xCB05850,0x13B4F669,0x21794A}; +const BIG TEST_Pxb={0x1E305936,0x16885BF1,0x327060,0xE26F794,0x1547D870,0x1963E5B2,0x1BEBB96C,0x988A33C,0x1A9B47}; +const BIG TEST_Pya={0x20FF876,0x4427E67,0x18732211,0xE88E45E,0x174D1A7E,0x17D877ED,0x343AB37,0x97EB453,0xB00D5}; +const BIG TEST_Pyb={0x1D746B7B,0x732F4C2,0x122A49B0,0x16267985,0x235DF56,0x10B1E4D,0x14D8F210,0x17A05C3E,0x5ECF8}; + +#endif + +#if CHOICE==BN254_T2 + +const BIG TEST_Gx={0x15488765,0x46790D7,0xD9900A,0x1DFB43F,0x9F2D307,0xC4724E8,0x5678E51,0x15C3E3A7,0x1BEC8E}; +const BIG TEST_Gy={0x3D3273C,0x1AFA5FF,0x1880A139,0xACD34DF,0x17493067,0x10FA4103,0x1D4C9766,0x1A73F3DB,0x2D148}; + +const BIG TEST_Pxa={0xF8DC275,0xAC27FA,0x11815151,0x152691C8,0x5CDEBF1,0x7D5A965,0x1BF70CE3,0x679A1C8,0xD62CF}; +const BIG TEST_Pxb={0x1D17D7A8,0x6B28DF4,0x174A0389,0xFE67E5F,0x1FA97A3C,0x7F5F473,0xFFB5146,0x4BC19A5,0x227010}; +const BIG TEST_Pya={0x16CC1F90,0x5284627,0x171B91AB,0x11F843B9,0x1D468755,0x67E279C,0x19FE0EF8,0x1A0CAA6B,0x1CC6CB}; +const BIG TEST_Pyb={0x1FF0CF2A,0xBC83255,0x6DD6EE8,0xB8B752F,0x13E484EC,0x1809BE81,0x1A648AA1,0x8CEF3F3,0x86EE}; + + +#endif + +#if CHOICE==BN254 + +const BIG TEST_Gx={0x14BEC4670E4EB7,0xEA2973860F6861,0x35C14B2FC3C28F,0x4402A0B63B9473,0x2074A81D}; +const BIG TEST_Gy={0xC284846631CBEB,0x34A6E8D871B3B,0x89FB94A82B2006,0x87B20038771FC,0x6A41108}; + +const BIG TEST_Pxa={0xE4A00F52183C77,0x554E02DF4F8354,0xB65EB5CF1C2F89,0x8B71A87BFCFC9,0x49EEDB1}; +const BIG TEST_Pxb={0xCFB8FA9AA8845D,0x8A9CC76D966697,0x185BA05BF5EC08,0x76140E87D97226,0x1FB93AB6}; +const BIG TEST_Pya={0x3644CC1EDF208A,0xA637FB3FF8E257,0x4453DA2BB9E686,0xD14AD3CDF6A1FE,0xCD04A1E}; +const BIG TEST_Pyb={0x71BD7630A43C14,0x1CAA9F14EA264E,0x3C3C2DFC765DEF,0xCF59D1A1A7D6EE,0x11FF7795}; + + +#endif +*/ +int main() +{ + int i; + char byt[32]; + csprng rng; + BIG xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r; + ECP2 P,G; + ECP Q,R; + FP12 g,gp; + FP4 t,c,cp,cpm1,cpm2; + FP2 x,y,X; + + + BIG_rcopy(a,CURVE_Fra); + BIG_rcopy(b,CURVE_Frb); + FP2_from_BIGs(&X,a,b); + + BIG_rcopy(xa,CURVE_Gx); + BIG_rcopy(ya,CURVE_Gy); + + ECP_set(&Q,xa,ya); + if (Q.inf) printf("Failed to set - point not on curve\n"); + else printf("G1 set success\n"); + + printf("Q= "); + ECP_output(&Q); + printf("\n"); + +// BIG_rcopy(r,CURVE_Order); BIG_dec(r,7); BIG_norm(r); + BIG_rcopy(xa,CURVE_Pxa); + BIG_rcopy(xb,CURVE_Pxb); + BIG_rcopy(ya,CURVE_Pya); + BIG_rcopy(yb,CURVE_Pyb); + + FP2_from_BIGs(&x,xa,xb); + FP2_from_BIGs(&y,ya,yb); + + ECP2_set(&P,&x,&y); + if (P.inf) printf("Failed to set - point not on curve\n"); + else printf("G2 set success\n"); + + printf("P= "); + ECP2_output(&P); + printf("\n"); + + for (i=0; i<1000; i++ ) + { + + PAIR_ate(&g,&P,&Q); + PAIR_fexp(&g); + +// PAIR_GTpow(&g,xa); + + } + printf("g= "); + FP12_output(&g); + printf("\n"); + +} + +#endif http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/rand.c ---------------------------------------------------------------------- diff --git a/version22/c/rand.c b/version22/c/rand.c new file mode 100644 index 0000000..4a2cd0a --- /dev/null +++ b/version22/c/rand.c @@ -0,0 +1,172 @@ +/* +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. +*/ + +/* + * Cryptographic strong random number generator + * + * Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers + * Slow - but secure + * + * See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification + */ +/* SU=m, m is Stack Usage */ + +#include "amcl.h" + +/* SU= 20 */ +static unsign32 sbrand(csprng *rng) +{ + /* Marsaglia & Zaman random number generator */ + int i,k; + unsign32 pdiff,t; + rng->rndptr++; + if (rng->rndptr<NK) return rng->ira[rng->rndptr]; + rng->rndptr=0; + for (i=0,k=NK-NJ; i<NK; i++,k++) + { + /* calculate next NK values */ + if (k==NK) k=0; + t=rng->ira[k]; + pdiff=t - rng->ira[i] - rng->borrow; + + if (pdiff<t) rng->borrow=0; + if (pdiff>t) rng->borrow=1; + rng->ira[i]=pdiff; + } + return rng->ira[0]; +} + +/* SU= 20 */ +static void sirand(csprng* rng,unsign32 seed) +{ + /* initialise random number system */ + /* modified so that a subsequent call "stirs" in another seed value */ + /* in this way as many seed bits as desired may be used */ + int i,in; + unsign32 t,m=1; + rng->borrow=0L; + rng->rndptr=0; + rng->ira[0]^=seed; + for (i=1; i<NK; i++) + { + /* fill initialisation vector */ + in=(NV*i)%NK; + rng->ira[in]^=m; /* note XOR */ + t=m; + m=seed-m; + seed=t; + } + for (i=0; i<10000; i++) sbrand(rng ); /* "warm-up" & stir the generator */ +} + +/* SU= 312 */ +static void fill_pool(csprng *rng) +{ + /* hash down output of RNG to re-fill the pool */ + int i; + hash256 sh; + HASH256_init(&sh); + for (i=0; i<128; i++) HASH256_process(&sh,sbrand(rng)); + HASH256_hash(&sh,rng->pool); + rng->pool_ptr=0; +} + +static unsign32 pack(const uchar *b) +{ + /* pack bytes into a 32-bit Word */ + return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0]; +} + +/* SU= 360 */ +/* Initialize RNG with some real entropy from some external source */ +void RAND_seed(csprng *rng,int rawlen,char *raw) +{ + /* initialise from at least 128 byte string of raw * + * random (keyboard?) input, and 32-bit time-of-day */ + int i; + char digest[32]; + uchar b[4]; + hash256 sh; + rng->pool_ptr=0; + for (i=0; i<NK; i++) rng->ira[i]=0; + if (rawlen>0) + { + HASH256_init(&sh); + for (i=0; i<rawlen; i++) + HASH256_process(&sh,raw[i]); + HASH256_hash(&sh,digest); + + /* initialise PRNG from distilled randomness */ + + for (i=0; i<8; i++) + { + b[0]=digest[4*i]; + b[1]=digest[4*i+1]; + b[2]=digest[4*i+2]; + b[3]=digest[4*i+3]; + // printf("%08x\n",pack(b)); + sirand(rng,pack(b)); + } + } + fill_pool(rng); +} + +/* Terminate and clean up */ +void RAND_clean(csprng *rng) +{ + /* kill internal state */ + int i; + rng->pool_ptr=rng->rndptr=0; + for (i=0; i<32; i++) rng->pool[i]=0; + for (i=0; i<NK; i++) rng->ira[i]=0; + rng->borrow=0; +} + +/* get random byte */ +/* SU= 8 */ +int RAND_byte(csprng *rng) +{ + int r; + r=rng->pool[rng->pool_ptr++]; + if (rng->pool_ptr>=32) fill_pool(rng); + return (r&0xff); +} + +/* test main program */ +/* +#include <stdio.h> +#include <string.h> + +void main() +{ + int i; + char raw[256]; + csprng rng; + + RAND_clean(&rng); + + + for (i=0;i<256;i++) raw[i]=(char)i; + RAND_seed(&rng,256,raw); + + for (i=0;i<1000;i++) + printf("%02x ",(unsigned char)RAND_byte(&rng)); +} + +*/ http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/randapi.c ---------------------------------------------------------------------- diff --git a/version22/c/randapi.c b/version22/c/randapi.c new file mode 100644 index 0000000..9b32efb --- /dev/null +++ b/version22/c/randapi.c @@ -0,0 +1,15 @@ +#include "randapi.h" + +/* Initialise a Cryptographically Strong Random Number Generator from + an octet of raw random data */ + +void CREATE_CSPRNG(csprng *RNG,octet *RAW) +{ + RAND_seed(RNG,RAW->len,RAW->val); +} + +void KILL_CSPRNG(csprng *RNG) +{ + RAND_clean(RNG); +} + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/randapi.h ---------------------------------------------------------------------- diff --git a/version22/c/randapi.h b/version22/c/randapi.h new file mode 100644 index 0000000..631499d --- /dev/null +++ b/version22/c/randapi.h @@ -0,0 +1,20 @@ +#ifndef RANDOM_H +#define RANDOM_H + +#include "amcl.h" + +/** @brief Initialise a random number generator + * + @param R is a pointer to a cryptographically secure random number generator + @param S is an input truly random seed value + */ +extern void CREATE_CSPRNG(csprng *R,octet *S); +/** @brief Kill a random number generator + * + Deletes all internal state + @param R is a pointer to a cryptographically secure random number generator + */ +extern void KILL_CSPRNG(csprng *R); + +#endif + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/c/readme.txt ---------------------------------------------------------------------- diff --git a/version22/c/readme.txt b/version22/c/readme.txt new file mode 100644 index 0000000..278770a --- /dev/null +++ b/version22/c/readme.txt @@ -0,0 +1,77 @@ +AMCL is very simple to build. + +The examples here are for GCC under Linux and Windows (using MINGW). + +First indicate your computer/compiler architecture by setting the wordlength +in arch.h + +Next - decide what you want to do. Edit amcl.h - note there is only +one area where USER CONFIGURABLE input is requested. + +Here choose your curve. + +Once this is done, build the library, and compile and link your program +with an API file and the ROM file rom.c that contains curve constants. + +Three example API files are provided, mpin.c which supports our M-Pin +(tm) protocol, ecdh.c which supports standard elliptic +curve key exchange, digital signature and public key crypto, and rsa.c +which supports the RSA method. The first +can be tested using the testmpin.c driver programs, the second can +be tested using testecdh.c, and the third can be tested using +testrsa.c + +In the ROM file you must provide the curve constants. Several examples +are provided there, and if you are willing to use one of these, simply +select your curve of CHOICE in amcl.h + +Example (1), in amcl.h choose + +#define CHOICE BN254 + +and + +#define CURVETYPE WEIERSTRASS + +Under windows run the batch file build_pair.bat to build the amcl.a library +and the testmpin.exe applications. + +For linux execute "bash build_pair" + +Example (2), in amcl.h choose + +#define CHOICE C25519 + +and + +#define CURVETYPE EDWARDS + +to select the Edwards curve ed25519. + +Under Windows run the batch file build_ec.bat to build the amcl.a library and +the testecdh.exe application. + +For Linux execute "bash build_ec" + + +To help generate the ROM constants for your own curve some MIRACL helper +programs are included. The programs bngen.cpp and blsgen.cpp generate ROM +data for a BN and BLS pairing friendly curves, and the program ecgen.cpp +generates ROM data for regular EC curves. + +The MIRACL based program check.cpp helps choose the best number base for +big number representation, given the word-length and the size of the modulus. + +The program bigtobig.cpp converts a big number to the AMCL +BIG format. + + +For quick jumpstart:- + +(Linux) +bash build_pair +./testmpin + +(Windows + MingW) +build_pair +testmpin
