blob: 45d9d61c9e387c10fd8106b7e97341a499989e51 [file] [log] [blame]
/***************************************************************************
*
Copyright 2013 CertiVox UK Ltd. *
*
This file is part of CertiVox SkyKey XT Crypto SDK. *
*
The CertiVox SkyKey XT Crypto SDK provides developers with an *
extensive and efficient set of cryptographic functions. *
For further information about its features and functionalities please *
refer to http://www.certivox.com *
*
* The CertiVox SkyKey XT Crypto SDK is free software: you can *
redistribute it and/or modify it under the terms of the *
GNU Affero General Public License as published by the *
Free Software Foundation, either version 3 of the License, *
or (at your option) any later version. *
*
* The CertiVox SkyKey XT Crypto SDK is distributed in the hope *
that it will be useful, but WITHOUT ANY WARRANTY; without even the *
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
See the GNU Affero General Public License for more details. *
*
* You should have received a copy of the GNU Affero General Public *
License along with CertiVox MIRACL Crypto SDK. *
If not, see <http://www.gnu.org/licenses/>. *
*
You can be released from the requirements of the license by purchasing *
a commercial license. Buying such a license is mandatory as soon as you *
develop commercial activities involving the CertiVox SkyKey XT Crypto SDK *
without disclosing the source code of your own applications, or shipping *
the CertiVox SkyKey XT Crypto SDK with a closed source product. *
*
***************************************************************************/
/*
* MIRACL SAKKE implementation file
* Author: M. Scott 2012
*/
#include "eccsi_c.h"
/* Calculate a public/private EC GF(p) key pair. W=S.g mod EC(p),
* where S is the secret key and W is the public key
* If RNG is NULL then the private key is provided externally in S
* otherwise it is generated randomly internally */
ECCSI_API int ECCSI_MASTER_KEY_PAIR_GENERATE(ecp_domain *DOM,csprng *RNG,octet* S,octet *W)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
#else
miracl *mr_mip=mirsys(DOM->nibbles,16);
#endif
big q,a,b,r,gx,gy,s,wx,wy;
epoint *G,*WP;
int err,res=0;
#ifndef MR_STATIC
char *mem=(char *)memalloc(_MIPP_ 9);
char *mem1=(char *)ecp_memalloc(_MIPP_ 2);
#else
char mem[MR_BIG_RESERVE(9)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(9));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECCSI_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
r=mirvar_mem(_MIPP_ mem, 3);
gx=mirvar_mem(_MIPP_ mem, 4);
gy=mirvar_mem(_MIPP_ mem, 5);
s=mirvar_mem(_MIPP_ mem, 6);
wx=mirvar_mem(_MIPP_ mem, 7);
wy=mirvar_mem(_MIPP_ mem, 8);
bytes_to_big(_MIPP_ FS,DOM->Q,q);
bytes_to_big(_MIPP_ FS,DOM->A,a);
bytes_to_big(_MIPP_ FS,DOM->B,b);
bytes_to_big(_MIPP_ FS,DOM->R,r);
bytes_to_big(_MIPP_ FS,DOM->Gx,gx);
bytes_to_big(_MIPP_ FS,DOM->Gy,gy);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
if (!epoint_set(_MIPP_ gx,gy,0,G)) res=MR_ERR_BAD_PARAMETERS;
}
if (res==0)
{
if (RNG!=NULL)
strong_bigrand(_MIPP_ RNG,r,s);
else
{
bytes_to_big(_MIPP_ S->len,S->val,s);
divide(_MIPP_ s,r,r);
}
ecurve_mult(_MIPP_ s,G,WP);
epoint_get(_MIPP_ WP,wx,wy);
if (RNG!=NULL) S->len=big_to_bytes(_MIPP_ 0,s,S->val,FALSE);
W->len=2*FS+1; W->val[0]=4;
big_to_bytes(_MIPP_ FS,wx,&(W->val[1]),TRUE);
big_to_bytes(_MIPP_ FS,wy,&(W->val[FS+1]),TRUE);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,9);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(9));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return ECCSI_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return ECCSI_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
ECCSI_API int ECCSI_USER_KEY_PAIR_GENERATE(ecp_domain *DOM,csprng *RNG,octet* V,octet *ID,octet *KSAK,octet *KPAK,octet *SSK,octet *PVT)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
#else
miracl *mr_mip=mirsys(DOM->nibbles,16);
#endif
int i;
char hh[HASH_BYTES];
HASHFUNC SHA;
big q,a,b,r,gx,gy,v,wx,wy,hs;
epoint *G,*WP;
int err,res=0;
#ifndef MR_STATIC
char *mem=(char *)memalloc(_MIPP_ 10);
char *mem1=(char *)ecp_memalloc(_MIPP_ 2);
#else
char mem[MR_BIG_RESERVE(10)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECCSI_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
r=mirvar_mem(_MIPP_ mem, 3);
gx=mirvar_mem(_MIPP_ mem, 4);
gy=mirvar_mem(_MIPP_ mem, 5);
v=mirvar_mem(_MIPP_ mem, 6);
wx=mirvar_mem(_MIPP_ mem, 7);
wy=mirvar_mem(_MIPP_ mem, 8);
hs=mirvar_mem(_MIPP_ mem, 9);
bytes_to_big(_MIPP_ FS,DOM->Q,q);
bytes_to_big(_MIPP_ FS,DOM->A,a);
bytes_to_big(_MIPP_ FS,DOM->B,b);
bytes_to_big(_MIPP_ FS,DOM->R,r);
bytes_to_big(_MIPP_ FS,DOM->Gx,gx);
bytes_to_big(_MIPP_ FS,DOM->Gy,gy);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
if (!epoint_set(_MIPP_ gx,gy,0,G)) res=MR_ERR_BAD_PARAMETERS;
}
if (res==0)
{
if (RNG!=NULL)
strong_bigrand(_MIPP_ RNG,r,v);
else
{
bytes_to_big(_MIPP_ V->len,V->val,v);
divide(_MIPP_ v,r,r);
}
ecurve_mult(_MIPP_ v,G,WP);
epoint_get(_MIPP_ WP,wx,wy);
if (RNG!=NULL) V->len=big_to_bytes(_MIPP_ 0,v,V->val,FALSE);
PVT->len=2*FS+1; PVT->val[0]=4;
big_to_bytes(_MIPP_ FS,wx,&(PVT->val[1]),TRUE);
big_to_bytes(_MIPP_ FS,wy,&(PVT->val[FS+1]),TRUE);
SHS_INIT(&SHA);
/* first hash G */
SHS_PROCESS(&SHA,0x04);
for (i=0;i<FS;i++) SHS_PROCESS(&SHA,DOM->Gx[i]);
for (i=0;i<FS;i++) SHS_PROCESS(&SHA,DOM->Gy[i]);
/* then KPAK, ID and PVT */
for (i=0;i<KPAK->len;i++) SHS_PROCESS(&SHA,KPAK->val[i]);
for (i=0;i<ID->len;i++) SHS_PROCESS(&SHA,ID->val[i]);
for (i=0;i<PVT->len;i++) SHS_PROCESS(&SHA,PVT->val[i]);
SHS_HASH(&SHA,hh);
bytes_to_big(_MIPP_ HASH_BYTES,hh,hs);
bytes_to_big(_MIPP_ KSAK->len,KSAK->val,wx);
mad(_MIPP_ hs,v,wx,r,r,wy);
SSK->len=big_to_bytes(_MIPP_ FS,wy,SSK->val,TRUE);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return ECCSI_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return ECCSI_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
ECCSI_API int ECCSI_USER_KEY_PAIR_VALIDATE(ecp_domain *DOM,octet *ID,octet *KPAK,octet *HS,octet *SSK,octet *PVT)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
#else
miracl *mr_mip=mirsys(DOM->nibbles,16);
#endif
int i;
char hh[HASH_BYTES];
HASHFUNC SHA;
big q,a,b,r,gx,gy,wx,wy,hs;
epoint *G,*WP;
int err,res=0;
#ifndef MR_STATIC
char *mem=(char *)memalloc(_MIPP_ 9);
char *mem1=(char *)ecp_memalloc(_MIPP_ 2);
#else
char mem[MR_BIG_RESERVE(9)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(9));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECCSI_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
r=mirvar_mem(_MIPP_ mem, 3);
gx=mirvar_mem(_MIPP_ mem, 4);
gy=mirvar_mem(_MIPP_ mem, 5);
wx=mirvar_mem(_MIPP_ mem, 6);
wy=mirvar_mem(_MIPP_ mem, 7);
hs=mirvar_mem(_MIPP_ mem, 8);
bytes_to_big(_MIPP_ FS,DOM->Q,q);
bytes_to_big(_MIPP_ FS,DOM->A,a);
bytes_to_big(_MIPP_ FS,DOM->B,b);
bytes_to_big(_MIPP_ FS,DOM->R,r);
bytes_to_big(_MIPP_ FS,DOM->Gx,gx);
bytes_to_big(_MIPP_ FS,DOM->Gy,gy);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
if (!epoint_set(_MIPP_ gx,gy,0,G)) res=MR_ERR_BAD_PARAMETERS;
}
if (res==0)
{
bytes_to_big(_MIPP_ FS,&(PVT->val[1]),wx);
bytes_to_big(_MIPP_ FS,&(PVT->val[FS+1]),wy);
if (!epoint_set(_MIPP_ wx,wy,0,WP)) res=ECCSI_INVALID_PUBLIC_KEY;
}
if (res==0)
{
SHS_INIT(&SHA);
/* first hash G */
SHS_PROCESS(&SHA,0x04);
for (i=0;i<FS;i++) SHS_PROCESS(&SHA,DOM->Gx[i]);
for (i=0;i<FS;i++) SHS_PROCESS(&SHA,DOM->Gy[i]);
/* then KPAK, ID and PVT */
for (i=0;i<KPAK->len;i++) SHS_PROCESS(&SHA,KPAK->val[i]);
for (i=0;i<ID->len;i++) SHS_PROCESS(&SHA,ID->val[i]);
for (i=0;i<PVT->len;i++) SHS_PROCESS(&SHA,PVT->val[i]);
SHS_HASH(&SHA,hh);
bytes_to_big(_MIPP_ HASH_BYTES,hh,hs);
HS->len=HASH_BYTES; for (i=0;i<HASH_BYTES;i++) HS->val[i]=hh[i];
bytes_to_big(_MIPP_ SSK->len,SSK->val,wx);
ecurve_mult(_MIPP_ wx,G,G);
ecurve_mult(_MIPP_ hs,WP,WP);
ecurve_sub(_MIPP_ WP,G);
bytes_to_big(_MIPP_ FS,&(KPAK->val[1]),wx);
bytes_to_big(_MIPP_ FS,&(KPAK->val[FS+1]),wy);
epoint_set(_MIPP_ wx,wy,0,WP);
if (!epoint_comp(_MIPP_ G,WP)) res=ECCSI_INVALID;
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,9);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(9));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return ECCSI_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return ECCSI_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
ECCSI_API int ECCSI_SIGN(ecp_domain *DOM,csprng *RNG,octet* J,octet *M,octet *ID,octet *KPAK,octet *HS,octet *SSK,octet *PVT,octet *SIG)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
#else
miracl *mr_mip=mirsys(DOM->nibbles,16);
#endif
int i,m;
char hh[HASH_BYTES];
char IOBUFF[FS];
HASHFUNC SHA;
big q,a,b,r,gx,gy,wx,wy,he,j;
epoint *G,*WP;
int err,res=0;
#ifndef MR_STATIC
char *mem=(char *)memalloc(_MIPP_ 10);
char *mem1=(char *)ecp_memalloc(_MIPP_ 2);
#else
char mem[MR_BIG_RESERVE(10)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECCSI_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
r=mirvar_mem(_MIPP_ mem, 3);
gx=mirvar_mem(_MIPP_ mem, 4);
gy=mirvar_mem(_MIPP_ mem, 5);
j=mirvar_mem(_MIPP_ mem, 6);
wx=mirvar_mem(_MIPP_ mem, 7);
wy=mirvar_mem(_MIPP_ mem, 8);
he=mirvar_mem(_MIPP_ mem, 9);
bytes_to_big(_MIPP_ FS,DOM->Q,q);
bytes_to_big(_MIPP_ FS,DOM->A,a);
bytes_to_big(_MIPP_ FS,DOM->B,b);
bytes_to_big(_MIPP_ FS,DOM->R,r);
bytes_to_big(_MIPP_ FS,DOM->Gx,gx);
bytes_to_big(_MIPP_ FS,DOM->Gy,gy);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
if (!epoint_set(_MIPP_ gx,gy,0,G)) res=MR_ERR_BAD_PARAMETERS;
}
if (res==0)
{
if (RNG!=NULL)
strong_bigrand(_MIPP_ RNG,r,j);
else
{
bytes_to_big(_MIPP_ J->len,J->val,j);
divide(_MIPP_ j,r,r);
}
ecurve_mult(_MIPP_ j,G,WP);
epoint_get(_MIPP_ WP,wx,wy);
bytes_to_big(_MIPP_ SSK->len,SSK->val,wy);
big_to_bytes(_MIPP_ FS,wx,IOBUFF,TRUE); /* r */
SHS_INIT(&SHA);
/* first hash HS */
for (i=0;i<HS->len;i++) SHS_PROCESS(&SHA,HS->val[i]);
/* then r */
for (i=0;i<FS;i++) SHS_PROCESS(&SHA,IOBUFF[i]);
/* finally M.. */
for (i=0;i<M->len;i++) SHS_PROCESS(&SHA,M->val[i]);
SHS_HASH(&SHA,hh);
bytes_to_big(_MIPP_ HASH_BYTES,hh,he);
mad(_MIPP_ wx,wy,he,r,r,wy);
invmodp(_MIPP_ wy,r,wy);
mad(_MIPP_ wy,j,j,r,r,wy); /* s' */
if (logb2(_MIPP_ wx)>FS*8) subtract(_MIPP_ r,wy,wy); /* s */
SIG->len=4*FS+1;
/* SIG = r || s || PVT */
for (i=m=0;i<FS;i++) SIG->val[m++]=IOBUFF[i];
big_to_bytes(_MIPP_ FS,wy,IOBUFF,TRUE);
for (i=0;i<FS;i++) SIG->val[m++]=IOBUFF[i];
for (i=0;i<PVT->len;i++) SIG->val[m++]=PVT->val[i];
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return ECCSI_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return ECCSI_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
ECCSI_API int ECCSI_VERIFY(ecp_domain *DOM,octet *M,octet *ID,octet *KPAK,octet *SIG)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->nibbles,16);
#else
miracl *mr_mip=mirsys(DOM->nibbles,16);
#endif
int i;
char hh[HASH_BYTES];
HASHFUNC SHA;
big q,a,b,r,gx,gy,wx,wy,he,hs;
epoint *G,*WP;
int err,res=0;
#ifndef MR_STATIC
char *mem=(char *)memalloc(_MIPP_ 10);
char *mem1=(char *)ecp_memalloc(_MIPP_ 2);
#else
char mem[MR_BIG_RESERVE(10)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL || mem==NULL || mem1==NULL) res= ECCSI_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
r=mirvar_mem(_MIPP_ mem, 3);
gx=mirvar_mem(_MIPP_ mem, 4);
gy=mirvar_mem(_MIPP_ mem, 5);
hs=mirvar_mem(_MIPP_ mem, 6);
wx=mirvar_mem(_MIPP_ mem, 7);
wy=mirvar_mem(_MIPP_ mem, 8);
he=mirvar_mem(_MIPP_ mem, 9);
bytes_to_big(_MIPP_ FS,DOM->Q,q);
bytes_to_big(_MIPP_ FS,DOM->A,a);
bytes_to_big(_MIPP_ FS,DOM->B,b);
bytes_to_big(_MIPP_ FS,DOM->R,r);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
/* extract PVT from signature */
bytes_to_big(_MIPP_ FS,&(SIG->val[2*FS+1]),wx);
bytes_to_big(_MIPP_ FS,&(SIG->val[3*FS+1]),wy);
if (!epoint_set(_MIPP_ wx,wy,0,WP)) res=ECCSI_INVALID_PUBLIC_KEY;
}
if (res==0)
{
SHS_INIT(&SHA);
/* first hash G */
SHS_PROCESS(&SHA,0x04);
for (i=0;i<FS;i++) SHS_PROCESS(&SHA,DOM->Gx[i]);
for (i=0;i<FS;i++) SHS_PROCESS(&SHA,DOM->Gy[i]);
/* then KPAK, ID and PVT */
for (i=0;i<KPAK->len;i++) SHS_PROCESS(&SHA,KPAK->val[i]);
for (i=0;i<ID->len;i++) SHS_PROCESS(&SHA,ID->val[i]);
for (i=0;i<2*FS+1;i++) SHS_PROCESS(&SHA,SIG->val[2*FS+i]);
SHS_HASH(&SHA,hh);
bytes_to_big(_MIPP_ HASH_BYTES,hh,hs);
/* extract signature */
bytes_to_big(_MIPP_ FS,&SIG->val[0],wx); /* get r */
bytes_to_big(_MIPP_ FS,&SIG->val[FS],wy); /* get s */
SHS_INIT(&SHA);
/* first hash HS */
for (i=0;i<FS;i++) SHS_PROCESS(&SHA,hh[i]);
/* then r */
for (i=0;i<FS;i++) SHS_PROCESS(&SHA,SIG->val[i]);
/* finally M.. */
for (i=0;i<M->len;i++) SHS_PROCESS(&SHA,M->val[i]);
SHS_HASH(&SHA,hh);
bytes_to_big(_MIPP_ HASH_BYTES,hh,he);
ecurve_mult(_MIPP_ hs,WP,WP);
bytes_to_big(_MIPP_ FS,&(KPAK->val[1]),gx);
bytes_to_big(_MIPP_ FS,&(KPAK->val[FS+1]),gy);
if (!epoint_set(_MIPP_ gx,gy,0,G)) res=ECCSI_INVALID_PUBLIC_KEY;
}
if (res==0)
{
ecurve_add(_MIPP_ G,WP); /* Y */
bytes_to_big(_MIPP_ FS,DOM->Gx,gx);
bytes_to_big(_MIPP_ FS,DOM->Gy,gy);
if (!epoint_set(_MIPP_ gx,gy,0,G)) res=MR_ERR_BAD_PARAMETERS;
}
if (res==0)
{
mad(_MIPP_ wx,wy,wx,r,r,hs);
mad(_MIPP_ wy,he,wy,r,r,wy);
ecurve_mult2(_MIPP_ hs,WP,wy,G,G);
epoint_get(_MIPP_ G,gx,gy);
if (mr_compare(gx,wx)!=0) res=ECCSI_INVALID;
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return ECCSI_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return ECCSI_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}