blob: e1f3bceef605daf78e5cedd13c9085d2c5cf8657 [file] [log] [blame]
/*
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 "mpin192_ZZZ.h"
#define ROUNDUP(a,b) ((a)-1)/(b)+1
/* Special mpin hashing */
static void mpin_hash(int sha,FP8_YYY *f, ECP_ZZZ *P,octet *w)
{
int i;
BIG_XXX x,y;
char h[64];
hash256 sha256;
hash512 sha512;
char t[10*MODBYTES_XXX]; // to hold 10 BIGs
int hlen=sha;
FP_YYY_redc(x,&(f->a.a.a));
BIG_XXX_toBytes(&t[0],x);
FP_YYY_redc(x,&(f->a.a.b));
BIG_XXX_toBytes(&t[MODBYTES_XXX],x);
FP_YYY_redc(x,&(f->a.b.a));
BIG_XXX_toBytes(&t[2*MODBYTES_XXX],x);
FP_YYY_redc(x,&(f->a.b.b));
BIG_XXX_toBytes(&t[3*MODBYTES_XXX],x);
FP_YYY_redc(x,&(f->b.a.a));
BIG_XXX_toBytes(&t[4*MODBYTES_XXX],x);
FP_YYY_redc(x,&(f->b.a.b));
BIG_XXX_toBytes(&t[5*MODBYTES_XXX],x);
FP_YYY_redc(x,&(f->b.b.a));
BIG_XXX_toBytes(&t[6*MODBYTES_XXX],x);
FP_YYY_redc(x,&(f->b.b.b));
BIG_XXX_toBytes(&t[7*MODBYTES_XXX],x);
ECP_ZZZ_get(x,y,P);
BIG_XXX_toBytes(&t[8*MODBYTES_XXX],x);
BIG_XXX_toBytes(&t[9*MODBYTES_XXX],y);
OCT_empty(w);
switch (sha)
{
case SHA256:
HASH256_init(&sha256);
for (i=0; i<10*MODBYTES_XXX; i++) HASH256_process(&sha256,t[i]);
HASH256_hash(&sha256,h);
break;
case SHA384:
HASH384_init(&sha512);
for (i=0; i<10*MODBYTES_XXX; i++) HASH384_process(&sha512,t[i]);
HASH384_hash(&sha512,h);
break;
case SHA512:
HASH512_init(&sha512);
for (i=0; i<10*MODBYTES_XXX; i++) HASH512_process(&sha512,t[i]);
HASH512_hash(&sha512,h);
break;
}
OCT_jbytes(w,h,AESKEY_ZZZ);
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_ZZZ *P,BIG_XXX u,int cb)
{
BIG_XXX x,q;
BIG_XXX_rcopy(q,Modulus_YYY);
BIG_XXX_copy(x,u);
BIG_XXX_mod(x,q);
while (!ECP_ZZZ_setx(P,x,cb))
{
BIG_XXX_inc(x,1); BIG_XXX_norm(x);
}
}
/* returns u derived from P. Random value in range 1 to return value should then be added to u */
static int unmap(BIG_XXX u,int *cb,ECP_ZZZ *P)
{
int s,r=0;
BIG_XXX x;
s=ECP_ZZZ_get(x,x,P);
BIG_XXX_copy(u,x);
do
{
BIG_XXX_dec(u,1); BIG_XXX_norm(u);
r++;
}
while (!ECP_ZZZ_setx(P,u,s));
ECP_ZZZ_setx(P,x,s);
*cb=s;
return r;
}
/* 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_ZZZ_ENCODING(csprng *RNG,octet *E)
{
int rn,m,su,sv,res=0;
BIG_XXX q,u,v;
ECP_ZZZ P,W;
if (!ECP_ZZZ_fromOctet(&P,E)) res=MPIN_INVALID_POINT;
if (res==0)
{
BIG_XXX_rcopy(q,Modulus_YYY);
BIG_XXX_randomnum(u,q,RNG);
su=RAND_byte(RNG);
if (su<0) su=-su;
su%=2;
map(&W,u,su);
ECP_ZZZ_sub(&P,&W); //ECP_ZZZ_affine(&P);
rn=unmap(v,&sv,&P);
m=RAND_byte(RNG);
if (m<0) m=-m;
m%=rn;
BIG_XXX_inc(v,m+1);
E->val[0]=su+2*sv;
BIG_XXX_toBytes(&(E->val[1]),u);
BIG_XXX_toBytes(&(E->val[PFS_ZZZ+1]),v);
}
return res;
}
int MPIN_ZZZ_DECODING(octet *D)
{
int su,sv;
BIG_XXX u,v;
ECP_ZZZ P,W;
int res=0;
if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT;
if (res==0)
{
BIG_XXX_fromBytes(u,&(D->val[1]));
BIG_XXX_fromBytes(v,&(D->val[PFS_ZZZ+1]));
su=D->val[0]&1;
sv=(D->val[0]>>1)&1;
map(&W,u,su);
map(&P,v,sv);
ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
ECP_ZZZ_toOctet(D,&P,false);
}
return res;
}
/* R=R1+R2 in group G1 */
int MPIN_ZZZ_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
{
ECP_ZZZ P,T;
int res=0;
if (res==0)
{
if (!ECP_ZZZ_fromOctet(&P,R1)) res=MPIN_INVALID_POINT;
if (!ECP_ZZZ_fromOctet(&T,R2)) res=MPIN_INVALID_POINT;
}
if (res==0)
{
ECP_ZZZ_add(&P,&T); //ECP_ZZZ_affine(&P);
ECP_ZZZ_toOctet(R,&P,false);
}
return res;
}
/* W=W1+W2 in group G2 */
int MPIN_ZZZ_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
{
ECP4_ZZZ Q,T;
int res=0;
if (!ECP4_ZZZ_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT;
if (!ECP4_ZZZ_fromOctet(&T,W2)) res=MPIN_INVALID_POINT;
if (res==0)
{
ECP4_ZZZ_add(&Q,&T); //ECP4_ZZZ_affine(&Q);
ECP4_ZZZ_toOctet(W,&Q);
}
return res;
}
/* create random secret S */
int MPIN_ZZZ_RANDOM_GENERATE(csprng *RNG,octet* S)
{
BIG_XXX r,s;
BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
BIG_XXX_randomnum(s,r,RNG);
#ifdef AES_S
BIG_XXX_mod2m(s,2*AES_S);
#endif
BIG_XXX_toBytes(S->val,s);
S->len=MODBYTES_XXX;
return 0;
}
/* Extract PIN from TOKEN for identity CID */
int MPIN_ZZZ_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN)
{
pin%=MAXPIN;
return MPIN_ZZZ_EXTRACT_FACTOR(sha,CID,pin,PBLEN,TOKEN);
}
/* Extract a factor < 32 bits for identity CID */
int MPIN_ZZZ_EXTRACT_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
{
ECP_ZZZ P,R;
int res=0;
char h[MODBYTES_XXX];
octet H= {0,sizeof(h),h};
if (!ECP_ZZZ_fromOctet(&P,TOKEN)) res=MPIN_INVALID_POINT;
if (res==0)
{
mhashit(sha,-1,CID,&H);
ECP_ZZZ_mapit(&R,&H);
ECP_ZZZ_pinmul(&R,factor,facbits);
ECP_ZZZ_sub(&P,&R); //ECP_ZZZ_affine(&P);
ECP_ZZZ_toOctet(TOKEN,&P,false);
}
return res;
}
/* Extract a factor < 32 bits for identity CID */
int MPIN_ZZZ_RESTORE_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
{
ECP_ZZZ P,R;
int res=0;
char h[MODBYTES_XXX];
octet H= {0,sizeof(h),h};
if (!ECP_ZZZ_fromOctet(&P,TOKEN)) res=MPIN_INVALID_POINT;
if (res==0)
{
mhashit(sha,-1,CID,&H);
ECP_ZZZ_mapit(&R,&H);
ECP_ZZZ_pinmul(&R,factor,facbits);
ECP_ZZZ_add(&P,&R); //ECP_ZZZ_affine(&P);
ECP_ZZZ_toOctet(TOKEN,&P,false);
}
return res;
}
/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */
int MPIN_ZZZ_CLIENT_2(octet *X,octet *Y,octet *SEC)
{
BIG_XXX px,py,r;
ECP_ZZZ P;
int res=0;
BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
if (!ECP_ZZZ_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT;
if (res==0)
{
BIG_XXX_fromBytes(px,X->val);
BIG_XXX_fromBytes(py,Y->val);
BIG_XXX_add(px,px,py);
BIG_XXX_mod(px,r);
// BIG_XXX_sub(px,r,px);
PAIR_ZZZ_G1mul(&P,px);
ECP_ZZZ_neg(&P);
ECP_ZZZ_toOctet(SEC,&P,false);
}
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_ZZZ_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
{
ECP_ZZZ P;
BIG_XXX r,x;
int res=0;
if (RNG!=NULL)
{
BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
BIG_XXX_randomnum(x,r,RNG);
#ifdef AES_S
BIG_XXX_mod2m(x,2*AES_S);
#endif
X->len=MODBYTES_XXX;
BIG_XXX_toBytes(X->val,x);
}
else
BIG_XXX_fromBytes(x,X->val);
if (type==0)
{
if (!ECP_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
}
else
{
ECP_ZZZ_mapit(&P,G);
}
if (res==0)
{
PAIR_ZZZ_G1mul(&P,x);
ECP_ZZZ_toOctet(W,&P,false);
}
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_ZZZ_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
{
ECP4_ZZZ P;
BIG_XXX r,x;
int res=0;
BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
if (RNG!=NULL)
{
BIG_XXX_randomnum(x,r,RNG);
#ifdef AES_S
BIG_XXX_mod2m(x,2*AES_S);
#endif
X->len=MODBYTES_XXX;
BIG_XXX_toBytes(X->val,x);
}
else
{
BIG_XXX_fromBytes(x,X->val);
if (type==1) BIG_XXX_invmodp(x,x,r);
}
if (!ECP4_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
if (res==0)
{
PAIR_ZZZ_G2mul(&P,x);
ECP4_ZZZ_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_ZZZ_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST)
{
return MPIN_ZZZ_GET_G1_MULTIPLE(NULL,1,S,CID,CST);
}
/* Implement step 1 on client side of MPin protocol */
int MPIN_ZZZ_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_XXX r,x;
ECP_ZZZ P,T,W;
int res=0;
char h[MODBYTES_XXX];
octet H= {0,sizeof(h),h};
BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
if (RNG!=NULL)
{
BIG_XXX_randomnum(x,r,RNG);
#ifdef AES_S
BIG_XXX_mod2m(x,2*AES_S);
#endif
X->len=MODBYTES_XXX;
BIG_XXX_toBytes(X->val,x);
}
else
BIG_XXX_fromBytes(x,X->val);
mhashit(sha,-1,CLIENT_ID,&H);
ECP_ZZZ_mapit(&P,&H);
if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
if (res==0)
{
pin%=MAXPIN;
ECP_ZZZ_copy(&W,&P); // W=H(ID)
ECP_ZZZ_pinmul(&W,pin,PBLEN); // W=alpha.H(ID)
ECP_ZZZ_add(&T,&W); // T=Token+alpha.H(ID) = s.H(ID)
if (date)
{
if (PERMIT!=NULL)
{
if (!ECP_ZZZ_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT;
ECP_ZZZ_add(&T,&W); // SEC=s.H(ID)+s.H(T|ID)
}
mhashit(sha,date,&H,&H);
ECP_ZZZ_mapit(&W,&H);
if (xID!=NULL)
{
PAIR_ZZZ_G1mul(&P,x); // P=x.H(ID)
ECP_ZZZ_toOctet(xID,&P,false); // xID
PAIR_ZZZ_G1mul(&W,x); // W=x.H(T|ID)
ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
}
else
{
ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
PAIR_ZZZ_G1mul(&P,x);
}
if (xCID!=NULL) ECP_ZZZ_toOctet(xCID,&P,false); // U
}
else
{
if (xID!=NULL)
{
PAIR_ZZZ_G1mul(&P,x); // P=x.H(ID)
ECP_ZZZ_toOctet(xID,&P,false); // xID
}
}
}
if (res==0)
{
//ECP_ZZZ_affine(&T);
ECP_ZZZ_toOctet(SEC,&T,false); // V
}
return res;
}
/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SST)
{
BIG_XXX r,s;
ECP4_ZZZ Q;
int res=0;
BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
ECP4_ZZZ_generator(&Q);
if (res==0)
{
BIG_XXX_fromBytes(s,S->val);
PAIR_ZZZ_G2mul(&Q,s);
ECP4_ZZZ_toOctet(SST,&Q);
}
return res;
}
/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */
int MPIN_ZZZ_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT)
{
BIG_XXX s;
ECP_ZZZ P;
char h[MODBYTES_XXX];
octet H= {0,sizeof(h),h};
mhashit(sha,date,CID,&H);
ECP_ZZZ_mapit(&P,&H);
//printf("P= "); ECP_ZZZ_output(&P); printf("\n");
//exit(0);
BIG_XXX_fromBytes(s,S->val);
//printf("s= "); BIG_XXX_output(s); printf("\n");
PAIR_ZZZ_G1mul(&P,s);
//printf("OP= "); ECP_ZZZ_output(&P); printf("\n");
//
ECP_ZZZ_toOctet(CTT,&P,false);
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_ZZZ_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID)
{
char h[MODBYTES_XXX];
octet H= {0,sizeof(h),h};
ECP_ZZZ P,R;
BIG_XXX x;
#ifdef USE_ANONYMOUS
ECP_ZZZ_mapit(&P,CID);
#else
mhashit(sha,-1,CID,&H);
ECP_ZZZ_mapit(&P,&H);
#endif
ECP_ZZZ_toOctet(HID,&P,false); // new
if (date)
{
// if (HID!=NULL) ECP_ZZZ_toOctet(HID,&P,false);
#ifdef USE_ANONYMOUS
mhashit(sha,date,CID,&H);
#else
mhashit(sha,date,&H,&H);
#endif
ECP_ZZZ_mapit(&R,&H);
ECP_ZZZ_add(&P,&R); //ECP_ZZZ_affine(&P);
ECP_ZZZ_toOctet(HTID,&P,false);
}
//else ECP_ZZZ_toOctet(HID,&P,false);
}
/* Implement M-Pin on server side */
int MPIN_ZZZ_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F,octet *Pa)
{
BIG_XXX px,py,y;
FP24_YYY g;
ECP4_ZZZ Q,sQ;
ECP_ZZZ P,R;
int res=0;
ECP4_ZZZ_generator(&Q);
// key-escrow less scheme: use Pa instead of Q in pairing computation
// Q left for backward compatiblity
if (Pa!=NULL)
{
if (!ECP4_ZZZ_fromOctet(&Q, Pa)) res=MPIN_INVALID_POINT;
}
if (res==0)
{
if (!ECP4_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
}
if (res==0)
{
if (date)
{
//BIG_XXX_fromBytes(px,&(xCID->val[1]));
//BIG_XXX_fromBytes(py,&(xCID->val[PFS_ZZZ+1]));
if (!ECP_ZZZ_fromOctet(&R,xCID)) res=MPIN_INVALID_POINT;
}
else
{
//BIG_XXX_fromBytes(px,&(xID->val[1]));
//BIG_XXX_fromBytes(py,&(xID->val[PFS_ZZZ+1]));
if (!ECP_ZZZ_fromOctet(&R,xID)) res=MPIN_INVALID_POINT;
}
//if (!ECP_ZZZ_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT)
}
if (res==0)
{
BIG_XXX_fromBytes(y,Y->val);
if (date)
{
if (!ECP_ZZZ_fromOctet(&P,HTID)) res=MPIN_INVALID_POINT;
}
else
{
if (!ECP_ZZZ_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
}
}
if (res==0)
{
PAIR_ZZZ_G1mul(&P,y); // y(A+AT)
ECP_ZZZ_add(&P,&R); // x(A+AT)+y(A+T)
//ECP_ZZZ_affine(&P);
if (!ECP_ZZZ_fromOctet(&R,mSEC)) res=MPIN_INVALID_POINT; // V
}
if (res==0)
{
PAIR_ZZZ_double_ate(&g,&Q,&R,&sQ,&P);
PAIR_ZZZ_fexp(&g);
if (!FP24_YYY_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 */
FP24_YYY_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_ZZZ_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
if (!ECP_ZZZ_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U
if (res==0)
{
PAIR_ZZZ_G1mul(&P,y); // yA
ECP_ZZZ_add(&P,&R); // yA+xA
//ECP_ZZZ_affine(&P);
}
}
if (res==0)
{
PAIR_ZZZ_ate(&g,&Q,&P);
PAIR_ZZZ_fexp(&g);
FP24_YYY_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_ZZZ_KANGAROO(octet *E,octet *F)
{
int i,j,m,s,dn,dm,steps;
int distance[MR_TS];
FP24_YYY ge,gf,t,table[MR_TS];
int res=0;
// BIG_XXX w;
FP24_YYY_fromOctet(&ge,E);
FP24_YYY_fromOctet(&gf,F);
FP24_YYY_copy(&t,&gf);
for (s=1,m=0; m<MR_TS; m++)
{
distance[m]=s;
FP24_YYY_copy(&table[m],&t);
s*=2;
FP24_YYY_usqr(&t,&t);
FP24_YYY_reduce(&t);
}
FP24_YYY_one(&t);
for (dn=0,j=0; j<TRAP; j++)
{
//BIG_XXX_copy(w,t.a.a.a);
//FP_YYY_redc(w);
//i=BIG_XXX_lastbits(w,20)%MR_TS;
i=t.a.a.a.a.g[0]%MR_TS;
FP24_YYY_mul(&t,&table[i]);
FP24_YYY_reduce(&t);
dn+=distance[i];
}
FP24_YYY_conj(&gf,&t);
steps=0;
dm=0;
while (dm-dn<MAXPIN)
{
steps++;
if (steps>4*TRAP) break;
//BIG_XXX_copy(w,ge.a.a.a);
//FP_YYY_redc(w);
//i=BIG_XXX_lastbits(w,20)%MR_TS;
i=ge.a.a.a.a.g[0]%MR_TS;
FP24_YYY_mul(&ge,&table[i]);
FP24_YYY_reduce(&ge);
dm+=distance[i];
if (FP24_YYY_equals(&ge,&t))
{
res=dm-dn;
break;
}
if (FP24_YYY_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_ZZZ_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2)
{
ECP_ZZZ P,T;
ECP4_ZZZ Q;
FP24_YYY g;
BIG_XXX x;
int res=0;
if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
if (res==0)
{
ECP_ZZZ_mapit(&P,CID);
if (CP!=NULL)
{
if (!ECP4_ZZZ_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT;
}
else
{
ECP4_ZZZ_generator(&Q);
}
}
if (res==0)
{
PAIR_ZZZ_ate(&g,&Q,&T);
PAIR_ZZZ_fexp(&g);
FP24_YYY_toOctet(G1,&g);
if (G2!=NULL)
{
PAIR_ZZZ_ate(&g,&Q,&P);
PAIR_ZZZ_fexp(&g);
FP24_YYY_toOctet(G2,&g);
}
}
return res;
}
/* calculate common key on client side */
/* wCID = w.(A+AT) */
int MPIN_ZZZ_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK)
{
FP24_YYY g1,g2;
FP8_YYY c;//,cp,cpm1,cpm2;
ECP_ZZZ W;
int res=0;
BIG_XXX r,z,x,h;//q,m,a,b;
FP24_YYY_fromOctet(&g1,G1);
FP24_YYY_fromOctet(&g2,G2);
BIG_XXX_fromBytes(z,R->val);
BIG_XXX_fromBytes(x,X->val);
BIG_XXX_fromBytes(h,H->val);
if (!ECP_ZZZ_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT;
if (res==0)
{
BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
BIG_XXX_add(z,z,h); // new
BIG_XXX_mod(z,r);
FP24_YYY_pinpow(&g2,pin,PBLEN);
FP24_YYY_mul(&g1,&g2);
PAIR_ZZZ_G1mul(&W,x);
FP24_YYY_compow(&c,&g1,z,r);
mpin_hash(sha,&c,&W,CK);
}
return res;
}
/* calculate common key on server side */
/* Z=r.A - no time permits involved */
int MPIN_ZZZ_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK)
{
int res=0;
FP24_YYY g;
FP8_YYY c;
ECP_ZZZ R,U,A;
ECP4_ZZZ sQ;
BIG_XXX w,h;
if (!ECP4_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
if (!ECP_ZZZ_fromOctet(&R,Z)) res=MPIN_INVALID_POINT;
if (!ECP_ZZZ_fromOctet(&A,HID)) res=MPIN_INVALID_POINT;
// new
if (xCID!=NULL)
{
if (!ECP_ZZZ_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT;
}
else
{
if (!ECP_ZZZ_fromOctet(&U,xID)) res=MPIN_INVALID_POINT;
}
BIG_XXX_fromBytes(w,W->val);
BIG_XXX_fromBytes(h,H->val);
PAIR_ZZZ_ate(&g,&sQ,&A);
PAIR_ZZZ_fexp(&g);
if (res==0)
{
PAIR_ZZZ_G1mul(&A,h);
ECP_ZZZ_add(&R,&A); // new
//ECP_ZZZ_affine(&R);
PAIR_ZZZ_ate(&g,&sQ,&R);
PAIR_ZZZ_fexp(&g);
PAIR_ZZZ_G1mul(&U,w);
FP24_YYY_trace(&c,&g);
mpin_hash(sha,&c,&U,SK);
}
return res;
}
/* Generate Y = H(TimeValue, xCID/xID) */
void MPIN_ZZZ_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y)
{
BIG_XXX q,y;
char h[MODBYTES_XXX];
octet H= {0,sizeof(h),h};
mhashit(sha,TimeValue,xCID,&H);
BIG_XXX_fromBytes(y,H.val);
BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
BIG_XXX_mod(y,q);
BIG_XXX_toBytes(Y->val,y);
Y->len=PGS_ZZZ;
}
/* One pass MPIN Client */
int MPIN_ZZZ_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_ZZZ];
octet M= {0,sizeof(m),m};
octet *pID;
if (date == 0)
pID = U;
else
pID = UT;
rtn = MPIN_ZZZ_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_ZZZ_GET_Y(sha,TimeValue,&M,Y);
rtn = MPIN_ZZZ_CLIENT_2(X,Y,V);
if (rtn != 0)
return rtn;
return 0;
}
/* One pass MPIN Server */
int MPIN_ZZZ_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, octet *Pa)
{
int rtn=0;
char m[M_SIZE_ZZZ];
octet M= {0,sizeof(m),m};
octet *pU;
if (date == 0)
pU = U;
else
pU = UT;
MPIN_ZZZ_SERVER_1(sha,date,ID,HID,HTID);
OCT_joctet(&M,pU);
if (MESSAGE!=NULL)
{
OCT_joctet(&M,MESSAGE);
}
MPIN_ZZZ_GET_Y(sha,TimeValue,&M,Y);
rtn = MPIN_ZZZ_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F,Pa);
if (rtn != 0)
return rtn;
return 0;
}
int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa)
{
BIG_XXX z,r;
ECP4_ZZZ Q;
int res=0;
BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
if (R!=NULL)
{
BIG_XXX_randomnum(z,r,R);
Z->len=MODBYTES_XXX;
BIG_XXX_toBytes(Z->val,z);
}
else
BIG_XXX_fromBytes(z,Z->val);
BIG_XXX_invmodp(z,z,r);
ECP4_ZZZ_generator(&Q);
if (res==0)
{
PAIR_ZZZ_G2mul(&Q,z);
ECP4_ZZZ_toOctet(Pa,&Q);
}
return res;
}